这里有一个使用bison建立一个简单的计算器的例子:http://www.cs.berkeley.edu/~maratb/cs164/bison.html使用bison和flex工具学习编译原理,远比单独看书然后自己编写一些程序生动的多。这样你就不会在那些复杂的字符处理,正则表达式的处理上浪费精力,最后费尽心力,却没有结果,失去了学习的兴趣。我 这里有一个简单的计算器的程序,可以实现加、减、乘、除运算,并支持括号的处理和26个字母作为变量。以前自己使用后缀表达式方式写过一个这样的程序,单 单中缀表达式改为后缀表达式就是几百行的代码,反正自己现在还是不知道怎么处理里面复杂的堆栈的(我用了STL的List实现)。
词法处理文件calc.lex内容如下:%{ /* * 一个简单计算器的Lex词法文件 */ #include <stdlib.h> void yyerror(char*); #include "calc.tab.h"%}%% /* a-z为变量 */[a-z] { yylval = *yytext - 'a'; return VARIABLE; } /* 整数 */[0-9]+ { yylval = atoi(yytext); return INTEGER; } /* 运算符 */[-+()=\*\n] {return *yytext;} /* 空白被忽略 */[ /t] ; /* 其他字符都是非法的 */. yyerror("无效的输入字符");%%int yywrap(void){ return 1;}词法处理的目标就是区分出来每个成员到底是什么,这里有两种 INTEGER和VARIABLE。只要区分出来各个成分词法分析的任务就完成了。
语法处理文件calc.y内容如下:%token INTEGER VARIABLE%left '+' '-'%left '*' '/'%{ #include <stdio.h> void yyerror(char*); int yylex(void); int sym[26];%}%%program: program statement '\n' | ;statement: expr {printf("%d\n", $1);} |VARIABLE '=' expr {sym[$1] = $3;} ;expr: INTEGER |VARIABLE{$$ = sym[$1];} |expr '+' expr {$$ = $1 + $3;} |expr '-' expr {$$ = $1 - $3;} |expr '*' expr {$$ = $1 * $3;} |expr '/' expr {$$ = $1 / $3;} |'('expr')' {$$ = $2;} ;%%void yyerror(char* s){ fprintf(stderr, "%s\n", s);}int main(void){ printf("A simple calculator.\n"); yyparse(); return 0;}语法分析文件的写法就是将BNF表达式描述一下即可,规则随着条目逐渐细化,变成了可以理解的内容。这里不用管如何实现这些语法的分析,只是需要告知如何构建这些语法。
编译命令如下:>bison -d calc.y>flex calc.lex>gcc calc.tab.c lex.yy.c -o calc
------------------------------------------------
yyparse 是bison生成的函数,用于解析语法,同时yylex是flex生成的函数,用于解析词法,bison生成的函数调用yylex不断处理,处理出来适合的表达式,之后计算.
转载于:https://www.cnblogs.com/linucos/archive/2012/09/26/2704185.html
相关资源:利用 Flex/Bison 构造编译器