在使用一种编程语言构建解析器时,我会从中选择一种或另一种而赚到什么而又失去什么?
在使用一种编程语言构建解析器时,我会从中选择一种或另一种而赚到什么而又失去什么?
Answers:
我将对LL和LR解析进行比较,以得出许多标准:
复杂
LL在这里获胜,不负众望。您可以轻松地手写LL解析器。实际上,这通常是做得到的:Microsoft C#编译器是一个手写的递归下降解析器(在此处提供源代码,以查找Patrick Kristiansen发表的评论-博客文章也很有趣)。
LR解析使用一种违反直觉的方法来解析文本。它可以工作,但是我花了一些时间来思考它是如何工作的。因此,手工编写这样的解析器很困难:您或多或少会实现LR解析器生成器。
概论
LR在这里胜出:所有LL语言都是LR语言,但是LR语言比LL语言更多(如果可以用LL解析器解析,则语言是LL语言,如果可以用LL解析器解析,则语言是LR语言。 LR解析器)。
LL有许多麻烦之处,几乎在实现任何编程语言时都会打扰您。请参阅此处以获取概述。
有一些明确的语言不是LR语言,但是很少见。您几乎从未遇到过此类语言。但是,LALR确实存在一些问题。
LALR或多或少是LR解析器缩小表规模的一种手段。LR解析器的表通常可以增长很多。LALR解析器放弃了解析所有LR语言的能力,以换取较小的表。大多数LR解析器实际上使用LALR(尽管不是秘密地,您通常可以确切地找到它实现的内容)。
LALR可以抱怨移位减少和减少减少冲突。这是由表入侵引起的:它会将相似的条目“折叠”在一起,因为大多数条目为空,所以可以工作,但是当它们不为空时会产生冲突。这些错误是不自然的,很难理解,并且修复通常很奇怪。
编译器错误和错误恢复
LL在这里赢了。在LL解析中,通常很容易发出有用的编译器错误,尤其是在手写解析器中。您知道接下来的期望,因此,如果没有出现,您通常会知道出了什么问题以及最明智的错误是什么。
另外,在LL解析中,错误恢复要容易得多。如果输入解析不正确,您可以尝试略过一点,找出其余输入是否解析正确。例如,如果某些编程语句格式错误,则可以跳过并分析下一条语句,这样就可以捕获多个错误。
使用LR解析器,这要困难得多。您可以尝试扩充语法,以便它接受错误的输入并在出现问题的区域中打印错误,但这通常很难做到。以非LR(或非LALR)语法结尾的机会也会增加。
速度
速度与解析输入(LL或LR)的方式并不是真正的问题,而是结果代码的质量和表的使用(表可用于LL和LR)。因此,LL和LR在这方面具有可比性。
链接
这是指向同时将LL和LR对比的站点的链接。查找底部附近的部分。