【编译原理】LR(0)分析举例
方便复习用
题目
文法:
分别求:DFA、parsing table、和串(a(a))
的分析过程。
DFA
先拆分和扩张文法:
画DFA的要点:
- 初始状态从开始扩张。
- 扩张:当箭头后面第一个是非终结字符时(本题的),将其对应的文法也写在本状态下面。
- 用 · 标记状态,· 到达最后结尾表示可规约的状态。也就没有箭头再去指出了。
Parsing Table
直接根据DFA画出即可。
status | output | output | output | output | goto | goto |
---|---|---|---|---|---|---|
( | ) | a | $ | E | L | |
0 | s2 | s3 | s1 | |||
1 | acc | s6 | s4 | |||
2 | s2 | s3 | s6 | s4 | ||
3 | r3 | r3 | r3 | r3 | r3 | r3 |
4 | s5 | |||||
5 | r2 | r2 | r2 | r2 | r2 | r2 |
6 | s2 | r5 | s3 | r5 | s6 | s7 |
7 | r4 | r4 | r4 | r4 | r4 | r4 |
(a(a)) 的分析过程
先给出分析过程再总结:
Stack | intput_q | action |
---|---|---|
$0 | (a(a)) | s2 |
$0(2 | a(a)) | s3 |
$0(2E6 | (a)) | r3 |
$0(2E6(2 | a)) | s3 |
$0(2E6(2a3 | )) | r3 |
$0(2E6(2E6 | )) | r5 |
$0(2E6(2L4 | )) | r5 |
$0(2E6(2L4)5 | ) | r2 |
$0(2E6E6 | ) | r5 |
$0(2E6L7 | ) | r4 |
$0(2L4 | $ | s5 |
$0(2L4)5 | $ | r2 |
$0E1 | $ | acc |
规定stack的 $ 为栈底,input_q的最左边为队首。
流程:
-
stack.top();
作为行并input_q.peek()
队首作为列,并查表得到相应的action: ,根据action的 情况分别转到流程2、3、4 - 当action=时,
stack.push(input_q.poll());
并返回流程1。 - 当action=时,使用第个文法去规约(从栈顶向栈底扫描匹配并忽略其间的状态编号,匹配成功后弹出匹配到的相关串,弹出后栈顶元素应该为某个状态的编号)。将规约后得到的结果作为列,
stack.top();
得到的状态编号作为行查表得到下一个action=,并push得到的规约串后再stack.push(i);
转到流程1。 - 当action=时,分析结束。
- 当action=时,发生异常,分析结束 。