一:SLR(1)的引入
由于LR(0)分析法中无法避免的出现了两种冲突即其规范族中会有含有冲突的项目集:移进归约和归约归约冲突,直觉上,对于有冲突的状态,向前查看一个符号,以确定采用的动作。例如:
对于项目集:S-rD·
D-D·,i
产生了移进归约冲突,按照SLR(1)的解决方法,向前查看一个符号,看其是不是S的后跟符号(FOLLOW(S)),若否则移进,是则归约
一个LR(0)归约族中含有如下的项目集(状态)S S={X-a·bp,A-r·,B-w·}
若有:FOLLOW(A)与FOLLOW(B)的交集为空
FOLLOW(A)与{b}的交集为空
FOLLOW(B)与{b}的交集为空
若S面临输入的符号为a,
1:a=b,则移进
2:a属于FOLLOW(A),则用第二产生式归约
3:a属于FOLLOW(B),则用第三产生式归约
4:否则报错
若一个文法的LR(0)分析表中所含有的动作冲突都能用上述方法解决,则这个文法是SLR(1)文法
二:SLR(1)不能避免的冲突
虽然SLR(1)能解决上述说明的一些冲突,但是也有不能解决的冲突,本文的写作目的就是讨论一下学习过程中所发现的一些不能解决的冲突,正是这些冲突才促使了LR(1)的产生
1:I5={S-ae·c,A-e·c},FOLLOW(A)={c,d},
在I5,FOLLOW(A)与{c}的交集不为空,因此该冲突不能用SLR(1)方法解决,只能考虑用LR(1)方法解决
2:由于用SLR(1)方法解决动作冲突候,对于归约项目A-a·,只要当前面临的输入符号为a属于FOLLOW(A)时,就确定采用产生式进行归约,但是如果栈里的符号串为pa归约为pA,再移入当前符号a,则栈里变为pAa,但实际上pAa未必为文法规范句型的活前缀
例如:
在识别表达式文法的活前缀DFA中,在项目集I2存在移进归约冲突,即{E-T·,T-T·*F}若栈中符号为#T,当前输入符号为(,而且(属于FOLLOW(E),按照SLR(1)的方法就会引用第一产生式进行归约,归约后栈中符号为#E,而再加上当前符号(,栈中为#E(不是表达式文法规范句型的活前缀。
总结,通过以上两种无法避免的冲突,可以说,虽然SLR(1)方法对LR(0)有所改进,但仍存在着很多冗余的归约,就是不应该归约的时候把栈中元素给归约了,造成了2中的失掉活前缀的错误,所以说虽然可以通过求FOLLOW集的办法解决一些冲突,但是一方面求FOLLOW集之后,并不能保证一定能满足应用SLR(1)方法的条件,另一方面,即使应用了该方法,也有可能执行的是冗余的归约,从而造成错误。所以这些方面促进了引入LR(1)分析法