LLVM JIT解析器使用Bison/Antlr/Packrat/Elkhound/编写

LLVM JIT Parser writing with Bison / Antlr / Packrat / Elkhound /

本文关键字:Antlr Packrat Elkhound 编写 Bison JIT LLVM      更新时间:2023-10-16

在LLVM教程中,有关于如何编写简单JIT编译器的说明。不幸的是,本教程中的lexer和解析器是手动编写的。我在想,这样的解决方案有利于学习,但不适合编写复杂的、可用于生产的编译器。不过,GCC和其他一些"大型编译器"似乎都是手工编写的。但我认为,所有这些解析器生成器在编写自己的编译器时都会起到很大的推动作用(尤其是当你独自完成,没有团队的时候)。

是否可以将任何现有的语法分析器生成器(如Bison/Antlr/Packrat/Elkhound等)与LLVM一起使用来创建JIT编译器?我希望能够不断地(而不是一开始就一次)向解析器"提供"表达式,并在运行时编译它们。

另外,我发现了很多关于"最好的、现代的"解析器生成器的问题(比如这个:https://stackoverflow.com/questions/428892/what-parser-generator-do-you-recommend)。如果可以使用这些工具来创建LLVM JIT编译器,我将感谢任何额外的提示和建议,在这种特殊情况下,哪种工具的性能和灵活性最好。

使用像bison或antlr这样的解析器生成器有很多优点,尤其是在开发语言时。毫无疑问,你最终会对语法进行更改,并且你希望最终得到最终语法的文档。从文档中自动生成语法的工具非常有用。它们还可以帮助你相信语言的语法是(a)你认为的,(b)不含糊。

如果你的语言(与C++不同)实际上是LALR(1),甚至更好的是LL(1)并且你正在使用LLVM工具来构建AST和IR,那么你不太可能需要做的不仅仅是写下语法并提供一些简单的操作来构建AST。这会让你坚持一段时间。

除了"真正的程序员不使用解析器生成器"的偏见之外,人们最终选择构建自己的解析器的常见原因是,很难为语法错误提供良好的诊断,尤其是LR(1)解析。如果这是你的目标之一,你应该尝试让你的语法LL(k)是可解析的(用LL(k)提供良好的诊断仍然不容易,但似乎更容易一点),并使用像Antlr这样的LL(克)框架。

还有另一种策略,即首先使用比LL(1)更灵活的LALR(1)解析器以最简单的方式解析程序文本,甚至不尝试提供诊断。如果解析失败,则可以使用速度较慢、甚至可能是回溯的解析器再次解析,该解析器不知道如何生成AST,但会跟踪源位置并尝试从语法错误中恢复。在不使AST无效的情况下从语法错误中恢复甚至比继续解析更困难,因此有很多不尝试的地方要说。此外,跟踪源位置的速度非常慢,如果您不必生成诊断程序(除非您需要它来添加调试注释),那么它就没有多大用处,因此您可以通过不麻烦位置跟踪来加快解析速度。

就我个人而言,我对packrat解析有偏见,因为不清楚PEG解析的实际语言是什么。其他人不太介意,还有YMMV。