Lex Yacc (四) 实际应用全代码

修改后的实际应用全代码 草木瓜(七) 精读 源代码有百度云存盘

  • 复杂的逻辑判断简化成程序判断语句,可便于应用的扩展和维护,也极大增强了代码的可读性。
  • 我们对整体文件划分如下:
  • tree.l
  • tree.y
  • parser.h #内部编译使用的头文件
  • parser.c #内部编译的主函数
  • compile.h #内外部交互的头文件
  • main.c #外部程序

修改说明

    1.将内部使用变量,函数,结构体和宏定义集中到parser.h
    2.将yyparser的输入进行重定义,见#undef YY_INPUT部分
    3.提供一个回调函数接口 extern void (* G_LoadVar)(char *, float *); /* 函数指针 */
    4.内部创建可供外部调用的函数接口,FormulaParser FormulaVarGet
    5.提供一个内外部交互的定义文件compile.h,暂时的内容只是保持数组大小一致性。
    6.外部程序通过输入文件进行编译处理
  • 这样在外部程序main.c,直接可以实现公式编译和变量访问控制。
  • 生成静态库文件:
  • bison -d tree.y
  • lex tree.l
  • gcc -g -c lex.yy.c tree.tab.c parser.c 有Waring,忽略之 -c 只编译不链接
  • ar -rl compile.a *.o
  • 使用静态库文件编译外部程序:
  • gcc -g -o lw main.c compile.a
  • 运行编译显示结果:
  • ./lw input
    1
    Ret:0
    i:1
  • 只要参数中有-c,总是生成目标文件.o;
  • 只要参数中无-c而只有-o,则总是生成执行文件。
  • ar 命令维护链接编辑器使用的索引库。ar 命令将一个或多个指定的文件并入单个写成 ar 压缩文档格式的压缩文档文件。当 ar 命令创建库时,它创建可传输格式的报头;当它创建或更新库时,它重建符号表。有关格式和索引压缩文档和符号表的结构的信息
  • 在企业的应用中,本示例提供的功能还略显浅薄,主要有如下一些缺点:
    1.目前仅支持浮点整型,不支持字符型
    2.不支持switch分支结构
    3.不支持return,break,goto,continue等跳转语句
  • 这些用目前的语法树也不是不能实现,不过语法树需要做大量的递归操作,在效率上存在一些问题。
  • 后面的系列文章中会逐渐引入堆栈来处理语法编译的问题,也可能会对现有的语法树做些优化。Lex和Yacc系列到现在都是在Linux下面说事,我们也不能忽略Windows下的情况。诸如此类,只有花时间慢慢琢磨了。

input内容:

i=i+1;print(i);

tree.l

%{
#include <stdlib.h>
#include "parser.h"
#include "tree.tab.h"
struct VarDefine G_Def[MAX_DEFS];             /* 存储的变量数组 */
char G_sBuff[MAX_BUFF_ROWS][MAX_BUFF_COLS];   /* 存储分析语句 */
int G_iBuffRowCount = 0;     /* 当前语句行数 */
int G_iBuffColCount = 0;     /* 当前语句列数 */
%}
/* 使用代变量表示任意字符 */
any .
%%
#{any}*[\n] {
    add_buff(yytext);
    G_iBuffColCount = 0;
    G_iBuffRowCount++;
} /* 单行注释 */
[\n] {
    G_iBuffColCount = 0;
    G_iBuffRowCount++;
} /* 回车 */
"for"   {
    yylval.index = FOR - USER_DEF_NUM;
    G_Def[yylval.index].name = "for";
    add_buff(yytext);
    return FOR;
}
"while" {
    yylval.index = WHILE - USER_DEF_NUM;
    G_Def[yylval.index].name = "while";
    add_buff(yytext);
    return WHILE;
}
"if"    {
    yylval.index = IF - USER_DEF_NUM;
    G_Def[yylval.index].name = "if";
    add_buff(yytext);
    return IF;
}
"else"  {
    yylval.index = ELSE - USER_DEF_NUM;
    G_Def[yylval.index].name = "else";
    add_buff(yytext);
    return ELSE;
}
"print" {
    yylval.index = PRINT - USER_DEF_NUM ;
    G_Def[yylval.index].name = "print";
    add_buff(yytext);
    return PRINT;
}
[a-zA-Z][a-zA-Z0-9]* {
    add_var(yytext);
    yylval.index = G_iVarCurIndex;
    add_buff(yytext);
    return VARIABLE;
}
[0-9]+ {
    yylval.val = atof(yytext);
    add_buff(yytext);
    return NUMBER;
}
[0-9]*\.[0-9]+ {
    yylval.val = atof(yytext);
    add_buff(yytext);
    return NUMBER;
}
"++" { yylval.index = ADD_T - USER_DEF_NUM; G_Def[yylval.index].name = "++"; G_Def[yylval.index + 1].name = "++";  add_buff(yytext); return ADD_T; }
"--" { yylval.index = MUS_T - USER_DEF_NUM; G_Def[yylval.index].name = "--"; G_Def[yylval.index + 1].name = "++";  add_buff(yytext); return MUS_T; }
">=" { yylval.index = GE - USER_DEF_NUM;  G_Def[yylval.index].name = ">=";  add_buff(yytext); return GE;}
"<=" { yylval.index = LE - USER_DEF_NUM;  G_Def[yylval.index].name = "<=";  add_buff(yytext); return LE;}
"==" { yylval.index = EQ - USER_DEF_NUM;  G_Def[yylval.index].name = "==";  add_buff(yytext); return EQ;}
"!=" { yylval.index = NE - USER_DEF_NUM;  G_Def[yylval.index].name = "!=";  add_buff(yytext); return NE;}
"&&" { yylval.index = AND - USER_DEF_NUM; G_Def[yylval.index].name = "&&";  add_buff(yytext); return AND;}
"||" { yylval.index = OR - USER_DEF_NUM;  G_Def[yylval.index].name = "||";  add_buff(yytext); return OR; }
[()<>=+\-*/;{}.] {
    yylval.index = *yytext;  /* 存储运算符 */
    add_buff(yytext);
    return *yytext;
}
[\t]    { add_buff(yytext); } /* 去除TAB */
[ ]     { add_buff(yytext); }  /* 去除空格 */
{any}   { printf("Ignore Unknow Symbol:[%s]\n", yytext); }
%%
void add_buff(char * buff) {
    strcat(G_sBuff[G_iBuffRowCount], buff);
    G_iBuffColCount = G_iBuffColCount + strlen(buff);
}
int yywrap(void) {
    return 1;
}

tree.y

%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "parser.h"
#include "compile.h"
int G_iVarMaxIndex = 0;  /* 变量最大个数 */
int G_iVarCurIndex = -1; /* 变量当前索引 */
struct VarIndex G_Var[MAX_VARS];  /* 变量内存数组 */
char G_sFormula[MAX_FORMULA_LEN];  /* 全局变量,存储公式内容 */
int  G_iFormulaPos = 0;                /* 全局变量,存储公式当前的处理位置 */
void (* G_LoadVar)(char *, float *);
%}
%union {
    float val; /* 变量值 */
    int index; /* 变量数组索引 */
    Node *node; /* 结点地址 */
};
%token <val> NUMBER
%token <index> VARIABLE
%token PRINT
%token FOR WHILE
%nonassoc IF
%nonassoc ELSE
%left AND OR
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%left ADD_T ADD_TT MUS_T MUS_TT
%nonassoc UMINUS
%type <node> stmt stmt_list expr_set expr_setself expr_comp expr
%%
program:
function {}
;
function:
function stmt { NodeExecute($2); NodeFree($2); }
| /* NULL */
;
stmt:
';'                 {
    $$ = opr(';', 2, NULL, NULL); debug_vsp(yyval, ";", yyvsp, "0");
}
| expr_set ';'      {
    $$ = $1; debug_vsp(yyval, "es;", yyvsp, "01");
}
| PRINT expr ';'    {
    $$ = opr(PRINT, 1, $2); debug_vsp(yyval, "p(e);", yyvsp, "401");
}
| PRINT expr_set ';'    {
    $$ = opr(PRINT, 1, $2); debug_vsp(yyval, "p(es);", yyvsp, "401");
}
| FOR '(' expr_set ';' expr_comp ';' expr_set ')' stmt {
    $$ = opr(FOR, 4, $3, $5, $7, $9); debug_vsp(yyval, "for(es;ec;es) st", yyvsp, "410101010");
}
| WHILE '(' expr_comp ')' stmt       {
    $$ = opr(WHILE, 2, $3, $5); debug_vsp(yyval, "while(ec) st", yyvsp, "41010");
}
| IF '(' expr_comp ')' stmt %prec IF {
    $$ = opr(IF, 2, $3, $5);    debug_vsp(yyval, "if(ec) st", yyvsp, "41010");
}
| IF '(' expr_comp ')' stmt ELSE stmt %prec ELSE       {
    $$ = opr(IF, 3, $3, $5, $7);      debug_vsp(yyval, "if(ec)else st", yyvsp, "4101040");
}
| '{' stmt_list '}' {
    $$ = $2; debug_vsp(yyval, "{stl}", yyvsp, "101");
}
;
stmt_list:
stmt                {
    $$ = $1;  debug_vsp(yyval, "st", yyvsp, "0");
}
| stmt_list stmt  {
    $$ = opr(';', 2, $1, $2); debug_vsp(yyval, "stl st", yyvsp, "00");
}
;
expr_set:
VARIABLE '=' expr {
    $$ = opr('=', 2, set_index($1), $3); debug_vsp(yyval, "v=e", yyvsp, "210");
}
| VARIABLE '=' expr_setself {
    $$ = opr('=', 2, set_index($1), $3); debug_vsp(yyval, "v=ess", yyvsp, "210");
}
| expr_setself
;
expr_setself:
ADD_T VARIABLE  {
    $$ = opr(ADD_T, 1, set_index($2));  debug_vsp(yyval, "++v", yyvsp, "42");
}
| MUS_T VARIABLE  {
    $$ = opr(MUS_T, 1, set_index($2));  debug_vsp(yyval, "--v", yyvsp, "42");
}
| VARIABLE ADD_T  {
    $$ = opr(ADD_TT, 1, set_index($1));  debug_vsp(yyval, "v++", yyvsp, "24");
}
| VARIABLE MUS_T  {
    $$ = opr(MUS_TT, 1, set_index($1));  debug_vsp(yyval, "v--", yyvsp, "24");
}
| '(' expr_setself ')' {
    $$ = $2; debug_vsp(yyval, "(ess)", yyvsp, "101");
}
;

expr_comp:
expr '<' expr   {
    $$ = opr('<', 2, $1, $3); debug_vsp(yyval, "e<e", yyvsp, "010");    }
| expr '>' expr   {
    $$ = opr('>', 2, $1, $3); debug_vsp(yyval, "e>e", yyvsp, "010");    }
| expr GE expr    {
    $$ = opr(GE, 2, $1, $3);  debug_vsp(yyval, "e>=e", yyvsp, "040");   }
| expr LE expr    {
    $$ = opr(LE, 2, $1, $3);  debug_vsp(yyval, "e<=e", yyvsp, "040");   }
| expr NE expr    {
    $$ = opr(NE, 2, $1, $3);  debug_vsp(yyval, "e!=e", yyvsp, "040");   }
| expr EQ expr    {
    $$ = opr(EQ, 2, $1, $3);  debug_vsp(yyval, "e==e", yyvsp, "040");   }
| expr_comp AND expr_comp {
    $$ = opr(AND, 2, $1, $3); debug_vsp(yyval, "ec&&ec", yyvsp, "040"); }
| expr_comp OR expr_comp  {
    $$ = opr(OR, 2, $1, $3);  debug_vsp(yyval, "ec||ec", yyvsp, "040"); }
| '(' expr_comp ')'       {
    $$ = $2;                  debug_vsp(yyval, "(ec)", yyvsp, "101");
}
;
expr:
NUMBER            {
    $$ = set_content($1);      debug_vsp(yyval, "f", yyvsp, "3");
}
| VARIABLE        {
    $$ = set_index($1);        debug_vsp(yyval, "v", yyvsp, "2");
}
| '-' NUMBER %prec UMINUS {
    $$ = set_content(-$2);   debug_vsp(yyval, "-e", yyvsp, "13");
}
| expr '+' expr   {
    $$ = opr('+', 2, $1, $3);  debug_vsp(yyval, "e+e", yyvsp, "010");
}
| expr '-' expr   {
    $$ = opr('-', 2, $1, $3);  debug_vsp(yyval, "e-e", yyvsp, "010");
}
| expr '*' expr   {
    $$ = opr('*', 2, $1, $3);  debug_vsp(yyval, "e*e", yyvsp, "010");
}
| expr '/' expr   {
    $$ = opr('/', 2, $1, $3);  debug_vsp(yyval, "e/e", yyvsp, "010");
}
| '(' expr ')'    {
    $$ = $2;                   debug_vsp(yyval, "(e)", yyvsp, "101");
}
;
%%
#define SIZE_OF_NODE ((char *)&p->content - (char *)p)
Node *set_content(float value) {
    Node *p;
    size_t sizeNode;
    /* 分配结点空间 */
    sizeNode = SIZE_OF_NODE + sizeof(float);
    if ((p = malloc(sizeNode)) == NULL)
        yyerror("out of memory");
    /* 复制内容 */
    p->type = TYPE_CONTENT;
    p->content = value;
    return p;

}
Node *set_index(int value) {
    Node *p;
    size_t sizeNode;
    /* 分配结点空间 */
    sizeNode = SIZE_OF_NODE + sizeof(int);
    if ((p = malloc(sizeNode)) == NULL)
        yyerror("out of memory");
    /* 复制内容 */
    p->type = TYPE_INDEX;
    p->index = value;
    return p;
}
Node *opr(int name, int num, ...) {
    va_list valist;
    Node *p;
    size_t sizeNode;
    int i;
    /* 分配结点空间 */
    sizeNode = SIZE_OF_NODE + sizeof(OpNode) + (num - 1) * sizeof(Node*);
    if ((p = malloc(sizeNode)) == NULL)
        yyerror("out of memory");
    /* 复制内容 */
    p->type = TYPE_OP;
    p->op.name = name;
    p->op.num = num;
    va_start(valist, num);
    for (i = 0; i < num; i++)
        p->op.node[i] = va_arg(valist, Node*);
    va_end(valist);
    return p;
}
/**/
void debug_vsp(YYSTYPE yval, char * info, YYSTYPE * vsp, char * mark) {
#ifdef PARSE_DEBUG
    printf("\n -RULE 0x%x %s \n ", yval.node, info  );
    int i;
    int ilen = strlen(mark);
    for (i = 1 - ilen; i <= 0; i++) {
        switch (mark[ilen + i - 1]) {
        case '0':
            printf(" [ 0x%x ", vsp[i].node); //「」
            switch (vsp[i].node->type) {
            case TYPE_CONTENT:
                printf("%g ] ", vsp[i].node->content);
                break;
            case TYPE_INDEX:
                printf("%s ] ", G_Var[vsp[i].node->index].mark);
                break;
            case TYPE_OP:
                if (vsp[i].node->op.name < USER_DEF_NUM)
                    printf("%c ] ", vsp[i].node->op.name);
                else
                    printf("%s ] ", G_Def[vsp[i].node->op.name - USER_DEF_NUM].name);
                break;
            }
            break;
        case '1':
            printf(" %c ", vsp[i].index);  /* 打印运算符 */
            break;
        case '2':
            printf(" %s ", G_Var[vsp[i].index].mark);
            break;
        case '3':
            printf(" %g ", vsp[i].val);
            break;
        case '4':
            printf(" %s ", G_Def[vsp[i].index].name);
            break;
        }
    }
    printf("\n");
    print_stmt();
#endif
}
void add_var(char *mark) {
    if (G_iVarMaxIndex == 0) {
        strcpy(G_Var[0].mark, mark);
        G_iVarMaxIndex++;
        G_iVarCurIndex = 0;
        if (G_LoadVar != 0)
            G_LoadVar(mark, &G_Var[0].val);
        return;
    }
    int i;
    for (i = 0; i <= G_iVarMaxIndex - 1; i++) {
        if (strcmp(G_Var[i].mark, mark) == 0) {
            G_iVarCurIndex = i;
            return;
        }
    }
    strcpy(G_Var[G_iVarMaxIndex].mark, mark);
    G_iVarCurIndex = G_iVarMaxIndex;
    if (G_LoadVar != 0)
        G_LoadVar(mark, &G_Var[G_iVarCurIndex].val);
    G_iVarMaxIndex++;
}
void print_stmt() {
    printf(" -STMT: \n");
    /* int i; for(i=0;i<=G_iBuffRowCount;i++) printf("%s \n",G_sBuff[i]); */
    if (G_iBuffColCount == 0)
        printf(" %s \n", G_sBuff[G_iBuffRowCount - 1]);
    else
        printf(" %s \n", G_sBuff[G_iBuffRowCount]);
    printf("\n");
}
void NodeFree(Node *p) {
    int i;
    if (!p) return;
    if (p->type == TYPE_OP) {
        for (i = 0; i < p->op.num; i++)
            NodeFree(p->op.node[i]);
    }
    free (p);
}
int GetParserInput(char *buf, int maxlen) {
    int i;
    if (G_iFormulaPos >= strlen(G_sFormula))
        return 0;
    for (i = 0; i < maxlen && G_sFormula[G_iFormulaPos] != '\0'; i++)
        buf[i] = G_sFormula[G_iFormulaPos++];
    return i;
}
void yyerror(char *s) {
    //fprintf(stdout, "%s\n", s);
    printf("<Parser Error> Line %d ,Col %d \n", G_iBuffRowCount + 1, G_iBuffColCount + 1);
    printf(" %s\n", G_sBuff[G_iBuffRowCount]);
}

parser.h #内部编译使用的头文件

#include "compile.h"
//------------------------------------------------------------
//lex yacc 定义的结构体
/* 定义树结点的权举类型 */
typedef enum { TYPE_CONTENT, TYPE_INDEX, TYPE_OP } NodeEnum;
/* 操作符 */
typedef struct {
    int name; /* 操作符名称 */
    int num; /* 操作元个数 */
    struct NodeTag * node[1]; /* 操作元地址 可扩展 */
} OpNode;
/* 树结点 */
typedef struct NodeTag {
    NodeEnum type; /* 树结点类型 */
    /* Union 必须是最后一个成员 */
    union {
        float content; /* 内容 */
        int index; /* 索引 */
        OpNode op; /* 操作符对象 */
    };
} Node;
/* 变量结构 */
struct VarIndex
{
    float val;
    char mark[10];
};
/* 系统保留字 */
struct VarDefine
{
    int index;
    char * name;
};
//------------------------------------------------------------
//lex yacc 宏定义
#undef YY_INPUT
#define YY_INPUT(buf, ret, maxlen) (ret = GetParserInput(buf, maxlen))
/* yystype */
typedef union {
    float val;  /* 变量值 */
    int index;  /* 用于存放 变量数组索引 或 一元操作符值 或 多元操作符索引 */
    Node *node; /* 结点地址 */
} yystype;
#define YYSTYPE yystype

#define USER_DEF_NUM 259 /* Yacc编译的保留字开始索引 */

#define MAX_VARS 100 /* 最多变量数 */
#define MAX_DEFS 20 /* 最多保留字数 */

#define MAX_BUFF_COLS 40 /* 分析语句最多行数 */
#define MAX_BUFF_ROWS 40 /* 分析语句每行最多字符数 */
/* 是否打印调试信息的开关 */
#define PARSE_DEBUG
//------------------------------------------------------------
//lex yacc 全局变量
extern struct VarIndex G_Var[MAX_VARS];  /* 存储的变量数组 */
extern struct VarDefine G_Def[MAX_DEFS]; /* 系统保留字变量 */

extern int G_iVarMaxIndex;   /* 变量目前总数 */
extern int G_iVarCurIndex;   /* 当前操作变量索引 */

extern char G_sBuff[MAX_BUFF_ROWS][MAX_BUFF_COLS];  /* 存储分析语句 */
extern int G_iBuffRowCount;  /* 当前语句行数 */
extern int G_iBuffColCount;  /* 当前语句列数 */

extern char G_sFormula[MAX_FORMULA_LEN];  /* 全局变量,存储公式内容 */
extern int  G_iFormulaPos;                /* 全局变量,存储公式当前的处理位置 */

extern void (* G_LoadVar)(char *, float *); /* 函数指针 */
//------------------------------------------------------------
//lex yacc 函数定义
void add_var(char *);  /* 在内存中添加变量 */
void add_buff(char *); /* 在内存中添加语句 */
/* 打印分析调试信息 */
void debug_vsp(YYSTYPE , char * , YYSTYPE *, char * );
void print_stmt();
/* 属性操作类型 */
Node *opr(int name, int num, ...);
Node *set_index(int value);
Node *set_content(float value);
/* 树结点操作 */
void NodeFree(Node *p);
float NodeExecute(Node *p);
void yyerror(char *);

parser.c #内部编译的主函数

#include <stdio.h>
#include "parser.h"
#include "tree.tab.h"
float NodeExecute(Node *p) {
    if (!p) return 0;
    switch (p->type) {
    case TYPE_CONTENT: return p->content;
    case TYPE_INDEX:   return G_Var[p->index].val;
    case TYPE_OP:
        switch (p->op.name) {
        case WHILE:  while (NodeExecute(p->op.node[0]))NodeExecute(p->op.node[1]);
            return 0;
        case FOR:    NodeExecute(p->op.node[0]);
            while (NodeExecute(p->op.node[1])) {
                NodeExecute(p->op.node[3]);
                NodeExecute(p->op.node[2]);
            }
            return 0;
        case IF:     if (NodeExecute(p->op.node[0]))
                NodeExecute(p->op.node[1]);
            else if (p->op.num > 2)
                NodeExecute(p->op.node[2]);
            return 0;
        case PRINT:  printf("%g\n", NodeExecute(p->op.node[0]));
            return 0;
        case ';':    NodeExecute(p->op.node[0]);
            return NodeExecute(p->op.node[1]);
        case '=':    return G_Var[p->op.node[0]->index].val = NodeExecute(p->op.node[1]);
        case UMINUS: return NodeExecute(p->op.node[0]);
        case '+':    return NodeExecute(p->op.node[0]) + NodeExecute(p->op.node[1]);
        case '-':    return NodeExecute(p->op.node[0]) - NodeExecute(p->op.node[1]);
        case '*':    return NodeExecute(p->op.node[0]) * NodeExecute(p->op.node[1]);
        case '/root/include':    return NodeExecute(p->op.node[0]) / NodeExecute(p->op.node[1]);
        case '<':    return NodeExecute(p->op.node[0]) < NodeExecute(p->op.node[1]);
        case '>':    return NodeExecute(p->op.node[0]) > NodeExecute(p->op.node[1]);
        case GE:     return NodeExecute(p->op.node[0]) >= NodeExecute(p->op.node[1]);
        case LE:     return NodeExecute(p->op.node[0]) <= NodeExecute(p->op.node[1]);
        case NE:     return NodeExecute(p->op.node[0]) != NodeExecute(p->op.node[1]);
        case EQ:     return NodeExecute(p->op.node[0]) == NodeExecute(p->op.node[1]);
        case AND:    return NodeExecute(p->op.node[0]) && NodeExecute(p->op.node[1]);
        case OR:     return NodeExecute(p->op.node[0]) || NodeExecute(p->op.node[1]);
        case ADD_T:  return ++G_Var[p->op.node[0]->index].val;
        case MUS_T:  return --G_Var[p->op.node[0]->index].val;
        case ADD_TT: return G_Var[p->op.node[0]->index].val++;
        case MUS_TT: return G_Var[p->op.node[0]->index].val--;
        }
    }
    return 0;
}
int FormulaVarGet(char * mark, float * val) {
    int i;
    for (i = 0; i <= G_iVarMaxIndex; i++)
        if (strcmp(mark, G_Var[i].mark) == 0) {
            *val = G_Var[i].val;
            return 0;
        }
    return 1;
}
int FormulaParser(char * cmd, void (* loadvar)(char *, float *)) {
    printf("hello4\n");
    G_iFormulaPos = 0;
    G_LoadVar = loadvar;
    strcpy(G_sFormula, cmd);
    return yyparse();
}

compile.h #内外部交互的头文件

#define MAX_FORMULA_LEN 350

main.c #外部程序

#include <stdio.h>
#include "compile.h"
void loadvar(char * mark, float * val) {
    if (strcmp(mark, "xxxx") == 0) {
        *val = 6;
        return;
    }
    if (strcmp(mark, "xxxx") == 0) {
        *val = 6.99789;
        return;
    }
}
int main(int argc, char *argv[]) {
    int iRet;
    /**/
    char sFile[MAX_FORMULA_LEN] = {0};
    FILE *fp;
    if (argc != 2) {
        printf("Error: command filename\n");
        exit(-1);
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        printf("Error: Cannot open file\n");
        exit(-1);
    }
    fread(sFile, sizeof(char), MAX_FORMULA_LEN, fp);
    fclose(fp);
    printf("hello\n");
    iRet = FormulaParser(sFile, loadvar);
    printf("hello2\n");
    printf("\nRet:%d\n", iRet );
    float fVal;
    iRet = FormulaVarGet("i", &fVal);
    if (iRet == 0)
        printf("i:%g\n", fVal );
}

你可能感兴趣的:(Lex Yacc (四) 实际应用全代码)