【编译原理】LR(0)分析举例

方便复习用

题目

文法: E(L)aE\rightarrow (L) | a LELEL\rightarrow EL | E

分别求:DFA、parsing table、和串(a(a))的分析过程。

DFA

先拆分和扩张文法:1.EE1. E'\rightarrow E 2.E(L)2. E\rightarrow (L) 3.Ea3. E\rightarrow a 4.LEL4. L\rightarrow EL 5.LE5. L\rightarrow E

画DFA的要点:

  • 初始状态从EEE'\rightarrow E开始扩张。
  • 扩张:当箭头后面第一个是非终结字符时(本题的ELE、L),将其对应的文法也写在本状态下面。
  • 用 · 标记状态,· 到达最后结尾表示可规约的状态。也就没有箭头再去指出了。

【编译原理】LR(0)分析举例

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的最左边为队首。

流程:

  1. stack.top();作为行并input_q.peek()队首作为列,并查表得到相应的action: si,rj,acc,nulls_i, r_j, acc, null,根据action的 情况分别转到流程2、3、4
  2. 当action=sis_i时,stack.push(input_q.poll());并返回流程1。
  3. 当action=rjr_j时,使用第jj个文法去规约(从栈顶向栈底扫描匹配并忽略其间的状态编号,匹配成功后弹出匹配到的相关串,弹出后栈顶元素应该为某个状态的编号)。将规约后得到的结果作为列,stack.top();得到的状态编号作为行查表得到下一个action=sis_i,并push得到的规约串后再stack.push(i);转到流程1。
  4. 当action=accacc时,分析结束。
  5. 当action=nullnull时,发生异常,分析结束 。