2013-02-06 26 views
7

LLVM tutorials中有说明如何编写简单的JIT编译器。不幸的是,本教程中的词法分析器和解析器是手动编写的。我在想,这样的解决方案对于学习目的是有好处的,但它不适合编写复杂的,即时编译的编译器。看来GCC和其他几个“大编译器”是手写的。但我认为,所有这些解析器生成器在编写自己的编译器时都会有很大的提升(特别是当你独自一人做,没有团队的时候)。LLVM JIT解析器用Bison/Antlr/Packrat/Elkhound编写/

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

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

+0

“这样的解决方案对于学习目的很好,但不适合编写复杂的生产编译器” - 嗯。我一直认为GCC是一个复杂且适合生产的编译器。无论如何... – 2013-02-06 18:30:49

+0

海湾合作委员会一开始就使用野牛,但你是对的 - 我正在修复它在我的问题。但是真的,如果可能的话,我很乐意使用一个生成器来简化这个任务。 –

+5

如果有的话,我会说相反的是:yacc,Bison等适用于学习等目的,但对于严肃的生产工作,手写解析器可能是满足需求的唯一途径。 –

回答

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无效,这比仅仅继续解析更困难,所以有很多事情可以说不尝试。另外,跟踪源位置非常慢,如果您不需要生成诊断程序(除非您需要它来添加调试注释),那么它不是非常有用,所以您可以通过不打扰地加快解析速度位置跟踪。

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

+1

为什么“不清楚”什么是实际的语言? PEG是明确定义的,即使Packrat允许做的所有酷酷的黑客(高阶解析等)也是如此。 –

+1

@ SK-逻辑:明确定义与清除不一样。用C++编写的手工解析器是非常明确的。图灵机是明确的。是的,PEG是明确的。但是对于所有这些人来说,查看给定字符串是否在语言中的唯一方法是执行代码。 (在这三种选择中,PEG是最不好的,imo,但我仍然更喜欢正式的上下文无关语法,但正如我所说,像PEG这样的其他人,以及适合你的任何东西都与我一样酷)。 – rici

+0

从我的实际经验,PEG是最清晰易读的语法。我可以通过非常小的修改将语言规范直接转换为PEG。当然可以混淆它,但是我还没有看到一个非常糟糕的语法。有许多超出任何希望Yacc语法的难以理解的语法。 –