编译原理轻松学会LR(0)、SLR(1)、LR(1)、LALR(1)

Content

  1. LR完整分析过程
  2. 画LR(0)项目 + 填LR(0)分析表
  3. 画SLR(1)项目 + 填SLR(1)分析表
  4. 画LR(1)项目 + 填LR(1)分析表
  5. 画LALR(1)项目 + 填LALR(1)分析表

LR分析过程

已知文法生成式(已标号)

1 E → E + T
2 E → T
3 T → T * F
4 T → F
5 F → ( E )
6 F → I

已知LR分析表(根据项目图+已标号文法写出来的)

在这里插入图片描述

完整分析过程

状态栈 操作
0 # i*i+i# s5
05 #i *i+i# r6
03 #F *i+I# r4
02 #T i+i# s7
027 #T* i+i# s5
0275 #T*i +i# r6
027 10 #T*F +i# r3
02 #T +i# r2
01 #E +i# s6
016 #E+ i# s5
0165 #E+i # r6
0163 #E+F # r4
0169 #E+T # r1
01 #E # Accept

画LR(0)项目

方法:

  1. 先添加一个

    S

    S

    S‘ → S

    S‘→S

  2. 不断进行状态转移并求closure闭包

已知文法,画出这个文法的所有LR(0)项目?

E

a

A

E → aA

E→aA

E

b

B

E → bB

E→bB

A

c

A

A → cA

A→cA

A

d

A → d

A→d

B

c

B

B → cB

B→cB

B

d

B → d

B→d

在这里插入图片描述

填LR(0)分析表

方法:

  1. 先对文法进行标号
  2. 根据LR(0)项目图画出LR(0)分析表
0 S‘ → E
1 E → aA
2 E → bB
3 A → cA
4 A → d
5 B → cB
6 B → d
a b c d # E A B
0 s2 s3 1
1 Accept
2 s4 s10 6
3 s5 s11 7
4 s4 s10 8
5 s5 s11 9
6 r1 r1 r1 r1 r1
7 r2 r2 r2 r2 r2
8 r3 r3 r3 r3 r3
9 r5 r5 r5 r5 r5
10 r4 r4 r4 r4 r4
11 r6 r6 r6 r6 r6

画SLR(1)项目

和LR(0)的画法项目集的方法完全一样

S

S

S‘ → S

S‘→S

S

r

D

S → rD

S→rD

D

D

?

i

D → D*i

D→D?i

D

i

D → i

D→i

图略

画完之后你会发现一个问题:

I

3

I3

I3集合为?

S

r

D

?

S → rD·

S→rD??

D

D

?

?

i

D → D·*i

D→D??i —— 在填分析表的时候会出现多重入口——出现了归约/移进冲突

这个冲突其实是有可能解决的,接着往下看

填SLR(1)分析表

在填SLR(1)分析表的时候,我们这样解决「归约/移进冲突」:
对于规约的那个式子,求其左侧VN的随符集Follow,只有在Follow中符号对应的地方才填r

上面例题的答案大概是下面的样子(可以验证下自己答案):

r * i # S D
0 s2 1
1 acc
2 s4 3
3 s5 r1
4 r3 r3 r3 r3
5 s6
6 r2 r2 r2 r2

画LR(1)项目

基本思路差不多与LR(0)和SLR(1)一致,(重点!!!)区别在于:

A

α

?

B

β

a

A→α·Bβ,a

A→α?Bβ,a? 求闭包为:

B

?

γ

b

B→·γ,b

B→?γ,b ?其中 b = First(βa)(也就是说,如果B后还有个β,b就为First(β);若B后什么都没有,b就把a继承下来)

S

S

S‘ → S

S‘→S

S

B

B

S → BB

S→BB

B

a

B

B → aB

B→aB

B

b

B → b

B→b

画出其项目集:

在这里插入图片描述

填LR(1)分析表

移进的时候(就是s几),还是老样子
归约的时候(就是r几),不是像LR(0)那样全都填满,也不是像SLR(1)那样根据Follow集填,而是根据逗号右边的符号来填

还是给出上面例题的答案(自己对照着验证一下):

a b # S B
0 s3 s4 1 2
1 acc
2 s6 s7 5
3 s3 s4 8
4 r3 r3
5 r1
6 s6 s7 9
7 r3
8 r2 r2
9 r2

画LALR(1)项目

画法和LR(1)项目集的画法完全一样——LALR(1)只需在LR(1)基础上进行小小的改动

填LALR(1)分析表

合并LR(1)分析表的同心集——LALR(1)只需在LR(1)基础上进行小小的改动

何为同心集?

举个例子很容易明白:上面的

I

8

I8

I8和

I

9

I9

I9,即 B → aB,a|bB → aB,#

下面话需要理解一下:

  • LR(0)和SLR(1)的项目集画法完全一样——当然

    I

    I

    I状态的个数完全一样;

  • LR(1)使得同心集分裂,

    I

    I

    I状态的数目急剧增加

  • LALR(1)将LR(1)的同心集全部又合并了回去,也就是说LR(0)、SLR(1)、LALR(1)的状态集数目完全相同

下面给出前一个例题中的分析表进行同心集合并后的结果(自己验证一下答案):

a b # S B
0 s3,6 s4,7 1 2
1 acc
2 s3,6 s4,7 5
3, 6 s3,6 s4,7 8, 9
4, 7 r3 r3 r3
5 r1
8, 9 r2 r2 r2