所有实验的源代码:点此下载

实验目的:

熟悉语法分析器生成工具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工具将实验调试通过,并写出测试例测试正确性。

重要算法或文法正规式:

首先需要修改原先写的词法分析器,因为现在是要用语法分析器来调用词法分析器,所以需要将词法分析器中的main函数删掉,所有对记号名的宏定义也要删掉,记号在语法分析器中定义,词法分析器只需要包含相应的头文件就可以使用语法分析器所定义的记号名。
修改完词法分析器,下面分别考虑有二义性的文法和无二义性的文法。
对于有二义性的文法,在Yacc使用指南和课本中都提到过如何解决冲突。实验要求中也明确的说明了,优先级or<and<not,or和and左结合,not右结合,因此在定义终结符时,需要指明它们的优先级和结合性,具体如下。

%left OR
%left AND
%right NOT

%left表示左结合,%right表示右结合,越在前面定义的优先级越低,因此优先级是OR<AND<NOT。
为了便于测试,参照之前的词法分析器,将mian函数做一些修改,使之既可以从标准输入中读取测试用例,又可以从文件中读取。

有二义性文法的语法分析器代码:

%{#include <ctype.h>#include <stdio.h>int yylex();int yyerror(char* s);  /* yyerror 声明,使用库中的实现,为避免出现warning */#define YYSTYPE int /* 将Yacc栈定义为int类型 */#define YYDEBUG 1      /* 允许debug模式 */
%}%token TRUE FALSE LPAREN RPAREN ENTER
%left OR
%left AND
%right NOT%%/*
S –> S or S | S and S | not S | (S) | true | false
*/prog : prog exprp| exprp;exprp    : s ENTER {printf("\nThe result of the bool expression is "); $1 == 0 ? printf("FALSE\n") : printf("TRUE\n");}s : s OR s  {$$ = $1 || $3;}|s AND s  {$$ = $1 && $3;}|NOT s  {$$ = !$2;}|LPAREN s RPAREN  {$$ = $2;}|TRUE  {$$ = 1;}|FALSE  {$$ = 0;};%%int main(int argc, char ** argv){//yydebug = 1;extern FILE* yyin;if (argc == 2){if ((yyin = fopen(argv[1], "r")) == NULL){printf("Can't open file %s\n", argv[1]);return 1;}}yyparse();if(argc == 2){fclose(yyin);}return 0;
}

用非二义文法实现时,首先需要根据优先级和结合性,将二义文法修改为无二义文法,修改之后的文法如下。

S->S or T | T
T->T and F | F
F->not F | (S) | false | true

根据无二义文法构造的语法分析器就不会发生冲突了。

无二义文法的语法分析器代码:

%{#include <ctype.h>#include <stdio.h>int yylex();int yyerror(char* s);  /* yyerror 声明,使用库中的实现,为避免出现warning */#define YYSTYPE int /* 将Yacc栈定义为int类型 */#define YYDEBUG 1      /* 允许debug模式 */
%}%token OR AND NOT TRUE FALSE LPAREN RPAREN ENTER%%/*
S->S or T | T
T->T and F | F
F->not F | (S) | false | true*/prog : prog exprp| exprp;exprp    : s ENTER {printf("\nThe result of the bool expression is "); $1 == 0 ? printf("FALSE\n") : printf("TRUE\n");}s: s OR t  {$$ = $1 || $3;}| t;t: t AND f  {$$ = $1 && $3;}| f;f: NOT f  {$$ = !$2;}| LPAREN s RPAREN  {$$ = $2;}| FALSE  {$$ = 0;}| TRUE  {$$ = 1;};%%int main(int argc, char ** argv){//yydebug = 1;extern FILE* yyin;if (argc == 2){if ((yyin = fopen(argv[1], "r")) == NULL){printf("Can't open file %s\n", argv[1]);return 1;}}yyparse();if(argc == 2){fclose(yyin);}return 0;
}

词法分析器代码:

/* 把讨厌的注释去掉 */%{#include "cal.tab.h"
/*
yylval在cal.y中进行定义,不需要在此文件中再次定义
*/
%}ws            [ \t]
digit       [0-9]
number      {digit}+(\.{digit}+)?%%/* ECHO是一个宏,相当于 fprintf(yyout, "%s", yytext)*/
<INITIAL>or                   { return (OR);}
<INITIAL>and                  { return (AND);}
<INITIAL>not                  { return (NOT);}
<INITIAL>true                 { return (TRUE);}
<INITIAL>false                    { return (FALSE);}
<INITIAL>"("                    { return (LPAREN);}
<INITIAL>")"                    { return (RPAREN);}
{ws}                            {;}
<INITIAL>"\n"                   { return (ENTER);}
.                               {printf("\nLEX:ERROR! c=%s\n", yytext);}

实验结果:

实验所设计的测试用例如下。
(true and false) or false
(true or false) and false
true or false and false
not true or false
true or not true
false or not false

有二义性文法的运行结果。

无二义性文法的运行结果。

遇到的问题、实验难点、解决方法:

最初没搞明白词法分析器和语法分析器链接的原理,因此在用gcc编译时总是报错。后来又重新阅读了一遍Yacc使用指南,发现是记号名的问题,修改之后便能编译成功了。
由于时间较长,忘了如何将有二义性的文法根据它的优先级和结合性改写成无二义文法,因此又重新复习了一下课本的相关章节。
因为是第一次写语法分析器,因此遇到了若干细节上的问题,但最终经过我们的讨论与查阅资料,将问题逐个解决了。
第一次接触makefile文件,最初使用的很不熟练,但渐渐地发现使用makefile能极大的提高调试程序的效率,每当对代码做了修改之后,只需一句make命令便可重新生成可执行文件,当代码需要多次修改时,这样无疑会提供极大的便利。

编译原理实验四:验证Yacc的使用相关推荐

  1. 编译原理——实验叁——基于YACC的TINY语法分析器的构建

    一. 实验要求 运用YACC,针对TINY语言,构造一个语法分析器.给出实验方案,实施并描述结果. 二. 实验方案 (1)设计基于YACC的TINY词法分析器 (2)设计基于LEX的TINY语法分析器 ...

  2. 笔记-编译原理-实验四-语义分析与中间代码生成

    实验四. 语义分析及中间代码生成 设计思想 根据对属性文法及语义分析.中间代码生成的学习,可以将实验二.三的两种语法分析器进行一定的改造,以达到进行语法分析的同时进行语义分析并生成中间代码.根据PL0 ...

  3. 编译原理-实验四-LR(0)语法分析程序的设计

    一.实验目的 了解LR(0)语法分析算法的基本思想,掌握LR(0)语法分析程序的构造方法. 二.实验内容 根据LR(0)语法分析算法的基本思想,设计一个对给定文法进行LR(0)语法分析的程序,并用C. ...

  4. 编译原理 实验四 LR(0)分析法(LR0分析表的自动生成)

    写在前面 由于代码较长,csdn对文章总长度有字数限制,想只看完整代码的请移步另一篇博客. https://blog.csdn.net/qq_46640863/article/details/1257 ...

  5. 编译原理 | 实验四 | 逆波兰式

    目录 一.问题分析 二.算法思想 1.关于分词器 2.关于逆波兰式分析器: 三.实现代码 1.头文件  &  类视图 2.预处理部分 3.逆波兰分析过程 4.计算,输出部分 四.总结 一.问题 ...

  6. 编译原理实验二(全部存储到数组再逐行验证语法版.....这种思路被老师否了,应该是验证一行扔掉一行才对)

    编译原理实验二(可能还有BUG,不确定继续找) 要大改一次23333,老师的意思是不能用数组存储,而是一边识别单词,然后识别完一行就判断一次语法 写实验二的时候找到的实验一的一个逻辑错误 改动了实验一 ...

  7. 太原理工 编译原理 c语言,太原理工大学编译原理实验

    <太原理工大学编译原理实验>由会员分享,可在线阅读,更多相关<太原理工大学编译原理实验(19页珍藏版)>请在人人文库网上搜索. 1.本科实验报告课程名称: 编译原理 实验项目: ...

  8. 编译原理实验c语言cfg文法,编译原理

    地址在符号表中引入指针previous,来连接上一个符号的首地址运行时存储空间组织活动记录用于管理函数变量的信息栈式存储过程进入和返回通过变更top和sp指针,实现活动记录的栈式处理静态链实现局部变量 ...

  9. 编译原理实验:代码生成作业(1)

    编译原理实验4:中间代码生成实验包-C++文档类资源-CSDN下载编译原理实验4:中间代码生成实验包更多下载资源.学习资料请访问CSDN下载频道.https://download.csdn.net/d ...

最新文章

  1. 程序员,选择和努力哪个重要?
  2. composer mysql_php – 无法看到mysql数据库时,composer安装失败
  3. [转载]MATLAB movie 函数动态绘图
  4. android代码导入有错误,android新项目导入后进行编译出现cmake错误
  5. dubbo protocol port 消费者端_企业级 SpringBoot 与 Dubbo 的并用
  6. 复制GAC中的DLL
  7. jQuery:实现显示更多动画
  8. 从信号转换角度研究血压(波形)预测的相关论文
  9. 半监督学习与直推式学习
  10. 为什么宁愿工资低点,也不建议去外包公司?
  11. 小麦苗的常用代码--常用命令(仅限自己使用)--下
  12. antv,图表和地图
  13. php基础-GD库-批量制作水印图片
  14. 基于Dense-U-net的3D粒子场全息重建
  15. 微核Linux(Tiny Core Linux)
  16. 不要做一个只会抱怨的人
  17. 5GNR漫谈4:CORESET与SearchSpace
  18. 叮~请查收关联名师博客汇总地址哦
  19. Python Socket套接字编程
  20. 文献阅读笔记:Smart Homes that Monitor Breathing and Heart Rate

热门文章

  1. 加油吧!数字化转型@猎豹汽车装上“数据智能”新引擎
  2. 移动互联时代,这家公司竟这样改变了我们的世界
  3. 【JavaScript】
  4. Python安装Image库
  5. 【5G系列】AS层的网络选择(3)——小区重选标准
  6. 23款保时捷Panamera升级ACC、360全景影像,驾驶辅助系统等
  7. redis三个定时监控任务和主观下线、客观下线
  8. win7忘记密码,启动恢复
  9. 普林斯顿大学颜宁教授宣布全职加盟深圳医学科学院
  10. 现实中的人工智能发展,并未在模仿人类的通用人工智能