Lex和Yacc使用方法(七).企业方面的实际应用

Lex和Yacc应用方法(七).企业方面的实际应用

20070527

草木瓜

一、前言

    说到这里,也许有人觉得要把这些东西实际应用起来,还没谱,或许很多人觉得工作中很
少能使用到。
    本文的主要目的就是为了详细说明下实际的企业应用示例。示例基于《Lex和Yacc应用方
法(五).再识语法树》

    <注:本站文章难免有错误疏漏之处。Lex,Yacc系列文章 http://blog.csdn.net/liwei_cmg/category/207528.aspx>

二、企业应用综述

    Lex和Yacc的编译理论体系十分适用于处理相对复杂的逻辑判断。在中国这个特殊环境下,
有个十分典型的例子就是计算费用,俗话说就是算钱。实在不是一般的麻烦,接触的一些行业
如集装箱物流行业,电信行业皆如事,恐怕中国人的心眼全用在玩花样算钱了罢。
  越复杂的逻辑环境,Lex和Yacc的优势越明显。如工业控制,成本核算,人员评估,费用
计算等等方面。下面举些实际的例子说明。
  
  A.集装箱的滞箱费
  
  超期使用集装箱,一般会产生滞箱费。滞箱费与进出口,提箱单位,承运人,使用天数,
箱属,箱型和箱尺寸都可能有关系,此外还存在人为协议上的调整。
    我们假设:fee表示费用返回值,rate表示基本费率,size表示箱尺寸,type表示箱型,
days表示天数。

  计算公式:
  (注:实际费用并非如此,仅供示例)
  
    #普通箱,10天免费
    if((size==20 || size=40) && type==1)
      if(days<=10)
        fee=0;
      else
        fee=(days-10)*feerate;
    #冷箱,4天免费
    if(size==40 && type==2)
      if(days<=4)
        fee=0;
      else
        fee=(days-4)*feerate;
    #开顶箱和超高箱,7天免费
    if(type==3 || type==4)
      if(days<=7)
        fee=0;
      else
        fee=(days-4)*feerate;
   
   
    B.电信套餐计费
   
    各运营商,品牌,套餐的计费方法是层出不穷,不使用公式计费,复杂度可想而知。
拿亲情电话组为例,A,B,C,D是一个电话组,5元包300分钟,超出按市话3毛一分算。正
常资费为5毛一分。
    我们假设:FEE表示费用返回值,G_CALL*表示主被叫所在组,W_CALL*表示主被叫
套餐内累计时长, T_CALL*表示正常累计时长。0主叫,1被叫

  计算公式:
  (注:实际电信计费公式远复杂与此,仅做示例)
  
  if(G_CALL0==G_CALL1)
    if(T_CALL0<=300)
      FEE=0
    else
      FEE=30
  else
    FEE=50
   
三、修改后的实际应用全代码

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

    ----------------------------------------------------------------------
  <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 '/':    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 *)) {
  
   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);
   
   iRet=FormulaParser(sFile, loadvar);
   printf("/nRet:%d/n",iRet );
   
   float fVal;
   iRet=FormulaVarGet("i", &fVal);
   if(iRet==0)
    printf("i:%g/n",fVal );
   
  }
  
   
四、一些修改说明
 
  
  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
  ar -rl compile.a *.o
  
  使用静态库文件编译外部程序:
  
  gcc -g  -o lw main.c compile.a
  
  
    运行编译显示结果:
   
    ./lw input
   
    1

  Ret:0
  i:1
  
  input内容:
  i=i+1;print(i);
  
  
五、一些总结

    在企业的应用中,本示例提供的功能还略显浅薄,主要有如下一些缺点:
   
    1.目前仅支持浮点整型,不支持字符型
    2.不支持switch分支结构
    3.不支持return,break,goto,continue等跳转语句
   
    这些用目前的语法树也不是不能实现,不过语法树需要做大量的递归操作,在效率上存在
一些问题。
  后面的系列文章中会逐渐引入堆栈来处理语法编译的问题,也可能会对现有的语法树做些
优化。Lex和Yacc系列到现在都是在Linux下面说事,我们也不能忽略Windows下的情况。诸如
此类,只有花时间慢慢琢磨了。
   
     

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值