9

LLVM 教程中有说明如何编写简单的 JIT 编译器。不幸的是,本教程中的词法分析器和解析器是手动编写的。我在想,这样的解决方案有利于学习,但不适合编写复杂的、生产就绪的编译器。不过,GCC 和其他一些“大型编译器”似乎是手写的。但我认为,在编写自己的编译器时,所有这些解析器生成器都会大大提升(尤其是当你独自完成,没有团队的时候)。

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

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

4

1 回答 1

9

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

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

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

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

Personally, I'm biased against packrat parsing, because it's not clear what the actual language parsed by a PEG is. Other people don't mind this so much, and YMMV.

于 2013-02-07T01:05:44.097 回答