验证Yacc的使用_prog : prog exprp | exprp ;-程序员宅基地

技术标签: Yacc  C++  编译原理  

                               验证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,容易出问题。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wp1603710463/article/details/50405401

智能推荐

Python 入门的60个基础练习_练习python基础语法-程序员宅基地

文章浏览阅读4.2w次,点赞329次,收藏2.7k次。Python 入门的60个基础练习_练习python基础语法

iOS6和iOS7代码的适配(2)——status bar_ios7 statusbar-程序员宅基地

文章浏览阅读1w次。用Xcode5运行一下应用,第一个看到的就是status bar的变化。在iOS6中,status bar是系统在处理,应用_ios7 statusbar

gdb调试时No symbol "var" defined in current context && No Register_no registers调试显示-程序员宅基地

文章浏览阅读2.1k次。问题描述:,在gdb调试程序输出变量:p var,会提示No symbol "var" in current context.原因:程序编译时开启了优化选项,那么在用GDB调试被优化过的程序时,可能会发生某些变量不能访问,或是取值错误码的情况。这个是很正常的,因为优化程序会删改程序,整理程序的语句顺序,剔除一些无意义的变量等,所以在GDB调试这种程序时,运行时的指令和你所编写指_no registers调试显示

IDGeneratorUtil 主键id生成工具类_idgeneratorutils.generateid()-程序员宅基地

文章浏览阅读3.4k次。import java.util.Random;import org.drools.util.UUIDGenerator;/** * * * 类名称:GenerateIdUtil * 类描述: 主键生成工具类 * @author chenly * 创建时间:Jul 10, 2012 8:10:43 AM * 修改人: * 修改时间:Jul 10, 2012 8..._idgeneratorutils.generateid()

关于汇编 BX 和 BLX 跳转指令_汇编blx-程序员宅基地

文章浏览阅读5k次。BX:跳转到寄存器reg给出的目的地址处,如:BX R2BLX:跳转到寄存区reg给出的目的地址处并将返回地址存储到LR(R14)使用这两个指令时有一点特别需要注意:跳转的目的地址必须是奇数,若不是奇数则在后面加1,如某函数的起始地址是0x80000f00,则要跳转到此函数则应该跳转到0x80000f01处!否则会进入硬件错误中断!..._汇编blx

前端vue,打包整合进后端springboot的resources里面后,运行只要刷新就报404_前端项目放入resource-程序员宅基地

文章浏览阅读2.6k次,点赞2次,收藏4次。vue打包后,其实就剩index.html和一堆静态资源,页面的加载和替换都是通过刷新index.html种的dom来实现的(应该是这样,可能表述不是很好),所以做个重定向就可以了。(博主是这么解决的,网上还有很多人是各种路径错误,大家可以尝试下自己是哪个原因)import org.springframework.boot.web.server.ConfigurableWebServerFa..._前端项目放入resource

随便推点

添加远程github仓库时报错 Warning: Permanently added the RSA host key for IP address 52.74.223.119_cmd warning: permanently added-程序员宅基地

文章浏览阅读9.7k次。1.问题展示2.解决方案1.任意窗口, 打开git bash2.命令行界面, 输入cd C:3.cat ~/.ssh/id_rsa.pub正常下面应该显示一大串公钥如果没有,显示如下图, 则进行下一步, 创建公钥4.创建公钥, 输入 ssh-keygen5.然后一直下一步, 直到出现6.再次输入cat ~/.ssh/id_rsa.pub下面一大串数字便是公钥,复制这些字符串, 打开github, 点击头像, 打开settings, 打开SSH and GPG Keys_cmd warning: permanently added

SQL*Plus 使用技巧1-程序员宅基地

文章浏览阅读154次。[code="java"]1. SQL/Plus 常用命令 a. help [topic] 查看命令的使用方法,topic表示需要查看的命令名称。 如: help desc; b. host 该命令可以从SQL*Plus环境切换到操作系统环境,以便执行操作系统命名。 c. host [command] 在sql*plus环境中执行操作系统命令,如:host notepad.exe..._sql+plus的使用方法

域控服务器搭建与管理论文,校园网络服务器的配置与管理 毕业论文.doc-程序员宅基地

文章浏览阅读441次。该文档均来自互联网,如果侵犯了您的个人权益,请联系我们将立即删除!**学校毕 业 论 文**学校园网络服务器的配置与管理姓 名: **学 号: **指导老师:系 名:专 业: 计算机网络技术班 级:二0一一年十二月十五日摘 要随着网络技术的不断发展和Internet的日益普及,许多学校都建立了校园网络并投入使用,这无疑对加快信息处理,提高工作效..._服务器配置与应用论文

mysql单实例多库与多实例单库_数据库单实例和多实例-程序员宅基地

文章浏览阅读1k次。一、单实例多库:一个mysql实例,创建多个数据目录。规划:实例路径:/usr/local/mysql数据目录路径:(1)/usr/local/mysql/data(2)/usr/local/mysql/data2步骤:安装mysql。配置my.cnf文件。初始化各个数据库。用mysqld_multi启动。1、安装mysql。平常安装。2、m..._数据库单实例和多实例

MFC解决找不到MFC90.DLL的问题_microsoft v90.debugmfc-程序员宅基地

文章浏览阅读6.3k次。今天装了第三方的MFC软件库Xtreme ToolkitPro v15.0.1,听说搞MFC的人都知道它的强大,我刚学习,所以装了一个,然后想运行一下它自带的例子看看。出现一个“找不到mfc90.dll“的问题,百度一下,记录如下:vs2008已经打过sp1补丁,编译C++程序会提示找不到mfc90.dll文件的错误,但是如果是release版的话就能正常运行csdn看到解决方案,粘贴_microsoft v90.debugmfc

XeLaTeX-中文排版解决方案_latex 中文排版 texlive-程序员宅基地

文章浏览阅读2.1k次。以前使用CJK进行中文的排版,需要自己生成字体库,近日,出现了XeTeX,可以比较好的解决中文字体问题,不需要额外生成LaTeX字体库,直接使用计算机系统里的字体,本文以在Linux下为例说明XeTeX的使用。操作系统: UbuntuTeX:除了texlive包外,还需要安装的包是texlive-xetex。字体:可以使用fc-list查看你自己的字体库,注意字体的完整名称,在XeTe..._latex 中文排版 texlive