我已经阅读了有关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。
提前致谢。
答案 0 :(得分:2)
因此程序顺序应隐含在语法树中。应该从您的示例生成的树应该是这样的:
enter
|
seq
/ \
/ \
assign \
/ \ seq
a 5 / \
assign ...
/ \
b +
/ \
a 1
您可以想象为您的语言构建一个解释器,它以从左到右的深度优先顺序遍历树。在这种情况下,a = 5
语句将首先被评估并放入一些环境中,然后通过树的其余部分进行线程化。这样,当我们最终到达b = a + 1
节点时,当我们在环境中查找a
时,我们将返回结果5
。
让我们假设您将变量表示为字符串,并且您的所有值都是整数(显然过于简化),那么您可以想象编写一个解释器以达到以下效果:
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(值)。然后,您可以通过以下方式实现此功能:
这是非常粗略的伪代码,但基本上我的想法是递归地解释语句,通过评估来处理环境。