它实际上是 SLR,它使用合并的前瞻集。或者,更准确地说,SLR 解析表中每个 产生式 的前瞻集近似为产生式中最后一个符号的 FOLLOW 集,有效地忽略了上下文。
LALR 解析器已合并 states 相对于规范 LR 解析器。在 LR 和 LALR 中,与 SLR 相比,前瞻集的计算准确,但在 LALR 解析器的情况下,状态被合并,因此它具有与 SLR 解析器相同的状态(但不是相同的前瞻集) .
Wikipedia 文章中对 SLR 解析、LALR 解析和 Canonical LR 解析的区别进行了合理的讨论。有关详细信息,请参阅这些文章的参考资料。
无论您使用哪种解析器生成技术,如果语法需要更多前瞻,就会出现冲突。例如,以下语法需要两个 lokahead 符号来决定是移位还是减少 NAME:
prog → λ
prog → prog defn
defn → NAME :
defn → defn NAME
这里,如果名称后面没有冒号,则它是defn 的一部分,因此要决定是否移动名称,您不仅需要作为前瞻标记的名称,还需要 tge跟随令牌,第二个前瞻。
这是一个非常简单的语法,它不是 SLR(1),它可能会说明使用跟随集的问题。 (它直接来自 Dragon 的书,经常被用作 SLR(1) 语法不足的例子):
S → L = R
S → R
L → id
L → * R
R → L
这里,R 和 L 的 FOLLOW 集是相同的。 R 和 L 都包含 =,因为 * R = ... 是有效的,并且会减少到 L = ...,并且显然 R 和 L 都可以出现在 S 的末尾,因此两个 FOLLOW 集都包括输入结束标记。
接下来的问题是决定是否减少R → L。在L = R 中,我们应该将L 保留原样并移动=。但是 FOLLOW 集没有帮助,因为 R 可以跟随 =。所以在一个只使用 FOLLOW 集合的 SLR(1) 语法中,状态中存在移位/归约冲突:
S → L • = R
R → L •
在 LALR(1) 语法中不存在此冲突,因为在该状态下
产生式R → L 的前瞻集不包括=,因为产生式是从项目S → • R 中包含的,其前瞻是输入结束标记。