一、简介
PL0 语言功能简单、结构清晰、可读性强,而又具备了一般高级程序设计语言的必须部分,因而 PL0 语言的编译程序能充分体现一个高级语言编译程序实现的基本方法和技术。
分析对象〈算术表达式〉的 BNF 定义如下:
<表达式> ::= [+|-]<项>{<加法运算符> <项>}
<项> ::= <因子>{<乘法运算符> <因子>}
<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
二、设计思想
1、表达式的文法
在上一次的自上而下分析中考虑到使用递归下降分析法,使用扩充的巴克斯范式书写表达式的文法会更简单,但是本次在LR(0)分析法中则需要转换为一般文法:
可用的文法:
E -> +B | -B | B
B -> TA | T
A -> +TA | -TA | +T | -T
T -> FM | F
M -> *FM | /FM | *F | /F
F -> i | n | (E)
不可用的文法:
E -> STA
S -> + | - |ε
A -> +TA | -TA |ε
T -> FM
M -> *FM | /FM |ε
F -> i | n | (E)
表达式开头的符号可以省略,但是后面接着的项前面的符号不可以省略;在非终结符F中,标识符和无符号整数就用终结符i和n代替。
这里要特别强调为什么我写了2种文法上去:不可用的文法不是说他错了,而是在LR分析中不可用! 我一开始画DFA时用的就是第二个不可用文法,这个文法很好理解,也很简单。
但是,在画完LR0分析表后我发现无法正常识别表达式,原因就在于这个ε使得DFA没法正常的规约,比如开头的S要是空的话,怎么就能上来就把空规约为S呢?但事实确实得这样做。
于是我思考是不是得用LR1分析来做,于是又重新构造了一遍DFA,时间证明,不可行,一切都是ε导致的,于是我翻遍视频,书本,蛮惊讶的发现所有LR分析都没有ε的存在,我应该是知道答案了。
于是提出了可用文法,思考后我采用了SLR分析,实践证明,这次做对了。
如果我的分析帮助到了你,就评论个“学霸流弊!”吧。
2、文法的项目
根据文法获得识别活前缀的方法在这里采用有效项目集来构造,为了方便表达,就不写成GO函数的形式,而是直接构造成DFA。
在构造表之前由于我使用的是SLR分析,所以需要先做好开始条件。
文法的表达式编号:
1:E -> +B
2:E -> -B
3:E -> B
4:B -> TA
5:B -> T
6:A -> +TA
7:A -> -TA
8:A -> +T
9:A -> -T
10:T -> FM
11:T -> F
12:M -> *FM
13:M -> /FM
14:M -> *F
15:M -> /F
16:F -> i
17:F -> n
18:F -> (E)
FIRST和FOLLOW集合:
为方便表示,我将读入的标识符和整数用终结符i和n表示
| — | FIRST | FOLLOW |
|---|---|---|
| E | + - i n ( | # ) |
| B | i n ( | # ) |
| T | i n ( | # + - ) |
| A | + - | # ) |
| F | i n ( | # + - * / ) |
| M | * / | # + - ) |
3、DFA
由于状态太多,所以我只画了识别非终结符的线条,识别终结符的线条没有画出来,详情参考下面的ACTION表。
4、SLR分析表
对表格中所有空格致ERROR出错标志。
其中的规约项并不是像LR0分析一样一整行都是,经过分析后认为无需画LR1分析表。
所有的规约项目都是参照FOLLOW集合来添加,不然会产生冲突。
三、算法流程
算法的流程图就是对各种单词符号的组合进行判断。
对于输入的种别编码采用首字母存储,这杨就和符号都可以统一以字符来处理。
四、源程序
这个得等老师截止提交后我才能发出来,不然就代码雷同了。。。。
五、数据测试
说明:
1、上面的代码是带有分析过程的代码,去掉各种输出就是提交的代码。
2、算法有2种输入方式,一是直接输入表达式,二是输入词法分析的结果。
输入输出示例1:
以词法分析的结果作为输入,带有分析过程。
输入输出示例2:
以表达式方式输入,输入:+(i+n-(i*(i-i)))*i# 带有分析过程。