【问题标题】:How do recursive ascent parsers work?递归上升解析器如何工作?
【发布时间】:2009-05-30 14:32:56
【问题描述】:

递归上升解析器如何工作?我自己编写了一个递归 descent 解析器,但我不太了解 LR 解析器。我found on Wikipedia 只会让我更加困惑。

另一个问题是为什么递归上升解析器的使用不超过基于表的解析器。似乎递归上升解析器总体上具有更好的性能。

【问题讨论】:

  • +1 我一直在想同样的事情。递归下降解析器很容易理解,但很难做到正确。 LR 解析器很容易用生成器(如 YACC)编写,但我从来没有真正理解它是如何“在后台”工作的。
  • 快乐的“好问题”徽章 :)

标签: parsing recursion


【解决方案1】:

经典的dragon book 很好地解释了 LR 解析器的工作原理。如果我没记错的话,还有Parsing Techniques. A Practical Guide. 在那里你可以读到它们。维基百科中的文章(至少是介绍)是不正确的。它们是由 Donald Knuth 创建的,他在他的计算机编程艺术第 5 卷中对其进行了解释。如果您懂西班牙语,这里有我发布的 here 的完整书籍列表。也不是所有的书都是西班牙语的。

在了解它们的工作原理之前,您必须了解一些概念,例如首先、跟随和前瞻。另外,我真的建议您在尝试理解 LR(上升)解析器之前理解 LL(后代)解析器背后的概念。

有一个解析器家族 LR,特别是 LR(K)、SLR(K) 和 LALR(K),其中 K 是它们需要工作的前瞻次数。 Yacc 支持 LALR(1) 解析器,但您可以进行调整,而不是基于理论,使其适用于更强大的语法。

关于性能,它取决于被分析的语法。它们以线性时间执行,但它们需要多少空间取决于您为最终解析器构建了多少状态。

【讨论】:

  • 第 5 卷是几年后的事了!最好。我希望我能在 2020 年或任何时候回到这个页面,并嘲笑这条评论。
  • @DariusBacon -- 欢迎来到 2020 :)
【解决方案2】:

我个人很难理解函数调用如何更快 - 远不如表查找“显着更快”。而且我怀疑与词法分析器/解析器必须做的所有其他事情(主要是读取和标记文件)相比,即使“明显更快”也是微不足道的。我查看了维基百科页面,但没有遵循参考;作者是否真的分析了一个完整的词法分析器/解析器?

对我来说更有趣的是表驱动解析器在递归下降方面的衰落。我来自 C 背景,其中 yacc(或等效的)是首选的解析器生成器。当我转向 Java 时,我发现了一个表驱动实现(JavaCup)和几个递归下降实现(JavaCC、ANTLR)。

我怀疑答案类似于“为什么使用 Java 而不是 C”的答案:执行速度不如开发速度重要。正如 Wikipedia 文章中所指出的,表驱动的解析器几乎不可能从代码中理解(当我使用它们时,我可以跟随它们的操作,但永远无法从解析器重构语法)。相比之下,递归下降非常直观(这无疑是它比表驱动早了 20 年的原因)。

【讨论】:

  • 递归下降比表驱动的 LR 解析器慢。我想知道递归上升是完全不同的野兽。
  • 是的,根据文章递归上升具有内联函数调用来表示状态机,而不是变量和表。正如我在第一段中所说,我并不认为它更快,尤其是在解析器的使用方式方面。
  • 但我还要提出一个更大的观点:解析器实现的原始速度很少是重要的。特别是在如何使用解析器的上下文中。
  • 我认为基于方法的解析器(尤其是递归下降)的主要卖点是可调试性。走电话比桌子容易得多。 然而,我见过一些调试器可以将映射转换/归约回语法并使其更具可读性。
【解决方案3】:

关于递归 ascent 解析的 Wikipedia 文章引用了似乎是关于该主题的原始论文(“Very Fast LR Parsing”)。略读那张纸为我清除了一些东西。我注意到的事情:

  1. 论文讨论了生成汇编代码。我想知道如果您正在生成 C 或 Java 代码,您是否可以做与他们相同的事情;请参阅第 4 和 5 节,“错误恢复”和“堆栈溢出检查”。 (我并不是要 FUD 他们的技术——它可能会很好——只是说这是你在提交之前可能想要研究的东西。)

  2. 他们将递归上升工具与他们自己的表驱动解析器进行比较。从他们结果部分的描述来看,他们的表驱动解析器似乎是“完全解释的”;它不需要任何自定义生成的代码。我想知道是否存在中间立场,即整体结构仍然是表驱动的,但您为某些操作生成自定义代码以加快速度。

维基百科页面引用的论文:

另一篇关于使用代码生成代替表格解释的论文:

另外,请注意递归下降解析并不是解析基于 LL 语法的语言的最快方法:

【讨论】:

    猜你喜欢
    • 2012-08-11
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    相关资源
    最近更新 更多