【发布时间】:2021-09-16 16:29:27
【问题描述】:
在这个例子中:
S -> aA
A -> Aa|b
上述文法生成的语言(字符串集)是无限的。有没有可能找到它的LR(0)状态机?
【问题讨论】:
标签: context-free-grammar shift-reduce-conflict
在这个例子中:
S -> aA
A -> Aa|b
上述文法生成的语言(字符串集)是无限的。有没有可能找到它的LR(0)状态机?
【问题讨论】:
标签: context-free-grammar shift-reduce-conflict
语法没有“a”LR(0) 状态。您可以为语法构造一个 LR(0) 状态机;那台机器有几个状态。
这是一个用于语法的 LR(0) 状态机,由 Grammophone 生成:
上面的状态机没有显示归约转移,但是可以从每个状态的项中推导出来;以 • 结尾的项目的状态是归约状态(状态 1、3、4 和 5)。由于 LR(0) 解析器可能不会参考下一个标记来决定是否进行约简,因此文法不是 LR(0);状态 3 既有转换又有归约 [注 1]。
虽然语法不是 LR(0),但 LR(0) 状态机仍然很重要,因为 SLR(1) 和 LALR(1) 解析器使用相同的状态机,它们具有完全相同的状态。因此,构建 SLR(1) 和 LALR(1) 解析器从构建 LR(0) 状态机开始。不同之处在于 SLR(1) 和 LALR(1) 解析器确实使用 (1) 前瞻符号来确定归约操作。使用这两种算法中的任何一种,都将解决状态 3 中的冲突,因为减少仅与b 的前瞻相关联,而状态机中没有过渡。
规范的 LR(1) 解析器不使用相同的状态机(在大多数情况下);在 CLR 解析器中,可能有两个状态具有相同的项目集。这有时可以解决冲突。但是在这个语法中是没有必要的。
只有具有前缀属性的语言才能是LR(0);换句话说,没有句子是另一个句子的前缀。 (将其称为“无前缀属性”可能更好,但这并不容易谈论。)为语言赋予前缀属性的最简单方法是为每个输入添加一个输入结束标记(通常符号为$)。输入结束标记必须是一个新符号,它不会出现在语法的任何地方。由于新语言中的每个句子都以$ 结尾,并且除了结尾之外没有句子包含$,因此一个句子不可能成为另一个句子的前缀。
所以要使这个语法为 LR(0),只需将规则 S -> a A 更改为 S -> a A $。这解决了状态 3 中的 shift-reduce 冲突,并且仍然产生无限语言。
【讨论】: