为什么左递归不好?


20

在编译器设计中,为什么应在语法中消除左递归?我正在读这是因为它可能导致无限递归,但是对于正确的递归语法来说,它也不是真的吗?


2
通常,编译器使用自上而下的解析。如果您有左递归,则解析器将进入无限递归。但是,在右递归中,解析器可以看到到目前为止所拥有的字符串的前缀。因此,它可以检查推导是否进行得“太远”。当然,您可以交换角色并从右侧解释表达式,从而使右递归变差,而左递归变好。
Shaull

6
左递归不好,因为在过去,当计算机具有16 KB的RAM时,最常用的解析器生成器无法应对它。
Andrej Bauer

Answers:


15

左递归语法不一定是一件坏事。可以像使用LR解析器一样,使用堆栈轻松地解析这些语法以跟踪已解析的短语。

回想一下,CF语法的左递归规则 的形式为:G=(V,Σ,R,S)

ααβ

αVβVΣ(V,Σ,R,S)

βαα

每当语法解析器(从词法分析器)接收到一个新的终端时,该终端就被推到栈顶:此操作称为shift

每当规则的右手边被堆栈顶部的一组连续元素匹配时,此组将被代表新匹配短语的单个元素替换。这种替换称为减少

使用正确的递归语法,堆栈可以无限期增长,直到发生归约为止,从而极大地限制了解析的可能性。但是,左递归将使编译器更早地生成缩减(实际上是尽快)。有关更多信息,请参见Wikipedia条目


如果您定义变量,这将有所帮助。
Andrew S

12

考虑以下规则:

example : 'a' | example 'b' ;

现在考虑一个LL解析器,它试图匹配'b'与此规则不匹配的字符串。由于'a'不匹配,它将尝试匹配example 'b'。但是为了做到这一点,它必须匹配example……这就是它最初试图做的。尝试永远查看是否可以匹配可能会陷入困境,因为它一直试图将相同的令牌流匹配到相同的规则。

为了防止这种情况,您要么必须从右边进行解析(就我所见,这是非常不常见的,并且将使正确的递归成为问题),人为地限制了允许的嵌套量,或者进行匹配递归开始之前需要一个令牌,因此总会有一个基本情况(即所有令牌都被消耗掉了,仍然没有完全匹配的情况)。由于右递归规则已经执行了第三条规则,因此它没有相同的问题。


3
您有点盲目地认为解析必然是天真的自上而下的解析。
reinierpost

我着重介绍了一种相当常见的解析方法的一个陷阱,这个问题很容易避免。当然可以处理左递归,但是保留它会在使用它的解析器类型上产生几乎总是不必要的限制。
cHao 2013年

是的,这是一种更具建设性和实用性的方式。
reinierpost

4

(我知道这个问题现在已经很老了,但是如果其他人也有同样的问题...)

您是在递归下降解析器环境中询问吗?例如,对于语法expr:: = expr + term | term,为什么要这样(左递归):

// expr:: = expr + term
expr() {
   expr();
   if (token == '+') {
      getNextToken();
   }
   term();
}

有问题,但不是(正确的递归)吗?

// expr:: = term + expr
expr() {
   term();
   if (token == '+') {
      getNextToken();
      expr();
   }
}

看起来像是两个版本的expr()呼叫本身。但是重要的区别是上下文-即进行该递归调用时的当前令牌。

在左递归的情况下,expr()使用相同的令牌连续调用自身,并且没有任何进展。在正确的递归情况下,term()在到达之前,它将消耗调用中的一些输入和PLUS令牌expr()。因此,在这一点上,递归调用可以调用term,然后在再次到达if测试之前终止。

例如,考虑解析2 + 3 +4。左递归解析器expr()在卡在第一个标记上的同时进行无限次调用,而右递归解析器在expr()再次调用前消耗“ 2 +” 。第二个expr()匹配“ 3 +”的呼叫expr(),仅剩下4的呼叫。4匹配一个术语,并且解析终止,而不再调用expr()


2

从野牛手册:

“任何类型的序列都可以使用left递归或right递归来定义,但是您应该始终使用left递归,因为它可以解析具有有限堆栈空间的任意数量的元素序列。Right递归会占用Bison堆栈中的空间。 ”,它与序列中元素的数量成比例,因为在规则一次可以应用一次之前,所有元素都必须移到堆栈上。有关此的进一步说明,请参阅Bison Parser算法。”

http://www.gnu.org/software/bison/manual/html_node/Recursion.html

因此,这取决于解析器的算法,但是如其他答案所述,某些解析器可能根本无法使用左递归

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.