总览
LR分析方法的关键是识别出句柄(最左直接短语),根据不同的寻找句柄的方法,就得到了不同的规范归约方法。下面四种依次递进,前者为后者基础。
这四种方法的区别就在于产生式归约(上面说的识别句柄)的条件。
首先是最简单的LR(0)文法,只要项目集中出现了归约项目,那么对后面所有字符都采取归约操作,所以可以看到LR(0)分析表某些状态整行都是一样的rx
.(r for reduce, 归约)
如果所有项目集中,都不存在 移进-归约冲突 和 归约-归约冲突,那么就说这个文法是LR(0)的。
如果存在这两种冲突,就使用SLR方法,对所有的归约项目来说,只有遇到该项目的FOLLOW
集中的元素时才进行归约。如,对于一个项目集
I = { X -> α·bβ, A -> α·, B -> α· }
第一个是移进项目,第二三是归约项目,存在归-归冲突,如果下一输入符号是b,还存在移-归冲突。SLR的解决方法是,考察归约项左部符号的FOLLOW
集, 只有当下一输入符号是对应项目的FOLLOW
集中元素时,才决定进行归约。这时,为了避免移-归冲突和归-归冲突,需要保证不同归约项的FOLLOW
集和移进项目等待的符号(·
后面的终结符)交集为空。就上面说的那个项目集而言,b
可以认为是移进项目X -> α·bβ
的移进信号, FOLLOW(A) FOLLOW(B)
分别是归约项目A -> α·, B -> α·
的归约信号。可以看到,归约项目不再是整行都是归约,而是某几个符号(对应FOLLOW集)才是归约操作,如:
在同一行内,归约信号对应归约操作,移进信号对应移进操作,如:
如果给定文法的SLR分析表中不存在有冲突的动作(移进信号和归约信号交集为空),那么该文法称为SLR文法。
如P113的例子,SLR方法同样有问题,即移进信号和归约信号的交集不为空的情况。SLR方法将归约项目的FOLLOW集合作为归约信号
,实际上扩大了范围。归约信号必然在FOLLOW
集合中,但是FOLLOW
集中元素不全是归约信号。此时用到了下面的LR(1)方法。
首先需要知道,LR(1)项的定义,求LR(1)项的等价项。余下的过程同上。由于LR(1)项目很多,所以进一步使用LALR方法对某些状态进行合并。具体内容在后面。
LR(0)分析法
最为简单,是后面几个的基础。
首先明确,分析法的
- 目标:构造分析表(包括后几种分析法)
- 已有信息:给定的文法(如P105文法5.8)
- 所用算法:将文法转为项目;构造项目的闭包;构造拓广文法的LR(0)项目集规范族(参考构造算法P107);根据规范族生成分析表
这里介绍构造闭包、构造项目集规范族的算法
构造项目集规范组
- 根据文法,写出该文法的所有项目(参考P104-P105)
- 将等价的项目放到一起,作为一个项目集规范组(参考P105)。如
S -> a·A
,意思是我已经得到了符号串a
, 下面我期待的是A
。根据文法中A
的产生式,期待A
也就等价于期待A
所能得到的产生式。假定有产生式A -> γ
, 那么S -> a·A
等价的项目就包括A -> ·γ
。当然,如果γ
开始符号还是非终结符号,还要继续上述过程。总之就是,如果·
后面是非终结符,就要把这个非终结符的所有产生式前面加上·
添加到这个项目集中。重复这个过程,直到项目集不再增大。(参考P107)
构造项目集规范族
P107下面构造算法。
规范族生成分析表
前面已经得到的项目集规范族。给每个项目集编号,将箭头表示的关系转化为表格即可。
例如:
项目集已经编号,箭头上带有符号,表示前后的转换过程。
ACTION表对应的都是终结符;GOTO都是非终结符。
ACTION表中,s for shift, 转换;r for reduce, 归约
GOTO表中数字意思是状态,和状态列数字一致;
ACTION表中s
后面的数字表示状态;r
后面的数字是下面产生式的编号,表示用这个编号对应的产生式进行归约。
SLR分析法
LR(1)分析法
按照同样的过程,构造LR(1)项目集,构造DFA,构造分析表。
注意上面LR(1)项目集闭包算法中红字部分,for (FIRST(βa)中的每个符号)
,β
是非终结符
B
后面的那一项,可以为空。
试着将P115的例5.13做一下,得到项目集规范组和分析表。注意,在求项目的等价项目时要小心。
LALR分析法
观察LR(1)分析法得到的项目集状态族可以看到,I8 I9, I4 I7, I3 I6
除了展望符,前面的产生式是一样的。把这样的状态集称为同心状态集。由于LR(1)方法得到的状态太多,LALR方法尝试对同心状态集进行合并。
合并同心项目集可能会带来两个问题:
1.产生归约-归约冲突
这里状态I6 I9
是同心项目集。当下一个符号是d
时,对I6
来说,将栈顶的c归约为A;对I9
来说,将栈顶的c归约为B。下一个符号是e
时同理。这样就产生了归约-归约冲突。不过,合并同心状态集不会产生移进-归约冲突。 因为合并的是展望符,而展望符只在归约时起作用,在移进时不起作用。
2.推迟错误的发现
会推迟错误的发现,但最终还是会发现错误。
LALR分析法可能会作多余的归约动作,但绝不会作错误的移进操作。
LALR方法的特点:
- 形式上与LR(1)相同
- 大小上与LR(0)/SLR相当
- 分析能力介于SLR和LR(1)二者之间
SLR < LALR(1) < LR(1)
因为推迟了某些错误的发现,因此弱于LR(1);同时LALR对归约信号的划分比SLR更细致,因此又强于SLR。 - 合并后的展望符集合仍为
FOLLOW
集的子集