所以我有一些语法对于自上而下的解析器不起作用,因为它已经离开了递归:
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)解析表(应该能够自己做这个部分)。
感谢。
答案 0 :(得分:0)
在尝试从左侧扩展非终结符的解析器中,如果某些非终结符可以扩展为左侧自身的字符串,则解析器可以永久扩展该非终结符而不实际解析任何内容。这是递归。另一方面,如果非终结符号扩展为左侧有一些不同的非终结符号的字符串,只要没有扩展链产生左侧原始非终结符号的字符串,则完全没问题。同样地,如果非终结符号在扩展中并非一直向右,那就没关系了,只要它们不是一直到左边。
tl; dr B b b
或b B b
没有任何问题。你已经删除了所有左递归。你不需要继续前进。