ANTLR 是一个编译器编写工具,类似的 Lex/Yacc 或 Flex/Bison,但功能更强大,更现代,通常不那么令人沮丧。我目前正在阅读由 Antlr 的创造者特伦斯 · 帕尔的 The Definitive ANTLR 4 Reference 。这是一个奇妙的资源,关于ANTLR的工作和用法,但它是用Java写的 – 我最不喜欢的语言之一。谢天谢地, Antlr 面向多种语言, 所以我想在 Python 中遵循 — — 这也是我最不喜欢的语言之一。
ANTLR 本身是用 Java 编写的,因此您需要安装 Java、下载 ANTLR Jar 文件以及 shell 环境中的 Java 类路径设置,从而考虑要用哪种语言(本例中为 Python)。假设您使用的是 Fish,如下所示:
有了这个办法,我们几乎完成了Java。我们可以转到更多 Python 特定步骤,第一个步骤是安装 Python ANTLR 运行时。这很简单,就像运行 pip install:
设置的最后一点是配置用于调用 ANTLR 工具本身的别名。虽然这纯粹是可选的,但我发现它节省了大量的打字时间。这与 ANTLR 书第 5 页的脚本类似,但是针对 Python 定制的。
注意:请务必使用 chmod +x 上述脚本,并放在路径中的某个地方。
现在,我们可以回到享受学习ANTLR。本书的后大部分都是一个直截了当的翻译过程,书中引用的Java类名称与Python ANTLR框架所公开的Java类名称非常相似(如果不是相同的话)。
例如,下面是一个用于调用语法的”主”文件示例:
您只需将”YourLexer”和”YourParser”换成您的词法器和解析器的适当名称。
即使是访问者和听众的创作,也几乎是书中Java示例的1:1翻译。例如,侦听器的蓝图可能看起来像:
实际上,Java运行时使用的凹凸与 Python 运行时使用的凹凸非常相似,这非常好。我怀疑这是有意的,因为减少添加新语言目标所需的工作量,并降低其文档的复杂性。
然而,所有这些都有一个缺点。尽管语言暗示着ANTLR书中的四元,但ANTLR语法并不是语言不可知论者。完全可以将无法编译为任何数量的目标语言的 ANTLR 语法合并。事实上,我们在第 43 页的书中很早就遇到这种情况,我们接触到了侦听器模式。
语法 Java.g4 在定位 Python 时不起作用,ANTLR 生成以下错误:
错误很多!
让我们拉出第一个实际错误,看看更近一点。
它抱怨规则”类型”给我们带来了问题。为了更好地了解原因,让我们看看语法的适用部分:
还有由这个语法位生成的 Java 解析器:
而且,如果它不是 100% 清楚,让我们看看 Java 代码,我们需要移植到 Python 来利用这个语法:
从本质上讲,语法定义了一个叫做”type”的规则,但是”type”是Python中的保留词。然后,ANTLR 本身会生成一个解析器,该解析器实际上定义了一个名为”type”的函数,在 Java 中显然没问题,但在 Python 中却非常失败。
使用一些常见的前缀来避免此问题,或者让规则在字典中查找。相反,通过使用文本规则名称并期望其中每个名称都可以定义为目标语言中完全相同的名称的函数,因此,根据定义,ANTLR 不是与语言无关的函数。对于任何语法,可能有多个真实或假设的后端无法编译此类语法。
例如,下面是一个语法,在 Python 中非常有效,但不能为 Java 编译:
可悲的是, 这个 github 问题意味着这也是作者已知的问题, 他们认为不值得修复。
虽然许多,如果不是大多数,语法可能不是一个问题,这是相当可悲的:
- 这样的问题在书中很早就发生了。
- 这本书高度暗示, 互联网上的其他资源完全说, Antlr 是语言不可知论者 – 不, 它不是
- 作者似乎并不倾向于更广泛地纠正这个错误,或者这种关于他工具的误解。
撇开这一点不谈,ANTLR实际上是一个奇妙的工具,特别是如果你进入它的知识和意识的疣。我很兴奋地看到什么奇妙的东西,我可以创造这个惊人的工具。