Antlr的优点(相对于lex / yacc / bison)[关闭]


143

过去,我曾在各种项目中使用过lex和yacc(通常是野牛),通常是翻译器(例如流到EDA应用程序中的EDIF的子集)。此外,我还必须支持基于几十年前的lex / yacc语法的代码。因此,尽管我不是专家,但我知道如何使用这些工具。

过去,我已经在各个论坛上看到过有关Antlr的正面评论,并且我对自己可能会缺少的东西感到好奇。因此,如果您同时使用了两者,请告诉我Antlr有哪些更好或更高级的功能。我目前的限制是我在C ++商店工作,我们提供的任何产品都不包括Java,因此生成的解析器必须遵循该规则。

Answers:


145

更新/警告:该答案可能已过期!


一个主要区别是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语法更容易构建和调试。缺点是您必须处理一些隐秘的错误,例如移位减少和(可怕的)减少减少。这些是Bison在生成解析器时捕获的错误,因此它不会影响最终用户的体验,但是可以使开发过程更加有趣。正是由于这个原因,通常认为ANTLR比YACC / Bison更易于使用。


2
因此,您认为Antlr的最大优势(也许是单一优势)是,在构建阶段它会生成较少的错误,例如sr和rr?我希望我会尝试一下,但最终可能会坚持我所知道的...
唐•韦克菲尔德

1
是的,仅此而已。:-)我也不太同意ANTLR比Bison容易的流行观点,所以我想我同意您的决定。
Daniel Spiewak

2
“事实”规则是否需要第二条规则来表明简单的“ expr”是实际的?否则,很好的解释。
乔纳森·勒夫勒

8
我最近发现的另一条评论(尽管已有十年历史了)对输出进行了合理的观察: compilers.iecc.com/comparch/article/98-11-040:“ ANTLR / PCCTS是LL,这使得语法编写更加困难,但是生成的代码是可读的。Yacc是LALR(您当然知道)使语法编写更加容易,但是生成的代码也可能是象形文字。”
唐·韦克菲尔德

72
我刚刚完成了对ANTLR下一个版本v3.4的立即左递归支持。处理LR表达式规则和类似的东西,例如C声明符规则。:)
Terence Parr

117

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行代码及附近。手写递归下降解析器通常位于同一球场。沃思的Oberon编译器也许是最紧凑的编译器,它包含大约4000行代码,包括代码生成,但是Oberon是一种非常紧凑的语言,只有大约40条生产规则。

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

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


4
之所以喜欢它,是因为它解释了使人们立即理解的各种机制背后的历史
导致2013年

35

ANTLR有几个优点:

  • 可以输出各种语言的解析器-运行生成的解析器不需要Java。
  • 很棒的GUI使语法调试变得容易(例如,您可以在GUI中看到生成的AST的权限,不需要其他工具)
  • 生成的代码实际上是人类可读的(这是ANTLR的目标之一),并且它生成LL解析器的事实肯定会在这方面有所帮助。
  • 终端的定义也不受上下文限制(与(f)lex中的regex相反)-因此,例如,允许定义包含正确封闭的括号的终端

我的.02 $


9

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


9
  • Bison和Flex可以减少内存占用,但是您没有图形IDE。
  • antlr使用更多的内存,但是您有antlrworks(图形化IDE)。

Bison / Flex内存使用量通常约为1 MB。与antlr对比,假设它要解析的文件中的每个令牌都使用512字节的内存。如果有400万个令牌,则您在32位系统上的虚拟内存不足。

如果您要解析的文件很大,则antlr可能会用完内存,因此,如果您只想解析配置文件,那将是一个可行的解决方案。否则,如果要分析包含大量数据的文件,请尝试使用Bison。


7
我很好奇。您能否指向描述每个令牌占用512字节内存的文档?我不记得看到过这样的讨论。我对Google关键字的选择也不能使我满意……
唐·韦克菲尔德

2
您是在生成解析器时谈论解析器生成器的内存占用,还是在解析源语言的输入时谈论所生成解析器的内存占用?语法中数以百万计的记号绝对是疯狂的。如果您认真尝试推销这种想法,则应将您关在精神病院。至于解析器本身的输入文件,在某些情况下,它们可能具有大量的令牌,但是大多数语言是模块化的,您没有将整个输入解析为单个文件,单个模块较小。
trijezdci 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.