欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【编译原理】自底向上分析方法——LR文法分析方法的总结

程序员文章站 2022-07-13 17:35:30
...

LR(0)、SLR(1)、LR(1)、LALR(1) de 若干方面的区别

推导过程

LR(0)的基础上才有SLR(1) SLR分析方法只用在分析表上,DFA与LR(0)相同
LR(1)的基础上才有LALR(1) LR(1)的DFA合并同心项才能为LALR(1)

分析能力

LR(1)>LALR(1)>SLR(1)>LR(0)
分析能力指的是分析方法对于文法的甄别能力,也就是可以理解成文法包括的范围,LR(1)范围最大,比如,是SLR(1)文法的文法也一定是LR(1)文法

本质区别

四个文法,区别都只在一点,LR分析表中ACTION表中的归约动作的差别:
先做一个假设,有文法G,其中:

文法的第二条产生式是 (2) A->a  (之后的r2表示按照第二条产生式进行归约)
终结符集合是 { a,b,c,$ }
FOLLOW(A) = { b,c }
有状态 I5: A->a·
(LR(1)时 有状态 I5: A->a·,b )
(LALR(1)时 有状态  I5: A->a·,b 和同心项  I10: A->a·,$ 合并为  I5: A->a·,b|$ )
  • LR(0) 状态有归约状态,整个状态都会进行该归约动作
    即LR分析表中的状态5所在的那一整行全填 r2
状态 a b c $
5 r2 r2 r2 r2
  • SLR(1) 状态中针对FOLLOW集中有的终结符号会进行该归约动作
    即LR分析表中的状态5所在的那一行中对应的FOLLOW(A)中有的终结符填写r2
状态 a b c $
5 r2 r2
  • LR(1) 状态中针对展望符对应的总结符号进行该归约动作(一般为FOLLOW集的真子集)
    即LR分析表中的状态5所在的那一行中只对展望符b填写归约动作r2
状态 a b c $
5 r2
  • LALR(1) 状态中也是针对展望符对应的总结符号进行该归约动作(一般为FOLLOW集的真子集)
    即LR分析表中的状态5所在的那一行中只对展望符b和$填写归约动作r2
状态 a b c $
5 r2 r2

文法对比

  • SLR(1)对于LR(0) 排除不合理的归约,使用FOLLOW集解决移入-归约、归约-归约冲突。如果FOLLOW(A)与FIRST(B)存在交集,且A,B属于同一个项目集,则SLR无法解决该冲突。
  • LR(1)对于SLR(1) SLR(1)无法解决的冲突使用LR(1)分析法可以解决。使用展望符,每个展望符是FOLLOW集的子集(一般为真子集)。
  • LALR(1)对于LR(1) LALR(1)就是在LR(1)的基础上合并同心项集(具有相同核心的项集,也就是项集的第一分量也叫做核心项),与之同时可能会引出新的冲突且只能为归约-归约冲突(原因是合并同心项本质上只是将展望符合并了,对原本的移入动作并没有影响,所以只能是归约-归约冲突)。另外一个毛病是LALR(1)会将LR(1)的报错延后,会多进行若干次归约,直到碰到移入动作才能检测出错误。
  • 另外,LR(0)、SLR(1)、LALR(1)的状态数都是一样的,但是LR(1)的状态数会多非常多,比如C语言的文法,LR(0)分析时只有几百个状态,而LR(1)分析会出现几千个状态,所以实际开发中使用LR(1)是不合理的,因而才出现LALR(1)分析方法。

可以适当利用物理意义对二义性文法进行冲突处理

有时候二义性文法相较于无二义性文法来说,少了很多非终结符,这样进行LR(0)分析时也会方便很多,减少很多状态,
【编译原理】自底向上分析方法——LR文法分析方法的总结
如图,左为有优先级的LR分析的树、中为二义性文法的LR分析的树、右为LL分析的树
可以看出,二义性文法的LR分析比有优先级的LR、LL分析方法都简洁高效,因而,在某些时候,权衡性能和效益、确保正确使用文法的情况下,可以适当的使用LR(0)对二义性文法进行分析。

二义性文法

(1)E->E + E
(2)E->E * E
(3)E->(E) 
(4)E-> id

在一下两个状态中

I7
E→ E + E·
E→ E· + E
E→ E·*E

I8
E→ E * E·
E→ E· + E
E→ E·*E

使用SLR分析方法构造SLR分析表:FOLLOW(E) = { +,,),id,$}
对于状态7:
当输入符号是 ‘+’ 时,状态7出现移入-规约冲突,因为+可以移入,同时+属于FOLLOW(E),可以进行归约动作r1
此时,根据物理意义,即加法的左结合律,a+b+c可以先a+b进行计算,所以此时不会进行移入操作,而是只进行归约操作。
当输入符号是 ‘ * ’ 时,状态7出现移入-规约冲突,因为
可以移入,同时属于FOLLOW(E),可以进行归约动作r2
此时,根据物理意义,即乘法的优先级,a+b
c需要先对b*c进行计算,所以此时不会进行归约操作,而是只进行移入操作。
故而状态7的冲突得到解决。
状态8同理,可自行尝试。

一直学,你只是个学生,但只需自创一招,你便是宗师