【问题标题】:Definition of Shift/Reduce conflict in LR(1) parsingLR(1) 解析中 Shift/Reduce 冲突的定义
【发布时间】:2016-03-24 13:04:20
【问题描述】:

表述是否正确:

" 当且仅当存在项时,LR(1) 解析器中才会发生移位归约冲突:

A -> 阿尔法。

A -> 阿尔法。测试版

这样,Follow(A) 不会与 First(beta) 脱节。

其中 A 是非终结符,alpha 和 beta 可能是语法符号的空序列。”

(直觉上这是因为没有办法根据栈顶和lookahead来判断到底适合shift还是reduce)

注意:如果你们认为这取决于第一/后评论定义的任何细节,我会提供。

【问题讨论】:

  • 是的,这就是它的定义方式。
  • 您是在问这是否必然是 S/R 冲突,还是每个 S/R 冲突都有这种形式?
  • @rici 好点,我的意思是如果每个 S/R 冲突都有这种形式

标签: parsing compiler-construction theory lr


【解决方案1】:

不,这种说法不正确。

假设在一些语法中:

  • 产品包括:
    • A → α
    • A→αβ
  • 跟随(A) ∩ FIRST(β) ≠ ∅

对于具有移位减少冲突的语法来说,这还不够,因为它要求非终结符 A 在前瞻包含 FOLLOW(A ) ∩ FIRST(β)。

因此,只有当我们要求对语法进行归约,或者至少不包含任何无法到达或无用的产生式时,上述足以产生移位归约冲突。

但是,上述条件不是必要的,因为没有要求移位和减少适用于相同的非终结符,甚至“相关”非终结符。考虑以下简单语法:

prog → stmt
prog → prog stmt
stmt → expr
stmt → func
expr → ID
expr → '(' expr ')'
func → ID '(' ')' stmt

该语法(并非模棱两可,因为它发生)在包含 ID . ( 的状态中存在移位减少冲突,因为 ID 可以减少到 expr 然后 stmt,或者 ( 可以被转移为func → ID '(' ')' stmt 的一部分。


虽然这是一个侧面,但值得注意的是,FOLLOW 集仅用于 SLR(k) 语法的构造。规范的 LR(k) 构造——甚至 LALR(k) 构造——将成功地为语法生成解析器,其中使用 FOLLOW 集而不是完整的前瞻计算将指示(不存在)移位减少冲突。经典示例,取自 Dragon 书(我的副本中的示例 4.39),使用更有意义的非终端名称进行编辑:

stmt → lvalue '=' rvalue
stmt → rvalue
lvalue → '*' rvalue
lvalue → ID
rvalue → lvalue

这里,FOLLOW(rvalue) 是 {=, $},因此状态为 {stmt → lvalue · '=' rvalue, @ 987654331@},看来减少到rvalue 是可能的,导致错误的移位减少冲突。

【讨论】:

  • 这是一个很好的答案。谢谢你。为了使我的陈述/定义正确,可以对其进行修改以指定语法不包含冗余/无法达到的减少,并且进一步将项目修改为 A -> α。和 B -> α.β 例如不需要 LHS 在每种情况下都相同?在您发现此评论后,将在稍后投票/接受。
  • @N.McA.:您评论中的条件不一定是移位减少冲突。它适用于我的第二个示例,但在使用规范 LR(1) 解析器(也不是 LALR(1) 解析器)的语法中没有移位归约冲突。
  • 啊,我正要评论询问是否会这样。我认为 SLR(1) 解析器是否正确,我们确实使用跟随集来确定归约操作,这会是冲突吗?这意味着 SLR 和 Canonical LR 接受的语法集是不同的。
  • 另外,另一个我没有提到的 S/R 冲突的情况是 A -> α。和 A -> α.β,其中 β 派生出空字符串。
  • 而且,是的,SLR(1) 是 LR(1) 的严格子集。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多