删除左递归

时间:2010-04-16 10:06:26

标签: compiler-construction grammar

以下语法已经离开了递归

E= E+T|T
T= T*F|F
F= a|b|c

如何删除它?它有什么一般程序吗?

4 个答案:

答案 0 :(得分:13)

是的,有一般程序,例如, wikipedia

E = TE'
E'= (e) | +TE'
T = FT'
T'= (e) | *FT'
F = a | b | c

应该提到的是,这会从左到右改变+*的相关性。也就是说,在a + b + c被解析为(a + b) + c之前,它现在被解析为a + (b + c)

这对于加法和乘法来说不是问题,但例如,它对于减法和除法来说就是一个问题。

维基百科文章详细介绍了左递归删除程序及其复杂性。

答案 1 :(得分:3)

例如,一般程序可在Wikipedia找到。我将演示E = E+T|T

E是左递归非终端。 +T是非空序列(alpha)。 T是不以E(beta)开头的序列。

我们为“休息”创建一个新的非终结符,即。非空序列。这会处理递归。

E' = epsilon|+TE'

我们修改原始规则以使用新的非终结符来处理递归。

E = TE'

答案 2 :(得分:2)

正如其他人所指出的,有一个通过右递归替换左递归的一般过程。其他答案很好地展示了如何使用该通用过程来删除给定语法中的左递归。

这是一个以特定于该语法的方式重构给定语法的解决方案。

E= T+E|T
T= F*T|F
F= a|b|c

答案 3 :(得分:1)

制作

E = E+T
  | T
T = T*F
  | F
F = a|b|c

转到

E= T ('+' T)*
T= F ('*' F)*
F= a|b|c

保持使用A(E,T)处理第一个E disjunct的相同处理。新版本使用:

ret = T1;
while(set.more()) ret = A(ret, set.pop_front().T);