不同的解析算法之间的运行时差异是什么?

时间:2010-10-13 10:27:21

标签: algorithm parsing language-agnostic

有许多不同的解析算法(递归下降,LL(k),LR(k),LALR,......)。我发现很多关于不同语法的信息,不同类型的解析器都可以接受。但它们在运行时行为方面有何不同?哪种算法更快,使用更少的内存或堆栈空间?

或者换句话说 - 哪种算法表现最好,假设语法可以用于任何算法?

2 个答案:

答案 0 :(得分:6)

LR解析器恕我直言可以是最快的。基本上,他们使用令牌作为前瞻集或转换表的索引来决定下一步做什么(推送状态索引,弹出状态索引/调用缩减例程)。转换为机器代码,这只是一些机器指令。 Pennello在他的论文中详细讨论了这个问题:

Thomas J. Pennello:非常快速的LR解析。 SIGPLAN编译器构建研讨会1986:145-151

LL解析器涉及递归调用,它比简单的表查找慢一点,但它们可以非常快。

GLR解析器是LR解析器的推广,因此 比LR解析器慢。一个关键的观察是,大多数时候GLR解析器的行为与LR解析器完全相同,并且可以使该部分基本上以与LR解析器相同的速度运行,因此它们可以相当快。

您的解析器可能会花费更多时间将输入流分解为令牌,而不是执行解析算法,因此这些差异可能并不重要。

在将语法变为可用形式方面,以下是解析技术“使其变得简单”的顺序:

  • GLR(非常简单:如果你可以编写grammmar规则,你可以解析)
  • LR(k)(许多语法适合,极少数解析器生成器)
  • LR(1)(最常见[YACC,Bison,Gold,...]
  • LL(通常需要大量重新设计语法以消除左递归)
  • 手工编码的递归下降(对于简单的语法很容易编码;如果语法变化很大,很难处理复杂的语法和难以维护)

答案 1 :(得分:6)

我研究了LRSTAR和YACC之间的LR解析器速度。

1989年,我将论文"Optimization Of Parser Tables For Portable Compilers"中定义的矩阵解析器表与YACC解析器表(梳状结构)进行了比较。这些都是LR或LALR解析器表。我发现矩阵解析器表的速度通常是梳形解析器表的两倍。这是因为非终结转换(转到动作)的数量通常约为终端转换数量的两倍。矩阵表具有更快的非终结转换。但是,除了状态转换之外,解析器还有许多其他的事情,所以这可能不是瓶颈。

2009年,我将矩阵词法分析器表与flex生成的词法分析器表以及re2c生成的直接代码词法分析器进行了比较。我发现矩阵表的速度大约是flex生成表的两倍,几乎和re2c词法分析器一样快。矩阵表的好处是它们可以更快地编译直接代码表并且它们更小。最后,如果您允许矩阵表非常大(没有压缩),它们实际上可以比直接代码(re2c)表更快。有关显示比较的图表,请参阅:the LRSTAR comparison page

使用LRSTAR构建的编译器前端(没有预处理)每秒处理大约2,400,000行代码,这包括在解析和lexing时构建符号表和抽象语法树。使用DFA构建的词法分析器每秒处理30,000,000个令牌。使用DFA时,矩阵表驱动词法分析器还有另一个优点。词法分析器骨架可以用汇编语言重写。当我在1986年这样做时,词法分析器的速度是C代码版本速度的两倍。

我对LL解析器速度或递归下降解析器速度没有多少经验。抱歉。如果ANTLR可以生成C ++代码,那么我可以对其解析器进行速度测试。