【问题标题】:Isn't an LR(0) parser using lookaheads as well?LR(0) 解析器不是也使用前瞻吗?
【发布时间】:2015-03-14 13:35:32
【问题描述】:

LL(1)-解析器需要一个前瞻符号来决定使用哪个产生式。这就是为什么我一直认为使用术语“前瞻”的原因,当解析器查看下一个输入标记而不“消耗”它时(即它仍然可以通过下一个操作从输入中读取)。然而,LR(0) 解析器让我怀疑这是正确的:

我见过的每个 LR(0) 解析器示例也使用下一个输入标记来决定是移位还是减少。 在减少的情况下,不消耗输入令牌。

我使用免费软件工具“ParsingEmu”生成 LR 表并在下面对“aab”一词执行 LR 评估。如您所见,列标题包含标记。从评估中,您可以看到解析器正在通过查看下一个输入标记来决定使用哪一列。但是当解析器在步骤 4 - 6 中减少时,输入不会改变(尽管解析器在执行到下一个状态的转换时需要知道下一个输入标记“$”)。

语法:

S -> A
A -> aA
A -> b

表:

评价:

由于我的困惑,现在我做了以下假设:

  1. 我对“前瞻”(前瞻 = 输入令牌不被消耗)定义的假设是错误的。对于 LL 解析器或 LR 解析器,前瞻只是意味着两种不同的东西。如果是这样,那么“前瞻”如何定义?

  2. LR 解析器具有(从理论的角度来看,当您使用下推自动机时)额外的内部状态,它们通过将输入令牌放入堆栈来消耗输入令牌,因此能够进行移位-通过查看堆栈来减少决策。

  3. 上面显示的评估是 LR(1)。如果为真,LR(0) 评估会是什么样子?

现在什么是正确的,1、2 或 3 还是完全不同的?

【问题讨论】:

  • How can an LR(0) parser ever leave state 0? 的可能重复项(我自己的问题)
  • 可以分享解析动车组的链接吗?
  • 对不起,ParsingEmu 似乎完全从网络上消失了。我只能找到提到它的论文。

标签: parsing compiler-construction ll lr shift-reduce


【解决方案1】:

准确很重要:

LR(k) 解析器使用当前解析器状态和 k 前瞻符号来决定是否reduce,如果是的话,由哪个生产。

它还使用移位转换表来决定在移位下一个输入标记后它应该移动到哪个解析状态。无论 k 的值如何,移位转换表都由当前状态和正在移位的(单个)令牌作为键。

如果在给定的解析器状态下,可能同时产生移位和归约动作,则解析器存在移位/归约冲突,并且无效。因此,上述两个确定理论上可以非确定性地进行。

如果在给定的解析器状态下,无法进行归约并且下一个输入符号无法移动(即,该输入符号的状态没有转换),则解析失败并且算法终止。

另一方面,如果移位转换导致指定的接受状态,则解析成功并且算法终止。

这意味着,前瞻用于预测应该应用哪些缩减(如果有)。在 LR(0) 解析器中,必须在读取下一个输入标记之前做出转移(更准确地说,尝试转移)的决定,但要计算转移到 do 的状态读取令牌后,如果无法移位,此时将发出错误信号。


LL(k) 解析器必须在看到非终结符后立即预测哪个产生式替换非终结符。基本 LL 算法从包含 [S, $](从上到下)的堆栈开始,并执行以下任何适用的操作,直到完成:

  • 如果栈顶是非终结符,则将栈顶替换为该非终结符的一个产生式,使用接下来的 k 个输入符号来决定哪个(不移动输入光标),然后继续。

  • 如果栈顶是终端,则读取下一个输入标记。如果是同一个终端,则弹出堆栈并继续。否则,解析失败,算法结束。

  • 如果堆栈为空,则解析成功并且算法完成。 (我们假设在输入的末尾有一个唯一的 EOF 标记 $。)


在这两种情况下,前瞻具有相同的含义:它包括在不移动输入光标的情况下查看输入标记。

如果k为0,那么:

  • LR(k) 解析器必须在不检查输入的情况下决定是否进行归约,这意味着任何状态都不能有两个不同的归约动作或一个 reduce 和一个 shift 动作。

  • LL(k) 解析器必须在不检查输入的情况下决定给定非终结符的哪个产生式适用。实际上,这意味着每个非终结符只能有一个产生式,这意味着语言必须是有限的。

【讨论】:

  • 我的问题图片中显示的解析是 LR(1) 解析器吗?
  • 但是语法将是 LR(0) 可解析的,因为在一种状态下它必须转换(状态 0 和 1)或归约(状态 3 和 4)?如果一个状态行根据列(= 标记)同时包含移位和减少操作,它就不是 LR(0) 可解析的?
  • @chansey: shift consumes 一个令牌,所以它必须读取它:) LR(0) 解析器不需要知道它将在它之前转换到哪个状态读取令牌;它只需要知道它会发生变化。一旦做出决定,就不可撤销;它不能决定减少是否更有意义。我想这似乎是不对称的,它是:解析过程完全是关于归约动作,因为目标是发现一个推导。移位只是一种说法,“这里不减少,尝试下一个输入点”。解析器状态也是如此,即...
  • ...一个实现细节,如果你喜欢的话。解析器的可观察动作是“发出推导步骤”和“使用输入令牌”,LR(0) 解析器必须先de the first before the second。更一般地说,LR(k) 解析器在发出以消费令牌结尾的派生之前最多可以进行 k 消费。
  • @kapil:LL 解析器有一个预测堆栈,它表示它期望接下来看到的内容。如果预测堆栈的顶部是非终端,则解析器需要决定要预测哪个非终端产品。然后它弹出非终端并推动生产的右侧。如果预测堆栈的顶部是终端,则解析器使用一个令牌,该令牌必须与堆栈顶部的预测令牌相同。如果是正确的标记,则弹出预测堆栈;否则它会声明一个错误。
猜你喜欢
  • 2018-03-30
  • 2013-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 2016-04-14
相关资源
最近更新 更多