真的希望有人可以帮助解决这个问题。我一直在使用 Robert Stehwien 的 ANTLR 脚本来为类似公式的 excel 创建 AST。
http://arcanecoder.blogspot.co.uk/2008/04/using-antlr-to-create-excel-like.html
虽然生成的代码在作为 ActionScript 运行时看起来很好,但当我移植到 Java 时,我发现了一个有趣的小问题。
以下公式的树是“+”而不是“(+ 1 2)”。这是我能找到的最简单的情况,但是其他公式也无法创建正确的树。
(1 + 2)
但是,以下工作正常:
1 + 2
有什么想法可能导致这种情况吗?提前谢谢了!!
为下面的代码转储道歉,我不确定我还能如何简单地解释这个问题。这是我用来提取树字符串的代码:
ANTLRStringStream input = new ANTLRStringStream("(1 + 2)");
FormulaLexer lexer = new FormulaLexer(input);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
FormulaParser parser = new FormulaParser(tokenStream);
ParserRuleReturnScope scope = parser.formula();
CommonTree expressionTree = (CommonTree) scope.getTree();
System.out.println(expressionTree.toStringTree());
这是最终的 ANTLR 脚本。这几乎与原始版本相同,但删除了 ActionScript 选项:
/*
Originally written by Robert Stehwien
*/
grammar Formula;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
POS;
NEG;
CALL;
}
@package {com.arcanearcade.antlr}
@lexer::package {com.arcanearcade.antlr}
formula
: (EQ!)? expression
;
//The highest precedence expression is the most deeply nested
//Precedence ties are parsed left to right
//Expression starts with the lowest precedece rule
expression
: boolExpr
;
boolExpr
: concatExpr ((AND | OR | LT | LTEQ | GT | GTEQ | EQ | NOTEQ)^ concatExpr)*
;
concatExpr
: sumExpr (CONCAT^ sumExpr)*
;
sumExpr
: productExpr ((SUB | ADD)^ productExpr)*
;
productExpr
: expExpr ((DIV | MULT)^ expExpr)*
;
expExpr
: unaryOperation (EXP^ unaryOperation)*
;
unaryOperation
: NOT^ operand
| ADD o=operand -> ^(POS $o)
| SUB o=operand -> ^(NEG $o)
| operand
;
// the highest precedence rule uses operand
operand
: literal
| functionExpr -> ^(CALL functionExpr)
| percent
| VARIABLE
| LPAREN expression RPAREN -> ^(expression)
;
functionExpr
: FUNCNAME LPAREN! (expression (COMMA! expression)*)? RPAREN!
;
literal
: NUMBER
| STRING
| TRUE
| FALSE
;
percent
: NUMBER PERCENT^
;
STRING
:
'\"'
( options {greedy=false;}
: ESCAPE_SEQUENCE
| ~'\\'
)*
'\"'
;
WHITESPACE
: (' ' | '\n' | '\t' | '\r')+ {skip();};
TRUE
: ('t'|'T')('r'|'R')('u'|'U')('e'|'E')
;
FALSE
: ('f'|'F')('a'|'A')('l'|'L')('s'|'S')('e'|'E')
;
NOTEQ : '<>';
LTEQ : '<=';
GTEQ : '>=';
AND : '&&';
OR : '||';
NOT : '!';
EQ : '=';
LT : '<';
GT : '>';
EXP : '^';
MULT : '*';
DIV : '/';
ADD : '+';
SUB : '-';
CONCAT : '&';
LPAREN : '(';
RPAREN : ')';
COMMA : ',';
PERCENT : '%';
VARIABLE
: '[' ~('[' | ']')+ ']'
;
FUNCNAME
: (LETTER)+
;
NUMBER
: (DIGIT)+ ('.' (DIGIT)+)?
;
fragment
LETTER
: ('a'..'z') | ('A'..'Z')
;
fragment
DIGIT
: ('0'..'9')
;
fragment
ESCAPE_SEQUENCE
: '\\' 't'
| '\\' 'n'
| '\\' '\"'
| '\\' '\''
| '\\' '\\'
;