SLR(1) 和 LALR(1) 语法冲突
SLR(1) and LALR(1) grammar conflicts
假设你有一个语法 G,我们为它找到了一个 LR(1) 自动机。我们可以通过状态合并和转换规则将其转换为 LALR(1) 或 SLR(1) 解析器,但可能会出现冲突。
我的问题如下:所有问题都必须出现在合并状态吗?未合并的非冲突 LR(1) 状态是否可能在 LALR(1) 或 SLR(1) 自动机中发生冲突?
有趣的问题!答案是
- 如果语法是 LR(1),则 LALR(1) 解析器中的任何冲突都必须发生在合并状态中,但是
- 如果一个文法是LR(1),LR(1)状态可能会出现未合并的冲突。
对于第一点,假设你有一个 LR(1) 语法,所以你可以形成它的 LR(1) 解析器。我们可以通过将具有相同产生式的所有状态合并在一起,忽略先行,将其转换为 LALR(1) 解析器。如果你有一个不与任何东西合并的 LR(1) 状态,那么这个 LR(1) 状态会逐字地出现在 LALR(1) 解析器中。并且由于 LR(1) 状态没有 shift/reduce 或 reduce/reduce 冲突,相应的 LALR(1) 解析器状态不会有任何冲突。
在 SLR(1) 前端,您最终可能会遇到不会发生 LR(1) 状态合并的状态,但存在 reduce/reduce 冲突。这背后的直觉是你可以在 LR(1) 解析器中有一个没有 reduce/reduce 冲突的状态,因为前瞻有足够的细节来解决冲突,但是当从 LR(1) 切换到 SLR(1) 时并扩展前瞻集,我们不小心引入了 reduce/reduce 冲突。这是发生这种情况的语法示例:
- S → aTb |一个R | cT
- T → d
- R→d
这是 LR(1) 配置集:
(1)
S' -> .S [$]
S -> .aTb [$]
S -> .aR [$]
S -> .cT [$]
(2)
S' -> S. [$]
(3)
S -> a.Tb [$]
S -> a.R [$]
T -> .d [b]
R -> .d [$]
(4)
T -> d. [b]
R -> d. [$]
(5)
S -> aT.b [$]
(6)
S -> aTb. [$]
(7)
S -> aR. [$]
(8)
S -> c.T [$]
T -> .d [$]
(9)
T -> d. [$]
(10)
S -> cT. [$]
这些是您在 SLR(1) 解析器中拥有的相同项目集。另请注意,FOLLOW(T) = {$, b}。这意味着 LR(1) 状态
(4)
T -> d. [b]
R -> d. [$]
转换为SLR(1)状态
(4)
T -> d. [b, $]
R -> d. [$]
在 $.
上有 reduce/reduce 冲突
假设你有一个语法 G,我们为它找到了一个 LR(1) 自动机。我们可以通过状态合并和转换规则将其转换为 LALR(1) 或 SLR(1) 解析器,但可能会出现冲突。
我的问题如下:所有问题都必须出现在合并状态吗?未合并的非冲突 LR(1) 状态是否可能在 LALR(1) 或 SLR(1) 自动机中发生冲突?
有趣的问题!答案是
- 如果语法是 LR(1),则 LALR(1) 解析器中的任何冲突都必须发生在合并状态中,但是
- 如果一个文法是LR(1),LR(1)状态可能会出现未合并的冲突。
对于第一点,假设你有一个 LR(1) 语法,所以你可以形成它的 LR(1) 解析器。我们可以通过将具有相同产生式的所有状态合并在一起,忽略先行,将其转换为 LALR(1) 解析器。如果你有一个不与任何东西合并的 LR(1) 状态,那么这个 LR(1) 状态会逐字地出现在 LALR(1) 解析器中。并且由于 LR(1) 状态没有 shift/reduce 或 reduce/reduce 冲突,相应的 LALR(1) 解析器状态不会有任何冲突。
在 SLR(1) 前端,您最终可能会遇到不会发生 LR(1) 状态合并的状态,但存在 reduce/reduce 冲突。这背后的直觉是你可以在 LR(1) 解析器中有一个没有 reduce/reduce 冲突的状态,因为前瞻有足够的细节来解决冲突,但是当从 LR(1) 切换到 SLR(1) 时并扩展前瞻集,我们不小心引入了 reduce/reduce 冲突。这是发生这种情况的语法示例:
- S → aTb |一个R | cT
- T → d
- R→d
这是 LR(1) 配置集:
(1)
S' -> .S [$]
S -> .aTb [$]
S -> .aR [$]
S -> .cT [$]
(2)
S' -> S. [$]
(3)
S -> a.Tb [$]
S -> a.R [$]
T -> .d [b]
R -> .d [$]
(4)
T -> d. [b]
R -> d. [$]
(5)
S -> aT.b [$]
(6)
S -> aTb. [$]
(7)
S -> aR. [$]
(8)
S -> c.T [$]
T -> .d [$]
(9)
T -> d. [$]
(10)
S -> cT. [$]
这些是您在 SLR(1) 解析器中拥有的相同项目集。另请注意,FOLLOW(T) = {$, b}。这意味着 LR(1) 状态
(4)
T -> d. [b]
R -> d. [$]
转换为SLR(1)状态
(4)
T -> d. [b, $]
R -> d. [$]
在 $.
上有 reduce/reduce 冲突