消除左递归

时间:2014-02-13 05:21:24

标签: parsing left-recursion top-down

所以我有一些语法对于自上而下的解析器不起作用,因为它已经离开了递归:

L::= A a | B b
A::= L b | a a
B::= b B b | b a

所以为了解决这个问题,我必须删除左递归。要做到这一点,我会做一些替代品:

L::= A a | B b
A::= A a b | B b b | a a (I plugged in the possible values of "L")
然后转向(我相信):

A::= a a A' | B b b
A'::= a b A' | ε

我很确定我在那里是正确的(如果我不是,也不会感到惊讶)。我正在努力的地方现在正在删除“B b b”中的左递归。我试过这么多方法,我认为它们中的任何一个都没有用。这是一个看起来最符合逻辑的,但也很丑陋(因此说它可能是错的)。从操纵B :: = b B b |开始b a

B::= b B b | b a
B::= b B' (they both start with b, so maybe i can pull it out?)
B'::= B b | a
B'::= b B' b | a (substituted B's value in)
B'::= b B" | a
B"::= b B" |a B" | ε

所以我想要展示最终的B将是什么:

B::= b B'
B'::= b B" | a
B"::= b B" | a B" | ε

这似乎太难看了,不正确。特别是因为我必须将其插入我创建的新“A”终端中。

有人可以帮帮我吗?不知道我是否正确地走这条路。我应该能够在之后创建一个LL(1)解析表(应该能够自己做这个部分)。

感谢。

1 个答案:

答案 0 :(得分:0)

在尝试从左侧扩展非终结符的解析器中,如果某些非终结符可以扩展为左侧自身的字符串,则解析器可以永久扩展该非终结符而不实际解析任何内容。这是递归。另一方面,如果非终结符号扩展为左侧有一些不同的非终结符号的字符串,只要没有扩展链产生左侧原始非终结符号的字符串,则完全没问题。同样地,如果非终结符号在扩展中并非一直向右,那就没关系了,只要它们不是一直到左边。

tl; dr B b bb B b没有任何问题。你已经删除了所有左递归。你不需要继续前进。