2012-02-28 88 views
4

我在http://parsingintro.sourceforge.net/上阅读了文章,并决定尝试将它改写为Ruby中的练习。有两个原因让我这么做,我想了解更多关于如何编写Ruby(Java,PHP,C和一些Python背景)的知识,并且我想了解更多关于解析器/编译器的知识。如何为从假想语言中解析出的AST树生成代码?

我已将所有代码发布在https://github.com/parse/boatcaptain。正在生成AST树,不幸的是本文的作者没有涉及代码生成和优化等概念。

任何人都可以帮助我指出我在正确的方向如何实现这个AST树成“代码”? This is the AST tree that is generated

我几年前在Java中编写了一个计算器,它使用了很多与此解析器中使用的相似的术语和技术。但在计算器中,我有eval()方法来处理我的“类”,因此得到输出,我是否应该在这里做类似的事情?计算器源代码:https://github.com/parse/Uppsala-University-Courses/blob/master/ImpOOP-Calculator/src/Calculator.java

我也很想反馈我写Ruby的方式,我相信我仍然会像编写Python一样编写Ruby,但缺少Ruby的一些优点。

+0

如果你想学习如何做代码生成,请阅读一本关于如何做代码生成的书。 Aho和Ullman的“编译器”是一个经典。不要期望这很容易,如果你想要一个好的代码生成;你不会在没有重要知识的情况下编码你的涅ana。 – 2012-05-08 20:34:37

回答

1

代码生成最基本的形式是简单地遍历你的中间表单 - AST,并发出相应的目标语言指令。

首先,您需要选择一种目标语言。你想让你的输入文件运行在哪个平台上?向你敞开的主要选项有:

  • 源到源翻译
  • 一个编译为本地代码
  • 一个编译成字节码(可以在虚拟机上运行刚刚在时间)

目标语言的选择可以决定你必须在语言之间进行映射的工作量。例如,将面向对象的类映射到ASM可能会很棘手。将固有程序代码映射到基于堆栈的代码也可能是一个挑战。

无论您选择何种语言,问题无疑将归结为以下过程:访问树的节点,并根据其类型发出相应的指令。

假设你遇到以下节点的AST(如一个链接到您):

 = 
delta  /
     alpha beta 

看到,因为它是一个“任务”节点,然后代码生成器知道它必须评估在将该值粘贴到LHS之前,树的RHS; '三角洲'。所以我们跟随RHS节点,看看它是一个分工操作。然后我们知道在分割它们之前,我们必须评估这个节点的LHS和RHS,并将结果贴在'delta'上。

所以现在我们向下移动LHS,看看它是一个变量,然后我们发出一个'load'指令。我们回过头来,然后沿着RHS,同样发出一个'负载''β'。然后我们回到树上(同时携带alpha和beta),在两个操作数上发出divide指令,存储结果,并将它传递给分配发射器,然后让它存储在'delta'中。

所以对于这个片段生成的代码可能是:

load alpha 
load beta 
tmp = div alpha beta 
store delta tmp 

至于预先存在的Ruby代码生成库,我不知道有任何,对不起。我希望这个答案对你来说不是太笼统或简单。