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

Parsing LL解析器比LR解析器有什么优势?,parsing,parser-generator,lalr,ll,lr,Parsing,Parser Generator,Lalr,Ll,Lr,LL解析器与LR解析器相比有哪些优势可以保证它们在应用程序中的相对普及 根据,LR解析似乎比LL有优势: LR解析可以处理比LL解析更大范围的语言,并且在错误报告方面也更好,即当输入不符合语法时,它可以尽快检测语法错误。这与LL(k)(或者更糟糕的是,LL(*)解析器)相反,LL(k)解析器可能由于回溯而将错误检测推迟到语法的另一个分支,这通常会使错误更难跨具有长公共前缀的析取进行定位 注意:这不是家庭作业。当我发现Antlr是一个LL解析器生成器时,我感到很惊讶(尽管名称中有“LR!”。我想到

LL解析器与LR解析器相比有哪些优势可以保证它们在应用程序中的相对普及

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

LR解析可以处理比LL解析更大范围的语言,并且在错误报告方面也更好,即当输入不符合语法时,它可以尽快检测语法错误。这与LL(k)(或者更糟糕的是,LL(*)解析器)相反,LL(k)解析器可能由于回溯而将错误检测推迟到语法的另一个分支,这通常会使错误更难跨具有长公共前缀的析取进行定位


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

我想到的一个原因是,在LL范式中编写一种需要任意回溯(cough C++)的语言要容易得多。

根据我的个人经验(我在各种情况下都使用过这两种方法),最实际的区别是,使用LL(k),您可以更轻松地定义语法(因为它是自上而下的),而不必考虑LR解析器经常发生的许多可能的reduce-reduce或shift-reduce冲突。您唯一需要关心的是左递归,它必须转换为右递归


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

如果你必须手工编写一个,递归下降(LL)是你可以现实地做的事情;人们实际上不能手工构建L(AL)R解析器

考虑到现代解析器生成器将为您处理所有的解析器构造,并且空间不是什么大问题,我更喜欢LR解析器,因为您不必为了使语法对特定的解析器生成器有效而与语法进行太多的斗争(没有“删除所有左递归”的愚蠢之处)

事实上,我更喜欢使用上下文无关语法来解析任何内容。不用担心左递归。无需转移/减少冲突担忧。没有前瞻性限制


如果您想了解一个GLR解析引擎可以处理的语言范围(包括著名的难以使用LL/LALR语言、C++进行解析的语言),您可以查看。

如果您想要一个解析树/林,并且不介意黑匣子,GLR非常棒。它允许您键入任何您想要的内容,而不是静态地解决LR/LALR冲突,而代价是在解析时通过穷举测试检查歧义。有人说这是一个很好的权衡。IRABAXTER的DMS工具或ELKHOND,它有一个免费的C++语法,对于这类问题是有用的。对于一大类语言应用程序也很有用,但使用自顶向下的方法,生成名为LL(*)的递归下降解析器,该解析器允许语义谓词。我将在这里声明,谓词允许您在CFG之外解析上下文敏感语言,而无需证明。程序员喜欢在语法中插入动作,比如良好的错误处理,并且喜欢单步调试。我三个都很好。LL是我们手工做的,所以更容易理解。不要相信这个事实。也就是说,如果使用ANTLR进行大量回溯,那么使用LL(*)的错误确实更严重(PEG有这个问题)

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

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

ANTLR另一种T工具,用于LangR不是反LR的,但我也喜欢它;)


坦白地说,像许多80年代的年轻程序员一样,我不理解LALR,也不喜欢黑匣子(现在我挖掘GLR引擎的优点,但仍然更喜欢LL)。我构建了一个基于LL(k)的商业编译器,并决定构建一个工具来生成我手工构建的东西。ANTLR不是每个人都可以使用的,比如C++之类的边缘情况可以更好地处理GLR,但是很多人发现ANTLR适合他们的舒适区。自2008年1月以来,在ANTLRWorks中,ANTLR的二进制jar已经有13.4万次下载,源代码zips total(根据谷歌分析)。请参阅关于LL(*)的大量经验数据。

我所熟悉的唯一优点是,您可以轻松地手工编写LL解析器。LR解析器更难手工编写(通常使用解析器生成器)

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

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


谈论解析器(而不是语法):LL(*)可以用简单的递归方法编写。这在我的书中是+1。@pst:是的,我只是希望“因为它们更容易实现”不是主要的优势注意,ANTLR中的“LR”只是代表“语言识别”,与它所接受的语法类别无关。实际上,在特伦斯·帕尔的心目中,它代表反LR。至少我记得有一次采访他时,他承认这并非偶然。他说他创建ANTLR是因为他觉得几乎完全关注LR解析是一个大错误,他厌倦了告诉所有人LR很烂,没有人听,所以他决定创建世界上最好的解析器生成器