编写简单的解析器是微不足道的,多年来我已经实现了几个。在大学里,我们还要写一个。但我们从未使用此方法生成有意义的输出; 我们从未学过如何创建后端。
如果我有一个工作的递归下降解析器用于简化的Pascal并且我想将代码转换为C ++,我将如何进行此操作?我不认为需要一个中间步骤,例如生成抽象语法树。
那么如何输出编译或翻译的代码?我发现的唯一有用的例子是Jack Crenshaw的教程,但它更关注前端,大多数其他资源。我的解析器代码和我的语法之间的关系非常明显。解析器方法和输出之间的关系怎么样?我的函数声明解析器方法可以与一个EmitLn( C ++ code here )调用完全相关。但是解析器方法又不那么容易,比如表达式。表达式被分解为可能更多的调用,因此暗示需要一个Emit()函数,它允许我逐个分解表达式的输出代码。 是否有任何用于输出代码的样板代码,例如Jack Crenshaw的Lets Build a Compiler中的EmitLn函数?这也告诉我,我需要维护一个基本的符号表,这是大多数例子中经常省略的另一件事。
我是对的吗?我还应该知道什么?任何提示/建议或资源?我的一个大问题是,有很多关于编译器前端的教程,但是后端有些解释呢?我可以解析语言,现在我想将其发展为能够翻译并将它们编译成其他语言。
答案 0 :(得分:3)
有些琐碎的编译器使用“即时”代码生成器来吐出代码 因为他们正在解析,正如你似乎想要做的那样。好消息是他们看起来 容易。
问题在于编译从根本上讲是关于传播信息的 代码的一部分到另一部分,以实现良好的代码生成。为了那个原因, 编译人员很久以前决定将解析与代码生成分开。 解析器解析代码并构建另一个中间数据结构(通常是 表示程序的抽象语法树或三元组。
通常,对中间结构进行非常深入的分析 确定如何生成良好的代码,然后适当的好 代码生成。做得好的技术很复杂, 但是需要制作好的(和正确的)代码。
尝试检查标准编译器资源。 Learning to write a compiler
值得你的 是时候详细阅读其中的一些参考而不是黑客。 如果你只坚持一个,Aho和Ullman就是经典着作。
如果您想了解动态代码生成的方式 为了合理地工作,退房 metacompilers
答案 1 :(得分:1)
简短回答在语法中匹配规则后,调用一个根据输入做某事的函数。
长答案:来自Terence Parr的语言实现模式讨论语法导向解释器:
语法导向的解释器不会创建AST或将源代码转换为字节码...解释器直接提供语法来执行语句。
这正是我在原始问题中要求的想法。他继续在书中描述了这种技术,它是如何工作的,它包含了什么,以及它们的局限性。它适用于DSL和小语言,而不是通用语言。
他指出IF和循环等结构很难实现。虽然这可能是正确的,但我在使用我的语言Peay BASIC中实现这些功能时没有遇到任何问题。作为指令序列或简单语句的语言是这种模式的理想选择;他以文本处理语言为例。
语法扩展为“匹配这个,称之为”对。因此,语法中的必要规则应该有一个与之相关的动作。赋值语句的示例:
assignment : ID '=' expr {interp.assign($ID, $expr.value);};
expr returns [Object value] : ... ;