Compiler construction 解释器后端,如何遍历抽象语法树?

Compiler construction 解释器后端,如何遍历抽象语法树?,compiler-construction,interpreter,abstract-syntax-tree,Compiler Construction,Interpreter,Abstract Syntax Tree,我正在做一个解释器,还没有找到一个很好的解释,说明如何在语义分析之后遍历和抽象语法树。我想知道正确的方法是什么。我知道您将终端从左到右合并到其父级处理中,并尽可能多地重复此操作 我有一个抽象语法树,它可能正确,也可能不正确 (来源:) 我该怎么办 将34和3合并为*,然后将4和*合并为+,然后将ident合并为call,将+合并为call?是这样吗?像这样向后遍历树的好算法是什么?我不会像您那样构建AST。我认为print是一个带有一个参数的函数。所以我会把这棵树建成 print \

我正在做一个解释器,还没有找到一个很好的解释,说明如何在语义分析之后遍历和抽象语法树。我想知道正确的方法是什么。我知道您将终端从左到右合并到其父级处理中,并尽可能多地重复此操作

我有一个抽象语法树,它可能正确,也可能不正确


(来源:)

我该怎么办


将34和3合并为*,然后将4和*合并为+,然后将ident合并为call,将+合并为call?是这样吗?像这样向后遍历树的好算法是什么?

我不会像您那样构建AST。我认为print是一个带有一个参数的函数。所以我会把这棵树建成

print
     \
      +
    /   \
   4     *
       /   \
      3     34
在将根中的运算符/函数应用于子级之前,先遍历树并计算子级。没有规定说你只能生两个孩子。如果你需要几个孩子,你可以有几个孩子

i、 e.乐趣(a、b、c、d)

还是没有孩子

i、 e.当前时间()

所以对于我的AST,你的问题是

visit                                               
print          need to evaluate right child  
+              left is 4, need to evaluate right  
*              left is 3, right is 34  
               evaluate 3 * 34 and return right = 102  
               evaluate 4 + 102 and return right = 106  
               evaluate print, so print 106  

我不会像你那样建造AST。我认为print是一个带有一个参数的函数。所以我会把这棵树建成

print
     \
      +
    /   \
   4     *
       /   \
      3     34
在将根中的运算符/函数应用于子级之前,先遍历树并计算子级。没有规定说你只能生两个孩子。如果你需要几个孩子,你可以有几个孩子

i、 e.乐趣(a、b、c、d)

还是没有孩子

i、 e.当前时间()

所以对于我的AST,你的问题是

visit                                               
print          need to evaluate right child  
+              left is 4, need to evaluate right  
*              left is 3, right is 34  
               evaluate 3 * 34 and return right = 102  
               evaluate 4 + 102 and return right = 106  
               evaluate print, so print 106  

为什么您希望直接进行AST解释而不首先将其转换为合理的内容(如平堆栈VM字节码)?可能是因为他不知道更多?也许从来没有听说过平栈VM字节码,或者不知道它的好处?你到底为什么要做一个直接的AST解释,而不先将它转换成合理的东西(比如平栈VM字节码)?也许是因为他不知道更好的东西?也许从来没有听说过平栈VM字节码,或者不知道它的好处?相对而言,打印号码应该是一个函数。几乎没有理由将其连接到基础语言中(他可能必须将“PRINTCHARACTER”或“PRINTSTRING”写入该语言,但PRINT number应该是生成数字字符串然后调用原语进行打印的内容)。我会像OP那样建造这棵树。这并没有真正改变答案,只是它增加了一个额外的步骤:在计算算术之后,他有“call(print,106)”并执行“call”的解释器步骤,这会找到print(某处)的AST并开始计算。相对而言,print number应该是一个函数。几乎没有理由将其连接到基础语言中(他可能必须将“PRINTCHARACTER”或“PRINTSTRING”写入该语言,但PRINT number应该是生成数字字符串然后调用原语进行打印的内容)。我会像OP那样建造这棵树。这并没有真正改变答案,只是增加了一个额外的步骤:在评估算术之后,他有“call(print,106)”并执行“call”的解释器步骤,这将找到打印的AST(某处),并开始评估它。