算术表达式的语法分析及语义分析程序设计 —— LR分析法、输出三元式
来源:互联网 发布:龙卷风浏览器 mac 编辑:程序博客网 时间:2024/05/22 13:21
1.系统描述
1.1目的
通过设计、编制、调试一个算术表达式的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。
1.2设计内容及步骤
1)根据要求构造相应的文法。
2)根据LR分析法的步骤在每个产生式的右部适当位置添加一个圆点构成项目。
3)构造识别活前缀的NFA。
4)LR项目集规范族的构造。
5)LR分析表的构造。
6)构造词法分析器。
7)模拟LR分析器的工作过程进行语法分析。
8)输出分析过程及三元式。
2.系统的详细设计
2.1 文法设计
本次设计具体文法需要满足的条件如下:
1) A->V=E
2) E->E+T |E-T|T
3) T->T*F|T/F|F
4) F->i|(E)
5) V->i
拓广文法:
0) A’->A; 1) A->V=E 2) E->E+T
3) E->E-T 4) E->T 5) T->T*F
6) T->T/F 7) T->F 8) F->i
9) F->(E) 10) V->i
2.2 文法项目
2.3 识别所有活前缀的DFA
FIRST和FOLLOW集如下:
2.4 构造LR分析表
2.5 词法分析器
从键盘输入一个算数表达式,以“#”结束。对输入的字符依次进行判别,每当开始识别一个单词时,若扫视到的第一个字符为字母,则把后续输入的字母或数字字符依次进行拼接,直至扫视到非字母、数字字符为止,以期获得一个尽可能长的字母数字字符串,然后以此字符串查所谓保留字表(此保留字表已事先造好),若查到此字符串,则取出相应的类别码;反之,则表明该字符串应为一标识符。
采用上述策略后,针对表I中部分单词可以构造一个如图1所示的有限自动机(以状态转换图表示)。在图1中添加了当进行状态转移时,词法分析程序应执行的语义动作。根据图1,可用C++语言编写出符合以上几项要求的一个相应的扫描器程序。
图1 识别表I所列语言中的部分单词的DFA及相关的语义过程
鉴于本程序只用来进行算数表达式的语法分析,所以只对“+”、“-”、“*”、“/”、“(”、“)”、“=、“#”和变量(此处用i代替)的单独表示种别码,其余全部归为一类。具体如下:
其对应的存储方式如下:
typedef struct code{ string data; int num;}Code;Code code[MAX];
2.6 LR分析器
将词法分析的输出即单词和种别码作为LR分析器的输入,构造状态栈state、分析栈ana、剩余输入栈sys、动作栈(ACTION词表、GOTO词表)和产生式表。其对应的存储方式分别为:
ACTION词表:
typedef struct action{ char para; int val;}Action;
GOTO词表:
vector<Gene> gene;
产生式表:
struct Gene{//产生式 string left; char* right;};vector<Gene> gene;
分别将对应的ACTION词表、GOTO词表和产生式词表用已有数据初始化。
根据LR分析法,将0入state栈,将“#”入ana栈,为了方便分析,sys栈直接有词法分析得到的code栈代替。
然后根据state栈的栈顶元素和code栈的栈顶元素寻找对应的ACTION词表(将state栈的栈顶元素和code栈的栈顶元素作为数组下标),找到对应的动作。若动作的para为“S”,即移进,则将code栈的栈顶元素取出,入ana栈。同时将对应动作的val入state;若动作的para为“R”,即规约,则根据对应产生式的长度,分别从ana栈和state栈中移出相应数量的单词。再根据state栈的栈顶元素和ana栈的最后一个元素查找GOTO词表(将state栈的栈顶元素和ana栈的最后一个元素作为数组下标),将其入state栈。
循环此过程,直至遇到“a”,即acc,则表明分析成功,表达式正确;否则,报错。
2.7 输出三元式和分析过程
在LR分析过程中,每循环一次,就将对应的state栈、ana栈、sys栈、动作栈和产生式表一次输出,即为分析过程。
在LR分析中,设置一个an栈,其操作与ana栈大致相同,不过只对含有规约所用的产生式中涉及到运算符时才会规约,其余时候的规约都不会执行。目的是为了保存原有操作数,方便三元式的输出。每次规约的过程中,若规约所用的产生式涉及到了含运算符的产生式的规约,则对an栈的最后三个单词进行调整(将运算符提前,第一运算数后移)输出。其中需要注意所含运算符为“(”“)”的情形,此时,不需要输出,但an栈还是要进行相应的规约。
3 用例分析
1)该用例是本分析程序的一个比较典型的简单的输入,得到结果如下:
2)当表达式包含变量或字母时,程序的运行结果:
3)当输入文法无法识别的字符时,程序会进行报错。程序的运行结果(这里是输入运算符“++”):
4)当输入的表达式不完整或不匹配时,程序会自动报错。
6)增加下难度,输入复杂表达式,输出结果如下(输入表达式为“i=(2*(1+3)+2)/2#”):
4.程序的评价
本程序最大的特点是先通过词法分析对输入的字符串进行识别,区别出一个个单词,并标以种别码,然后将其作为LR分析器的输入,由于是将输入的单词和运算符作为字符串处理,所以可以识别超过10的数字的运算,同样,由于状态栈、分析栈、剩余输入栈都是以字符串为单元来对输入处理的,所以还可以识别包括变量在内的算数表达式。功能相对而言较为全面。
在刚刚开始分析程序时,由于词法分析在上机实验时就已经实现了,而语法分析上机时时通过自顶向下的方法实现的,并且由于对原理理解得不够深刻,没有找到将词法分析的过程加入到语法分析中的方法。后来通过上网查找资料,发现通过种别码就可以将词法分析中得到的单词区分开来,同时将其作为语法分析参考的标准。但刚开始的时候在语法分析即LR分析时,是将得到的单词当做一个字符来处理,这样在分析栈和剩余输入栈中进、出栈时只需进出单个字符,比较好操作。但后来测试用例时,发现当输入“i=11+2#”时,在语法分析中“11”被当成了两个单独的字符“1”处理,而出现错误。于是,将字符串作为分析栈和剩余输入栈的基本单位,将字符串作为一个整体进栈和出栈,这样就能解决上述的错误,也能顺便解决含变量的算数表达式的分析。
- 算术表达式的语法分析及语义分析程序设计 —— LR分析法、输出三元式
- 算术表达式的语法分析及语义分析程序设计 —— LR分析法、输出三元式(续)
- 语法分析:算术表达式预测分析程序设计
- 语法分析:算术表达式递归下降分析程序设计
- 语法分析:算术表达式递归下降分析程序设计
- 算术表达式的语法和语义分析(算符优先分析方法生成三元式的中间代码)
- 表达式语法分析——预测分析法
- 表达式语法分析——预测分析法
- 表达式语法分析——预测分析法
- 表达式语法分析——预测分析法
- 【编译原理】自下而上的语法分析之LR分析法
- SDUT 表达式语法分析——预测分析法
- SDUT 2148 表达式语法分析——预测分析法
- 构造LR(1)项目集,生成LR(1)分析表、进行相应的语法分析
- 三元运算表达式分析
- 算术表达式语法分析
- 《C语言及程序设计》实践项目——算术运算符与算术表达式
- 编译原理之词法分析、语法分析、语义分析
- 【zzulioj 1919 二分】
- 【jzoj4711】【Binary】【树状数组】
- 易语言 精益/VIP精益模中的普通填表与网页填表的使用
- 链表中环的入口结点
- 【概念笔记】字节型输入输出流
- 算术表达式的语法分析及语义分析程序设计 —— LR分析法、输出三元式
- Django(2)——运用数据库为你的网页添加翻页功能
- poj2385 Apple Catching
- 关于在APIStore中获取数据
- ZZULI-oj-1919(二分)
- 【docker】docker容器的网络基础
- Activity的四种启动模式
- 爬虫小程序-爬取知乎推荐编辑文章内容
- HPUX上Logical Volume的Online扩展方法