如何解析这个简单的语法? big昧吗?

时间:2018-12-13 17:16:31

标签: parsing context-free-grammar ll

我正在深入解析,遇到了一个我不太了解的问题。我编写了以下语法:

S = R | aSc
R = b | RbR

其中S是开始符号。有可能表明abbbc是基于该语法的有效句子,希望这是正确的,但我可能完全误解了一些内容。如果我尝试使用递归下降来实现这一点,则在尝试使用左导数例如

解析abbbc时似乎遇到了问题
S => aSc
aSc => aRc

在这一点上,我本以为递归下降会在第二个生产中选择第一个选项,因为下一个标记是b导致:

 aRc => abc

,我们已经完成了,因为没有更多的非终结符了,这当然不是abbbc。证明abbbc有效的唯一方法是选择第二个选项,但先行回顾一下,我认为它将始终选择b。我不认为语法是模棱两可的,除非我错过了一些东西。那我做错了吗?

更新:我在https://web.stanford.edu/class/archive/cs/cs103/cs103.1156/tools/cfg/遇到了一个不错的衍生应用程序。我曾经做过一个健全的检查,以确认abbbc是一个有效的句子。

更多地考虑这个问题,是否可以说我不能使用LL(1)解析此语法,但实际上需要LL(2)是真的吗?提前两次,我可以正确选择第二个产品中的第二个选项,因为我现在也知道还有更多的令牌需要读取,因此选择b会提前终止推导。

1 个答案:

答案 0 :(得分:3)

对于初学者来说,很高兴您发现我们的CFG工具非常有用!我的一些助教曾经有一段时间了,我们从中获得了很多成就。

您的语法确实是模棱两可的。这源于您的R非终结符:

  

R→b | RbR

通常来说,如果您的递归生产规则中有两个相同的非终结符副本,则会产生歧义,因为对于两次应用规则有多种选择。例如,在这种情况下,您可以通过先将R扩展为RbR,然后选择其中一个来导出bbbbb

  1. 将左侧的R扩展为RbR,并将每个R转换为b,或者
  2. 将右R扩展为RbR,并将每个R转换为b。

由于该语法是模棱两可的,因此对于k的任何选择都不会是LL(k),因为所有LL(k)语法都必须是明确的。这意味着增强解析器的功能在这里无济于事。您需要重写语法以免歧义。

您在此处描述的非终结R会在其中生成奇数个b的字符串,因此我们可以尝试重新设计R以更直接地实现这一点。最初的尝试可能是这样的:

  

R→b | bbR

不幸的是,这不是LL(1),因为看到单个b之后,您不清楚应该应用第一个生产规则还是第二个生产规则。但是,它是LL(2)。

如果您想要LL(1)语法,则可以执行以下操作:

  

R→bX

     

X→bbX | ε

这可以通过放置单个b,然后根据需要放置尽可能多的可选b对来实现。