AST遍历函数

时间:2015-07-02 00:44:33

标签: abstract-syntax-tree traversal

我已经阅读了有关lex,yacc和生成AST的信息。我有两个问题,我无法找到解决方案:

1)用于解析和评估

a = 5;
b = a + 1;
a = 3;
d = a - 2;

鉴于所有4个语句都是评估并且在树中占据相同的级别(?),AST如何捕获(或应该捕获)程序顺序(因此b被评估为5 + 1而不是3 + 1) )?

2)假设我有一个ast(简化)如下:

root -> child1 -> grandchild1, grandchild2 
     -> child2 -> grandchild3, grandchild5, grandchild4
                      -> grandgrandchild123 etc  

如果我想根据一些输入参数自定义打印AST,其中我打印root,然后是child1和child2或child23,然后是所有子节点,那么最好的方法是什么?我正在考虑一种简单的方法,我有一个getchild1type(指向ast的指针),getchild3type(指向ast的指针)等方法,然后根据输入参数的要求在每个方法中迭代整个ast。

提前致谢。

1 个答案:

答案 0 :(得分:2)

因此程序顺序应隐含在语法树中。应该从您的示例生成的树应该是这样的:

       enter
        | 
       seq
        / \ 
       /   \
    assign  \
     / \     seq
    a   5   /   \   
          assign   ...
           /  \
          b    + 
              / \
             a   1

您可以想象为您的语言构建一个解释器,它以从左到右的深度优先顺序遍历树。在这种情况下,a = 5语句将首先被评估并放入一些环境中,然后通过树的其余部分进行线程化。这样,当我们最终到达b = a + 1节点时,当我们在环境中查找a时,我们将返回结果5

编辑1

让我们假设您将变量表示为字符串,并且您的所有值都是整数(显然过于简化),那么您可以想象编写一个解释器以达到以下效果:

int interpretExpr(AST * prog, std::map<string,int>env){
   if(prog is a "variable" node){
      return map.lookup(prog);
   }
   if(prog is a "plus" node){
      return interpretExpr(prog->left, map) + interpretExpr(prog->right, map);
   }
}

std::map<string,int> interpret(AST * prog, std::map<string,int> env){
   if(prog is an "entry" node){
      return interpret(prog->child);
   }
   if(prog is a "seq" node){
      std::map<string,int> newEnv = interpret(prog->leftChild, env);
      return interpret(prog->rightChild, newEnv);
   }
   if(prog is an "exit" node){
      return env;
   }
}

这将采用AST和一个环境,将string s(变量)映射到int s(值)。然后,您可以通过以下方式实现此功能:

这是非常粗略的伪代码,但基本上我的想法是递归地解释语句,通过评估来处理环境。