验证Yacc的使用
2015-12-25 21:42
239 查看
验证Yacc的使用
尝试二义文法和非二义文法两种不同的实现方式。布尔表达式二义文法为:S –>S or S | S and S | not S | (S) | true | false,其中优先级or < and < not,or 和 and 左结合,not 右结合。
非二义文法请参照表达式非二义文法自己写出来。
在cygwin下用flex,bison和gcc工具将例子调试通过,并写出测试例测试正确性。
参考:calculator0-3这四个例子。
输入一个布尔表达式,以换行结束。输出了这个布尔表达式的真值(true或false)。
makefile:
本例写了一个实数算术表达式的计算器。可以计算实数的加减乘除,可识别负数和括号。无论输入为整数还是实数,通通识别为实数。
输入输出:键盘输入一行算术表达式,以换行结束,屏幕输出计算结果。该过程可重复进行,直到出现词法或语法错误而退出,或者按ctrl+c结束程序。
词法分析程序用lex编写。
语法分析规则中使用的文法为二义的算术表达式文法。
注意:
int yywrap(void)函数中void不能少,否则出warning。
makefile中 gcc *.tab.o lex.yy.o -ly ,-ly必须在最后,否则可能出现重复定义main函数等错误。
makefile中, cal2.exe: cal.tab.o lex.yy.o ,lex.yy.o必须在cal.tab.o后面,否则会先编译lex.yy.o发现找不到cal.tab.h
yacc程序中不要随便引用yytext和yyleng,容易出问题。
一. 目的:
熟悉语法分析器生成工具Yacc的使用,并学会在cygwin下使用bison工具编译Yacc文法说明文件。学习如何使用lex和yacc合作进行语法分析。
二. 内容:
根据给出的calculator例子(calculator0,calculator1,calculator2,calculator3)完成下面题目:用lex和yacc写一个计算布尔表达式真值的计算器。
三.要求:
输入为一个布尔表达式,以换行结束。输出为这个布尔表达式的真值(true或false)。尝试二义文法和非二义文法两种不同的实现方式。布尔表达式二义文法为:S –>S or S | S and S | not S | (S) | true | false,其中优先级or < and < not,or 和 and 左结合,not 右结合。
非二义文法请参照表达式非二义文法自己写出来。
在cygwin下用flex,bison和gcc工具将例子调试通过,并写出测试例测试正确性。
参考:calculator0-3这四个例子。
四.源代码:
Cal.l:%{ #include "cal.tab.h" int yywrap(void) { return 1; } %} delim [ \t ] ws {delim}+ <strong>tr true fa false</strong> %% <strong>{fa} {return F;} {tr} {return T;} "||" {return AND;} "&&" {return OR;} "!" {return NOT;} "(" {return LPAREN;} ")" {return RPAREN;}</strong> {ws} {;} "\n" {return ENTER;} . {printf("\nLEX:ERROR! c=%s\n", yytext);} Cal.y: %{ int yylex(); #define YYSTYPE double /* 将Yacc栈定义为double类型 */ %} <strong>%token T F LPAREN RPAREN ENTER %left OR AND %right NOT</strong> %% /* 这样写prog可以让分析器每次读入一行进行分析,下一行重新分析exprg*/ prog : prog exprp | exprp ; exprp : expr ENTER { if($1) printf("The value of the expr is true\n");else printf("The value of the expr is false\n");} ; <strong>expr : expr OR expr {$$ = $1 || $3;} | expr AND expr {$$ = $1 && $3;} | NOT expr %prec NOT{$$ = ! $2;} | LPAREN expr RPAREN {$$ = $2;} | T {$$ = 1;} | F {$$ = 0;} ;</strong> %% int main(){ yyparse(); return 0; } Makefile: cal3: cal.tab.o lex.yy.o gcc -o cal3 cal.tab.o lex.yy.o -ly lex.yy.o: lex.yy.c cal.tab.h gcc -c lex.yy.c cal.tab.o: cal.tab.c gcc -c cal.tab.c lex.yy.c: cal.l flex cal.l cal.tab.c: cal.y bison -dv cal.y cal.tab.h: cal.y echo "cal.tab.h was created at the same time as cal.tab.c." clean: rm -f cal3.exe lex.yy.o cal.tab.o lex.yy.c cal.tab.c cal.tab.h cal3.exe.stackdump cal.output
五.结果及分析:
<span style="font-weight: bold;"> </span>true||true The value of the expr is true. true&&false The value of the expr is false. !false&&(false||true) The value of the expr is true.<strong> </strong>
输入一个布尔表达式,以换行结束。输出了这个布尔表达式的真值(true或false)。
六.附录:
cal.l%{ #include "cal.tab.h" int yywrap(void){ return 1; } %} delim [ \t ] ws {delim}+ tr true fa false %% {fa} {return F;} {tr} {return T;} "||" {return AND;} "&&" {return OR;} "!" {return NOT;} "(" {return LPAREN;} ")" {return RPAREN;} {ws} {;} "\n" {return ENTER;} . {printf("\nLEX:ERROR! c=%s\n", yytext);}cal.y:
%{ int yylex(); #define YYSTYPE double /* 将Yacc栈定义为double类型 */ %} %token T F LPAREN RPAREN ENTER %left OR AND %right NOT %% /* 这样写prog可以让分析器每次读入一行进行分析,下一行重新分析expr */ prog : prog exprp | exprp ; exprp : expr ENTER { if($1) printf("The value of the expr is true\n");else printf("The value of the expr is false\n");} ; expr : expr OR expr {$$ = $1 || $3;} | expr AND expr {$$ = $1 && $3;} | NOT expr %prec NOT{$$ = ! $2;} | LPAREN expr RPAREN {$$ = $2;} | T {$$ = 1;} | F {$$ = 0;} ; %% int main(){ yyparse(); return 0; }
makefile:
cal3: cal.tab.o lex.yy.o gcc -o cal3 cal.tab.o lex.yy.o -ly lex.yy.o: lex.yy.c cal.tab.h gcc -c lex.yy.c cal.tab.o: cal.tab.c gcc -c cal.tab.c lex.yy.c: cal.l flex cal.l cal.tab.c: cal.y bison -dv cal.y cal.tab.h: cal.y echo "cal.tab.h was created at the same time as cal.tab.c." clean: rm -f cal3.exe lex.yy.o cal.tab.o lex.yy.c cal.tab.c cal.tab.h cal3.exe.stackdump cal.output本例是一个有移进-归约冲突的例子,在calculator2的基础上做了如下修改:未定义PLUS的优先级和结合性,没有使用%prec UMINUS。
本例写了一个实数算术表达式的计算器。可以计算实数的加减乘除,可识别负数和括号。无论输入为整数还是实数,通通识别为实数。
输入输出:键盘输入一行算术表达式,以换行结束,屏幕输出计算结果。该过程可重复进行,直到出现词法或语法错误而退出,或者按ctrl+c结束程序。
词法分析程序用lex编写。
语法分析规则中使用的文法为二义的算术表达式文法。
注意:
int yywrap(void)函数中void不能少,否则出warning。
makefile中 gcc *.tab.o lex.yy.o -ly ,-ly必须在最后,否则可能出现重复定义main函数等错误。
makefile中, cal2.exe: cal.tab.o lex.yy.o ,lex.yy.o必须在cal.tab.o后面,否则会先编译lex.yy.o发现找不到cal.tab.h
yacc程序中不要随便引用yytext和yyleng,容易出问题。
相关文章推荐
- Opencv2.4.9+win7+VS2012一次性配置的方法--通过建立属性表永久配置
- 训练深度模型的优化问题(十四)
- 【LEETCODE】7-Reverse Integer
- 42节讲数据保存到文本!
- ViewOverlay 的使用
- stack
- HtmlHelper.Raw,<%%>,<%:%>,<%=%>的区别及使用
- stack
- 《算法竞赛入门经典2ndEdition 》例题5-1 大理石在哪儿(Where is the marble?, Uva10474)
- 训练深度模型的优化问题(十三)
- java跳出多重循环
- :before和::before的区别
- 旅行商问题(深度优先搜索 回溯法 排列树)
- 看起来好难越过去的坎
- 谱聚类算法(Spectral Clustering)
- Codeforces Round #290 (Div. 2) A. Fox And Snake 水题
- docfx开源啦
- codevs 1001 舒适的路线
- UVa11419 SAM I AM(构造最小点覆盖)
- 山重水复疑无路