来看一个简单的例子,语法为:
所有的状态及转移关系见下:
注意状态 I5 和 I6 中都出现了两个 shift/reduce 冲突。以 I5 为例,它同时有以下两条形态:
现在按前面介绍的方法来确定该执行的动作。首先定义符号 * 和 + 的优先级分别为 0 和 1 (数字越小优先级越高),且定义两个符号都是左结合的。
再来看上面第一条形态,其产生式右边的符号串为 E + E ,这个符号串里最右边的、且定义了优先级的符号就是 + ,其优先级为 1 。而此形态的 lookahead (也就是 * )的优先级为 0 ,高于 + 。因此,选择的动作为 shift 。
再按上面的方法消除其他 shift/reduce 冲突,确定 I5 和 I6 的动作如下(其中方括号内的是被放弃的动作):
LL(1) 分析法的解析过程中,在挑选产生式的时候只利用下一个读入符号(lookahead)的信息,而 LR(1) 分析法不仅仅是利用下一个读入符号的信息,事实上,它几乎利用了前面读入过的所有的符号的信息。 LR(1) 分析法的解析力量和适用范围远大于 LL(1) 分析法,在引入符号优先级解决常见的 shift/reduce 冲突情况后,它可以解析目前几乎所有的程序语言。
到了这里,可以圆满的回答上一章最后的两个问题了: