ANTLR v3树行者类.如何评估像阶乘这样的右关联函数



我试图用ANTLR v3构建一个表达式计算器,但我无法获得阶乘函数,因为它是正确的关联函数。这是代码:

class ExpressionParser extends Parser;
options { buildAST=true; }
imaginaryTokenDefinitions :
SIGN_MINUS
SIGN_PLUS;
expr     : LPAREN^ sumExpr RPAREN! ;
sumExpr  : prodExpr ((PLUS^|MINUS^) prodExpr)* ;
prodExpr : powExpr ((MUL^|DIV^|MOD^) powExpr)* ;
powExpr  : runary (POW^ runary)? ;
runary   : unary (FAT)?;
unary    : (SIN^|COS^|TAN^|LOG^|LN^|RAD^)* signExpr;
signExpr : (
     m:MINUS^ {#m.setType(SIGN_MINUS);}
     | p:PLUS^  {#p.setType(SIGN_PLUS);}
     )? atom ;
atom     : NUMBER | expr ;
class ExpressionLexer extends Lexer;
    PLUS  : '+' ;
    MINUS : '-' ;
    MUL   : '*' ;
    DIV   : '/' ;
    MOD   : '%' ;
    POW   : '^' ;
    SIN   : 's' ;
    COS   : 'c' ;
    TAN   : 't' ;
    LOG   : 'l' ;
    LN    : 'n' ;
    RAD   : 'r' ;
    FAT   : 'f' ;
    LPAREN: '(' ;
    RPAREN: ')' ;
    SEMI  : ';' ;
protected DIGIT : '0'..'9' ;
    NUMBER  : (DIGIT)+ ('.' (DIGIT)+)?;
{import java.lang.Math;}
class ExpressionTreeWalker extends TreeParser;
expr returns [double r]
{ double a,b; int i,f=1; r=0; }
 : #(PLUS  a=expr b=expr) { r=a+b; }
| #(MINUS a=expr b=expr) { r=a-b; }
| #(MUL   a=expr b=expr) { r=a*b; }
| #(DIV   a=expr b=expr) { r=a/b; }
| #(MOD   a=expr b=expr) { r=a%b; }
| #(POW   a=expr b=expr) { r=Math.pow(a,b); }
| #(SIN   a=expr       ) { r=Math.sin(a);   }
| #(COS   a=expr       ) { r=Math.cos(a);   }
| #(TAN   a=expr       ) { r=Math.tan(a);   }
| #(LOG   a=expr       ) { r=Math.log10(a); }
| #(LN    a=expr       ) { r=Math.log(a);   }
| #(RAD   a=expr       ) { r=Math.sqrt(a);  }
| #(FAT   a=expr       ) { for(i=1; i<=a; i++){f=f*i;}; r=(double)f;}
| #(LPAREN a=expr)       { r=a; }
| #(SIGN_MINUS a=expr)   { r=-1*a; } 
| #(SIGN_PLUS  a=expr)   { if(a<0)r=0-a; else r=a; }
| d:NUMBER               { r=Double.parseDouble(d.getText()); } ; 

如果我用这样的东西改变TreeWalker类中的FAT匹配情况:

 | #(a=expr    FAT      ) { for(i=1; i<=a; i++){f=f*i;}; r=(double)f;}

我得到这个错误:

 Expression.g:56:7: rule classDef trapped:
 Expression.g:56:7: unexpected token: a
 error: aborting grammar 'ExpressionTreeWalker' due to errors
 Exiting due to errors.

据我所见,您的树漫步器(原始的)很好。

但是,您可能需要在语法中标记FAT

runary : unary (FAT^)?;

(注意帽子^,与所有其他产品一样。)

编辑

正如Antlr3 wiki中所解释的,需要使用hat运算符来使节点成为"为整个封闭规则创建的子树的根,即使嵌套在子规则中也是如此"。在这种情况下,算子嵌套在条件子规则((FAT)?)中。这与运算符是前缀还是后缀无关。

请注意,在您的语法中,运算符不是右关联的,因为a!!根本无效。但我想说,关联性只对中缀运算符有意义。

最新更新