LL解析器比LR解析器有什么优势?

时间:2010-11-03 22:36:20

标签: parsing parser-generator lalr ll lr

LL解析器比LR解析器有哪些优势可以保证它们在today's parser generator tools中相对受欢迎?

根据Wikipedia,LR解析似乎比LL更有优势:

  

LR解析可以处理比LL解析更大范围的语言,并且在错误报告方面也更好,即它在输入不尽快符合语法时检测语法错误。这与LL(k)(或甚至更糟的LL(*)解析器)形成对比,LL(k)可能由于回溯而将错误检测推迟到语法的不同分支,通常使错误难以在具有长公共前缀的分离上进行本地化。

注意:这不是作业。当我发现Antlr是一个LL解析器生成器(尽管名字中有“LR”)时,我感到很惊讶。)。

6 个答案:

答案 0 :(得分:28)

如果你想要一个解析树/森林并且不介意黑盒子,那么GLR很棒。它允许您输入所需的CFG,但需要通过详尽的测试来检查分析时的歧义,而不是静态地解决LR / LALR冲突。有人说这是一个很好的权衡。 Ira Baxter的DMS工具或具有免费C ++语法的Elkhound对这类问题很有用。 ANTLR对于大类语言应用程序也很有用,但是使用自上而下的方法,生成称为LL(*)的递归下降解析器,允许语义谓词。我将在此处说明,谓词允许您解析超出CFG的上下文敏感语言。程序员喜欢将动作插入到语法中,例如良好的错误处理,以及单步调试。 LL擅长三种。 LL是我们手工操作的,因此更容易理解。不要相信wikipedia nonsense about LR being better at handling errors。也就是说,如果你使用ANTLR回溯很多,LL(*)的错误确实更糟(PEGs有这个问题)。

重新回溯。 GLR也推测(即回溯),就像PEG,ANTLR和任何其他非确定性策略一样。在任何非确定性LR状态下,GLR“分叉”子解析器以尝试任何可行的路径。无论如何,LL具有良好的错误处理环境。 LR知道它与表达式匹配,LL知道它是赋值中的表达式或IF - 有条件的; LR知道它可能存在但不确定 - 并且不确定性是它获得权力的地方。

GLR是O(n^3)最糟糕的情况。 packrat / PEG是O(n)最坏的情况。由于循环前瞻DFA,ANTLR为O(n^2),但实际上O(n)。没关系真的。 GLR足够快。

ANTLR AN 其他 T ool L ang R ecognition not not not not反LR,但我也喜欢那个;)

坦率地说,像80年代的许多年轻编码员一样,我不理解LALR并且不喜欢黑盒子(现在我挖掘了GLR引擎的美感但仍然喜欢LL)。我构建了一个基于商业LL(k)的编译器,并决定构建一个工具来生成我手工构建的内容。 ANTLR并不适合每个人,像C ++这样的边缘情况可能会更好地处理GLR,但很多人发现ANTLR适合他们的舒适区。自2008年1月以来,在ANTLRWorks中已经有134,000个ANTLR二进制jar下载量,以及源拉链总数(根据谷歌分析)。请参阅有关LL(*)的our paper,其中包含大量经验数据。

答案 1 :(得分:11)

如果你必须手动编码,递归下降(LL)是你可以现实地做的事情;人们不能手工制作L(AL)R解析器。

鉴于现代解析器生成器将为您处理所有解析器构造,并且该空间不是一个问题,我更喜欢LR解析器,因为您不必与语法争用,以使它们对您有效特定的解析器生成器(没有“删除所有左递归”的愚蠢)。

事实上,我更喜欢GLR parsers,它几​​乎可以用无上下文语法解析任何内容。没有左递归的担忧。没有转变/减少冲突的担忧。没有前瞻性的限制。

如果您想查看一个 GLR解析引擎可以处理的语言范围(包括着名的难以解析的LL / LALR语言,C ++),您可以查看{ {3}}

答案 2 :(得分:2)

根据我的个人经验(我在两种情况下都使用过),最实际的区别在于,使用LL(k),你可以更容易地定义语法(因为它是自上而下的)而不关心很多LR解析器经常发生的reduce-reduce或shift-reduce冲突。您唯一需要关心的是左递归,必须将其转换为正确的递归。

另一件事是,自上而下的方法通常意味着更高的复杂性(关于空间或时间),因为它必须在解析时存储整个树,并且它可以长大很多,直到解决歧义。

答案 3 :(得分:0)

我所熟悉的唯一优势是您可以轻松地手动编写LL解析器代码。 LR解析器很难手动编码(通常使用解析器生成器)。

答案 4 :(得分:0)

LL解析最坏情况复杂度为O(n ^ 4),而LR解析的最坏情况复杂度更好,O(n ^ 3)。

(但没有人会写O(n ^ 4)语法。)

https://en.wikipedia.org/wiki/Top-down_parsing

答案 5 :(得分:-1)

浮现在脑海中的一个原因是,在LL范例中使用需要任意回溯( cough C ++)的语言要容易得多。