验证Yacc的使用

                               验证Yacc的使用

一. 目的:

    熟悉语法分析器生成工具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,容易出问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值