3

编写简单的解析器是微不足道的,多年来我已经实现了几个。在大学里,我们也不得不写一篇。但是我们不必使用这种方法生成有意义的输出;我们从未学会如何创建后端。

如果我有一个用于简化 Pascal 的递归下降解析器,并且我想将代码转换为 C++,我将如何去做呢?我认为不需要中间步骤,例如生成抽象语法树。

那么我该如何输出编译或翻译的代码呢?我发现的唯一有用的例子是在 Jack Crenshaw 的教程中,但它更多地关注前端,就像大多数其他资源一样。我的解析器代码和我的语法之间的关系非常明显。解析器方法和输出之间的关系如何?我的函数声明解析器方法可以与一个 EmitLn( C++ code here ) 调用完全相关。但是那些不那么容易的解析器方法呢,比如表达式。表达式被分解为可能更多的调用,因此暗示需要一个 Emit() 函数,它允许我逐段分解表达式的输出代码。是否有任何用于输出代码的样板代码,例如 Jack Crenshaw 的 Lets Build a Compiler 中的 EmitLn 函数?这也表明我需要维护一个基本的符号表,这是大多数示例中经常省略的另一件事。

我对吗?我还应该知道什么?任何提示/建议或资源?我的大问题是,编译器前端的教程太多了,但是后端的一些解释怎么样?我可以解析语言,现在我想将其发展为能够将它们翻译和编译成其他语言。

4

2 回答 2

3

有一些简单的编译器使用“动态”代码生成器,它们在解析时会吐出代码,正如您似乎正在尝试做的那样。好消息是它们看起来很容易。

问题是编译基本上是将信息从代码的一部分传播到另一部分,以实现良好的代码生成。为此,编译器人员很久以前就决定将解析与代码生成分开。解析器解析代码并构建另一个代表程序的中间数据结构(通常是抽象语法树或三元组)。

通常,对中间结构进行非常深入的分析以确定如何生成好的代码,然后是适当的好的代码生成。做好这件事的技术很复杂,但出于产生好的(和正确的)代码的需要而很好地推动了这一点。

尝试检查标准编译器资源。 学习编写编译器

值得您花时间详细阅读其中一些参考资料,而不是进行黑客攻击。如果你只坚持一本,《Aho and Ullman》就是经典之作。

如果您想了解如何使动态代码生成工作得相当好,请查看 metacompilers

于 2011-10-20T08:56:17.060 回答
1

简答在匹配语法中的规则后,调用一个根据输入执行某些操作的函数。

长答案:来自 Terence Parr 讨论语法导向解释器的语言实现模式:

语法导向的解释器不会创建 AST 或将源代码转换为字节码……解释器直接从语法中提取来执行语句。

这正是我在最初的问题中想要的想法。他在书中继续描述了这项技术、它的工作原理、它的组成部分以及局限性。它适用于 DSL 和小型语言,而不是通用语言。

他指出,像 IF 和循环这样的结构很难实现。虽然这很可能是真的,但我用我的语言Peay BASIC实现这些功能没有任何问题。作为指令序列或简单语句的语言非常适合这种模式;他以文本处理语言为例。

语法被扩展为由“匹配这个,调用那个”对组成。所以语法中的必要规则应该有一个与之相关的动作。赋值语句示例:

assignment : ID '=' expr {interp.assign($ID, $expr.value);};
expr returns [Object value] : ... ;
于 2012-08-30T18:47:55.870 回答