Tree 计算同质AST中的IF子树

Tree 计算同质AST中的IF子树,tree,antlr,antlr3,abstract-syntax-tree,Tree,Antlr,Antlr3,Abstract Syntax Tree,我正在为同质AST构建一个树遍历器(所有节点都有相同的类),计算if语句的正确方法是什么 我的if AST如下所示: 我希望当解析一个IF块时,按顺序计算他的CONDBLOCK子块,如果其中一个是真的,那么树行者不会计算其余的 更清楚地说,我的树行者是这样的: ifStat : ^(IF { jump=false; } condition* defcond?) condition : { if (jump) return retval; } ^(CONDBLOCK exp

我正在为同质AST构建一个树遍历器(所有节点都有相同的类),计算if语句的正确方法是什么

我的if AST如下所示:

我希望当解析一个
IF
块时,按顺序计算他的
CONDBLOCK
子块,如果其中一个是真的,那么树行者不会计算其余的

更清楚地说,我的树行者是这样的:

ifStat       : ^(IF { jump=false; } condition* defcond?) 
condition    : { if (jump) return retval; } ^(CONDBLOCK exp block) { jump=$exp.value; }
defcond      : ^(DEFAULT block)
我的问题是,如果在示例
$op=+
中必须执行第一个
CONDBLOCK
,我不想计算任何其他内容,我想执行第一个
CODEBLOCK
,然后在我的AST树中,在
if
之后计算块

现在我已经用一个标志和一个签入
条件
规则实现了这一点,该规则返回标志是否为真(这意味着另一个块已经被执行)


但是
返回retval完全停止执行,我只想在不评估剩余条件的情况下继续执行。我怎样才能做到这一点呢?

任何一种涉及分支或跳转的AST运行时评估都可能会变得难看。您可能需要考虑将AST转换成一系列更常规的操作并按顺序执行它们。这是一个额外的步骤,但它将使您摆脱像这样的阻塞,我认为它比AST计算器更容易验证和调试

这样,就可以跳过对后续
条件
defcond
规则的评估。我坚持您的结构,这意味着评估有两个不同的阶段:匹配阶段(
exp
)和执行阶段(
block
)。这只值得注意,因为阶段在子图的不同部分处理,没有自然的跳跃方式,因此需要在整个
if
语句中跟踪它们

下面是一个简单的类,用于管理跟踪单个
if
评估:

类评估{
布尔匹配=假;
布尔完成=假;
}
matched
为true且
done
为false时,将执行下一个
。执行后,
done
设置为true。当
matched
done
都为true时,对于
if
语句的剩余部分,不再执行
s

以下是处理此问题的树解析器规则:

ifStat
@init{Evaluation eval=new Evaluation();}
:^(如果条件[eval]*defcond[eval]?)
;
条件[评估]
:^(CONDBLOCK exp{if($exp.value)eval.matched=true;}evalblock[eval])
;
defcond[评估评估]
:^(默认值{eval.matched=true;}evalblock[eval])//强制匹配
;
evalblock[评估]
:{eval.matched&!eval.done}//仅当条件匹配但尚未执行时才执行此操作
block//调用执行代码
{eval.done=true;}//计算已完成。
|^(CODEBLOCK.*)//读取代码子图(不执行任何操作)
;

下面是我用来测试的语法和代码:

treeeevaluator.g(生成AST的组合语法)
语法树赋值器;
选项{
输出=AST;
}
代币{
康德布洛克;
码块;
违约
}
编译单位:条件+EOF;
条件:cif elif*celse?->^(如果cif elif*celse?);
cif:IF expr block->^(CONDBLOCK expr block);
elif:elif expr block->^(CONDBLOCK expr block);
celse:ELSE块->^(默认块);
表达式:ID EQ^ID;
块:LCUR ID RCUR->^(代码块ID);
如果:‘如果’;
以利夫:“以利夫”;
ELSE:‘ELSE’;
立法会二题:{};
RCUR:'}';
等式:'=';
ID:('a'..'z'|'a'..'z')+;
WS:(“”|’\t’|’\f’|’\r’|’\n’+{skip();};
astreeeevaluatorparser.g(树解析器)
树语法astreeeevaluatorparser;
选项{
输出=AST;
tokenVocab=树评估器;
ASTLabelType=CommonTree;
}
@成员{
私人静态期末评估{
布尔匹配=假;
布尔完成=假;
}
private java.util.HashMap vars=new java.util.HashMap();
public void addVar(字符串名,int值){
变量put(名称、值);
}
}
编译单位:ifStat+;
ifStat
@init{Evaluation eval=new Evaluation();}
:^(如果条件[eval]*defcond[eval]?)
;
条件[评估]
:^(CONDBLOCK exp{if($exp.value)eval.matched=true;}evalblock[eval])
;
defcond[评估评估]
:^(默认值{eval.matched=true;}evalblock[eval])//强制匹配
;
evalblock[评估]
:{eval.matched&!eval.done}//仅当条件匹配但未完成时才执行此操作
block//调用执行代码
{eval.done=true;}//计算已完成。
|^(CODEBLOCK.*)//读取代码节点并继续而不执行
;
block:^(代码块ID){System.out.println(“已执行”+$ID.getText());};
exp返回[布尔值]
:^(等式lhs=ID rhs=ID)
{$value=vars.get($lhs.getText())==vars.get($rhs.getText());}
;
TreeEvaluatorTest.java(测试代码)
公共类树评估测试{
公共静态void main(字符串[]args)引发异常{
CharStream input=newantlrstringstream(“如果a==b{b}elif a==c{c}elif a==d{d}else{e}”);
treeeevaluatorlexer=新的treeeevaluatorlexer(输入);
CommonTokenStream令牌=新的CommonTokenStream(lexer);
treeeevaluatorparser=新的treeeevaluatorparser(令牌);
treeeevaluatorparser.compliationunit\返回结果=parser.compliationunit(