【问题标题】:What are the disadvantages of using ANTLR compared to Flex/Bison?与 Flex/Bison 相比,使用 ANTLR 有什么缺点?
【发布时间】:2025-12-01 12:45:01
【问题描述】:

几年前,我在本科学习期间曾研究过 Flex, Bison。然而,我现在已经不记得太多了。最近,我听说了 ANTLR。

  • 您会建议我学习 ANTLR 还是更好地复习 Flex/Bison?
  • ANTLR 的功能是否比 Flex/Bison 多/少?

【问题讨论】:

标签: antlr bison flex-lexer jflex


【解决方案1】:

ANTLRv3 是 LL(k),可以配置为 LL(*)。后者尤其容易编写解析器,因为您基本上可以按原样使用 EBNF。

此外,ANTLR 生成的代码非常类似于您从头开始编写的递归下降解析器。它非常易读且易于调试,以查看解析不起作用或错误的原因。

Flex/Bison(或任何其他 LALR 解析器)的优势在于速度更快。

【讨论】:

  • 更快?您是将 LALR 与 LL(k) 还是 LL(*) 进行比较? LL(k) 解析非常快。由于回溯,LL(*) 解析很慢,但你很少需要使用它(即使你这样做了,我相信 ANTLR 允许你将 LL(*) 用于语法的子集)。我知道 LALR 的一个优势是某些语法无法解析 LL(k) 可以被 LALR 解析,但实际上您实际上想要的大多数语法parse 可以重新表示为可以解析的形式 LL(k)。
  • 是的。 LALR 更快,因为您可以为此使用表驱动的有限状态机。一旦它由像 Bison 这样的解析器生成器生成,它是难以理解的并且几乎不可能调试,但它也非常快。由 ANTLR 实现的 LL(k) 使用递归下降解析,这有点慢。
  • 我刚试过antlrworks工具,下面的东西没用: expr : expr '+' expr;因为它不允许左递归。大家是不是觉得有点不方便。然后,您必须将其转换为类似 expr : expr ('+' expr)* 的东西,即像正则表达式一样编写它。在 flex 中,我可以写前一种方式,我发现它比这种正则表达式风格更自然。
  • @ajay,这就是区别的要点。对于某些结构,将它们写成右递归更为自然。对于其他人来说,将它们写成左递归更自然。也就是说,对于您的示例所建议的1 * (2 + 3) - 4 之类的简单语法,您宁愿编写如下内容:expr: term ('+' | '-') expr; term: factor ('*' | '/') term; factor : literal_number | '(' expr ')'。哪个更自然尚有争议,但请注意 ANTLR 不需要任何特殊构造来实现运算符关联性——这是语法术语本身固有的。
【解决方案2】:

ANTLR 有一个运行时库 JAR,您必须将其包含在您的项目中。

ANTLR 的递归下降解析器比 Flex/Bison 生成的“自下而上”解析器更容易调试,但语法规则略有不同。

如果您想要用于 Java 的 Flex/Bison 样式 (LALR) 解析器生成器,请查看 JavaCC

【讨论】:

    【解决方案3】:

    我们决定使用 ANTLR 来满足我们的一些信息处理要求 - 解析遗留文件和自然语言。学习曲线很陡峭,但我们正在超越它,我觉得这是一种更现代、更通用的方法,可以满足我们的需要。缺点 - 正如你所问 - 主要是学习曲线,这似乎是不可避免的。

    【讨论】:

    • 我怀疑几乎任何解析器生成器的学习曲线都大致相同。只需 5 分钟即可“从技术上”理解“它是 LALR...”或“它是 LL...”这句话 需要数周时间才能了解您必须使用的机器,将语法整理成形状,学习如何改变语法,......在所有条件相同,学习曲线相似的情况下,您应该选择适用于您的世界的最强大的解析器生成器。