我正在深入解析,遇到了一个我不太了解的问题。我编写了以下语法:
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会提前终止推导。
答案 0 :(得分:3)
对于初学者来说,很高兴您发现我们的CFG工具非常有用!我的一些助教曾经有一段时间了,我们从中获得了很多成就。
您的语法确实是模棱两可的。这源于您的R非终结符:
R→b | RbR
通常来说,如果您的递归生产规则中有两个相同的非终结符副本,则会产生歧义,因为对于两次应用规则有多种选择。例如,在这种情况下,您可以通过先将R扩展为RbR,然后选择其中一个来导出bbbbb
由于该语法是模棱两可的,因此对于k的任何选择都不会是LL(k),因为所有LL(k)语法都必须是明确的。这意味着增强解析器的功能在这里无济于事。您需要重写语法以免歧义。
您在此处描述的非终结R会在其中生成奇数个b的字符串,因此我们可以尝试重新设计R以更直接地实现这一点。最初的尝试可能是这样的:
R→b | bbR
不幸的是,这不是LL(1),因为看到单个b之后,您不清楚应该应用第一个生产规则还是第二个生产规则。但是,它是LL(2)。
如果您想要LL(1)语法,则可以执行以下操作:
R→bX
X→bbX | ε
这可以通过放置单个b,然后根据需要放置尽可能多的可选b对来实现。