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下的情况。诸如
此类,只有花时间慢慢琢磨了。