【问题标题】:Advantages of Antlr (versus say, lex/yacc/bison) [closed]Antlr 的优势(相对于 lex/yacc/bison)[关闭]
【发布时间】:2010-09-17 19:03:18
【问题描述】:

我过去曾在各种项目中使用过 lex 和 yacc(通常是 bison),通常是翻译器(例如流式传输到 EDA 应用程序的 EDIF 子集)。此外,我不得不支持基于几十年前的 le​​x/yacc 语法的代码。因此,尽管我不是专家,但我知道自己使用这些工具的方法。

我过去曾在各种论坛上看到过关于 Antlr 的正面评价,我很好奇我可能遗漏了什么。因此,如果您两者都使用过,请告诉我 Antlr 中哪个更好或更高级。我目前的限制是我在 C++ 商店工作,我们发布的任何产品都不会包含 Java,因此生成的解析器必须遵循该规则。

【问题讨论】:

    标签: c++ antlr yacc bison


    【解决方案1】:

    更新/警告:此答案可能已过时!


    一个主要区别是 ANTLR 生成 LL(*) 解析器,而 YACC 和 Bison 都生成 LALR 解析器。这是许多应用程序的一个重要区别,最明显的是运算符:

    expr ::= expr '+' expr
           | expr '-' expr
           | '(' expr ')'
           | NUM ;
    

    ANTLR 完全无法按原样处理这种语法。要使用 ANTLR(或任何其他 LL 解析器生成器),您需要将此语法转换为非左递归的语法。但是,Bison 对这种形式的语法没有问题。您需要将 '+' 和 '-' 声明为左关联运算符,但这并不是左递归所严格要求的。一个更好的例子可能是调度:

    expr ::= expr '.' ID '(' actuals ')' ;
    
    actuals ::= actuals ',' expr | expr ;
    

    请注意,expractuals 规则都是左递归的。这在代码生成时会产生更高效的 AST,因为它避免了对多个寄存器和不必要的溢出的需要(左倾树可以折叠,而右倾树不能)。

    就个人品味而言,我认为 LALR 语法更容易构建和调试。缺点是你必须处理一些隐晦的错误,比如 shift-reduce 和(可怕的)reduce-reduce。这些是 Bison 在生成解析器时捕获的错误,因此不会影响最终用户体验,但可以使开发过程更有趣。正是因为这个原因,ANTLR 通常被认为比 YACC/Bison 更易于使用。

    【讨论】:

    • 那么在您看来,Antlr 最大的(可能是单一的)优势在于它在构建阶段产生的 s-r 和 r-r 之类的错误更少?我希望我会尝试一下,但最终可能会坚持我所知道的......
    • 是的,差不多就是这样。 :-) 我也不完全同意 ANTLR 比 Bison 更容易的流行观点,所以我想我会同意你的决定。
    • “实际值”规则是否需要第二条规则来指示简单的“表达式”是实际值?否则,很好的解释。
    • 我最近发现的另一条评论,虽然已有十年之久,但对 output 进行了合理的观察:compilers.iecc.com/comparch/article/98-11-040:“ANTLR/PCCTS 是 LL,这使得语法编写更加困难, 但生成的代码是可读的。yacc 是 LALR(你当然知道)使语法编写更容易,但生成的代码也可能是象形文字。”
    • 我刚刚完成了对 ANTLR 下一个版本 v3.4 的立即左递归支持。处理 LR 表达式规则和类似的东西,如 C 声明符规则。 :)
    【解决方案2】:

    ANTRL 的另一个优势是您可以使用ANTLRWORKS,尽管我不能说这是一个严格的优势,因为其他生成器可能也有类似的工具。

    【讨论】:

      【解决方案3】:

      ANTLR 的几个优点:

      • 可以输出各种语言的解析器 - 运行生成的解析器不需要 Java。
      • 出色的 GUI 让语法调试变得简单(例如,您可以在 GUI 中直接看到生成的 AST,无需额外工具)
      • 生成的代码实际上是人类可读的(这是 ANTLR 的目标之一),它生成 LL 解析器这一事实在这方面肯定会有所帮助。
      • 终端的定义也是上下文无关的(与 (f)lex 中的正则表达式相反) - 例如,允许定义包含正确闭合的括号的终端

      我的 .02$

      【讨论】:

        【解决方案4】:

        YACC/Bison 和 ANTLR 之间最显着的区别是这些工具可以处理的语法类型。 YACC/Bison 处理 LALR 语法,ANTLR 处理 LL 语法。

        通常,长期使用 LALR 语法的人会发现使用 LL 语法更加困难,反之亦然。这并不意味着语法或工具本质上更难使用。您觉得哪种工具更容易使用主要取决于对语法类型的熟悉程度。

        就优势而言,LALR 语法在某些方面优于 LL 语法,而在其他方面 LL 语法也优于 LALR 语法。

        YACC/Bison 生成表驱动解析器,这意味着“处理逻辑”包含在解析器程序的数据中,而不是在解析器的代码中。回报是即使是非常复杂的语言的解析器也具有相对较小的代码足迹。这在 1960 年代和 1970 年代硬件非常有限时更为重要。表驱动的解析器生成器可以追溯到这个时代,而小代码占用是当时的主要要求。

        ANTLR 生成递归下降解析器,这意味着“处理逻辑”包含在解析器的代码中,因为语法的每个生产规则都由解析器代码中的一个函数表示。回报是通过阅读其代码更容易理解解析器在做什么。此外,递归下降解析器通常比表驱动解析器更快。但是,对于非常复杂的语言,代码占用空间会更大。这是 1960 年代和 1970 年代的一个问题。那时,由于硬件限制,只有相对较小的语言(例如 Pascal)以这种方式实现。

        ANTLR 生成的解析器通常在 10.000 行代码左右,甚至更多。手写递归下降解析器通常在同一个球场。 Wirth 的 Oberon 编译器可能是最紧凑的编译器,大约 4000 行代码(包括代码生成),但 Oberon 是一种非常紧凑的语言,只有大约 40 条生产规则。

        正如有人已经指出的那样,ANTLR 的一大优势是图形 IDE 工具,称为 ANTLRworks。它是一个完整的语法和语言设计实验室。它会在您键入语法规则时将其可视化,如果发现任何冲突,它将以图形方式向您显示冲突是什么以及导致冲突的原因。它甚至可以自动重构和解决左递归等冲突。一旦你有了一个无冲突的语法,你就可以让 ANTLRworks 解析你的语言的输入文件,并为你构建一个解析树和 AST,并在 IDE 中以图形方式显示树。这是一个非常大的优势,因为它可以为您节省大量工作时间:在开始编码之前,您会发现语言设计中的概念错误! LALR语法我没有找到这样的工具,好像没有这样的工具。

        即使对于那些不想生成解析器而是手动编码的人来说,ANTLRworks 也是语言设计/原型设计的绝佳工具。很可能是最好的此类工具。不幸的是,如果您想构建 LALR 解析器,这对您没有帮助。仅仅为了利用 ANTLRworks 从 LALR 切换到 LL 可能是值得的,但是对于某些人来说,切换语法类型可能是一个非常痛苦的经历。换句话说:YMMV。

        【讨论】:

        • 喜欢它,因为它解释了不同机制背后的历史,使人们立即理解
        【解决方案5】:
        • Bison 和 Flex 可以减少内存占用,但您没有图形 IDE。
        • antlr 使用更多内存,但您有 antlrworks,一个图形 IDE。

        Bison/Flex 内存使用量通常为 MB 左右。与 antlr 进行对比——假设它为要解析的文件中的每个标记使用 512 字节的内存。 400 万个令牌,而您在 32 位系统上的虚拟内存不足。

        如果你要解析的文件很大,antlr 可能会内存不足,所以如果你只是想解析一个配置文件,这将是一个可行的解决方案。否则,如果您想解析包含大量数据的文件,请尝试 Bison。

        【讨论】:

        • 我很好奇。您能否指出描述每个令牌消耗 512 字节内存的文档?我不记得看过那个讨论。我对 Google 关键字的选择也没有让我满意...
        • 您是在讨论生成解析器时解析器生成器的内存占用,还是在解析源语言输入时生成的解析器的内存占用?语法中的数百万个标记绝对是疯狂的。如果你认真地试图推销这样的想法,你应该被关进精神病院。至于解析器本身的输入文件,可能存在这些可能具有大量标记的情况,但大多数语言都是模块化的,您不会在单个文件中解析整个输入,单个模块更小。
        猜你喜欢
        • 1970-01-01
        • 2010-11-13
        • 1970-01-01
        • 1970-01-01
        • 2010-11-28
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 1970-01-01
        相关资源
        最近更新 更多