AST翻译?

时间:2012-05-11 16:12:54

标签: interpreter abstract-syntax-tree

我有一个AST(抽象语法树),现在我想测试我的编译器,给它2个或更多的数字,并期望输出结果为数学运算(如计算器)。

我的问题是,构建解释器的最佳方法是什么?访问AST节点是递归的,所以我不知道有多少封装计算存在,直到我到达树的末尾。但由于这是通过迭代迭代完成的,我怎样才能最终完成所有操作?

谢谢

1 个答案:

答案 0 :(得分:15)

一旦你有了AST,解释器很容易编码:

 int interpret(tree t)
 { /* left to right, top down scan of tree */
   switch (t->nodetype) {
     case NodeTypeInt:
        return t->value;
     case NodeTypeVariable:
        return t->symbtable_entry->value
     case NodeTypeAdd:
        { int leftvalue= interpret(t->leftchild);
          int rightvalue= interpret(t->rightchild);
          return leftvalue+rightvalue;
        }
     case NodeTypeMultiply:
        { int leftvalue= interpret(t->leftchild);
          int rightvalue= interpret(t->rightchild);
          return leftvalue*rightvalue;
        }
     ...
     case NodeTypeStatementSequence: // assuming a right-leaning tree
        { interpret(t->leftchild);
          interpret(t->rightchild);
          return 0;
        }
     case NodeTypeAssignment:
        { int right_value=interpret(t->rightchild);
          assert: t->leftchild->Nodetype==NodeTypeVariable;
          t->leftchild->symbtable_entry->value=right_value;
          return right_value;
        }
     case NodeTypeCompareForEqual:
        { int leftvalue= interpret(t->leftchild);
          int rightvalue= interpret(t->rightchild);
          return leftvalue==rightvalue;
        }
     case NodeTypeIfThenElse
        { int condition=interpret(t->leftchild);
          if (condition) interpret(t->secondchild);
          else intepret(t->thirdchild);
          return 0;
     case NodeTypeWhile
        { int condition;
          while (condition=interpret(t->leftchild))
                interpret(t->rightchild);
          return 0;

     ...
   }
 }

令人讨厌的是“goto”,因为这会改变解释者的注意力。要实现goto或函数调用,必须在树中搜索标签或函数声明,并在那里继续执行。 [人们可以通过预扫描树并在查找表中收集所有标签位置/函数声明来加快速度。这是构建编译器的第一步。]即使这还不够;你必须调整我们隐藏在函数调用中的递归堆栈,这样做并不容易。如果将此代码转换为具有显式托管递归堆栈的迭代循环,则修复堆栈要容易得多。