我想要一个只包含二进制非终端的语法和评估器(ANTLR解析树walker),而不需要在访问表达式节点时切换操作符以确定要执行的操作因为访问者将访问“additionNode”,因此访问者可以静态假设它必须执行另外的)。利用ANTLR 4的左递归消歧
相当直接的问题。 ANTLR支持左递归,所以这是一个有效的语法
expr :
| expr ('+'|'-') expr
| expr ('*'|'/') expr
| '(' expr ')'
| literal
;
漂亮的,但是任何沃克/参观者/编译器后端的这个现在已经做到对各类自身的调度,它太臭:
onVisitExit(ExprContext ctx){
left = compiledMap.get(ctx.getChild(0));
right = compiledMap.get(ctx.getChild(2));
operator = ctx.getChild(1);
switch(operator.getToken()){
case "+": compiledMap.put(ctx, left + right);
case "-": compiledMap.put(ctx, left - right);
case "*": compiledMap.put(ctx, left * right);
case "/": compiledMap.put(ctx, left/right);
}
}
利弊这一战略:
- ANTLR建立二叉树对我来说,在哪里(二)每个规则有一个左和右的说法,意思是我不担心,而对克林循环关闭。我真的很喜欢这个
- 我必须在令牌上手动调度(切换),而不是在节点的类型上。
使用更传统的&已经离开-因素语法
expr : addOrSub ;
addOrSub : multOrDiv (('+'/'-') multOrDiv)* ;
multOrDiv : bracks (('*'/'/') backs)* ;
bracks : '(' expr ')' | literal ;
literal : TOKEN ;
此相应的访问者有相反的利弊上面的一个2语法:ANTLR会做类型此调度对我来说 - 大多数情况下,仍然必须区分'+'和' - ' - 但现在我必须包含用于那些kleene闭包的while循环,因为我没有严格的二叉树了,这很烦人。
我想,我理想中的语法会是这样
expression : expr ;
fragment expr :
(addition | subtraction)
| (multiplication | division)
| brackets
| literal
;
addition : expr '+' expr ;
subtraction : expr '-' expr ;
multiplication : expr '*' expr ;
division : expr '/' expr ;
brackets : '(' expr ')' ;
literal : TOKEN ;
这将解决我的所有问题,当然除了在ANTLR
您可以“接受”自己的答案... – 2015-05-11 18:53:26