2012-06-02 33 views
1

真的希望有人能夠幫助解決這個問題。我一直在玩羅伯特史蒂文的ANTLR腳本,爲excel公式創建AST。ANTLR ActionScript到Java問題

http://arcanecoder.blogspot.co.uk/2008/04/using-antlr-to-create-excel-like.html

雖然它看起來動作腳本運行時,如生成的代碼是好的,當我到渣口,我發現一個有趣的小問題。

下面的公式有一個「+」而不是「(+ 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腳本。這幾乎等同於原,去除動作腳本選項:

/* 
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' 
    | '\\' '\"' 
    | '\\' '\'' 
    | '\\' '\\' 
    ; 

回答

1

始終確保任何AST的根是一個單一的(唯一的)令牌(不是解析器規則),並在重寫的情況下,單解析器規則,不做... -> ^(single_parser_rule)而是簡單地做:... -> single_parser_rule

所以你的情況,在operand規則,改變-> ^(expression)-> expression

operand 
    : literal 
    | functionExpr -> ^(CALL functionExpr) 
    | percent 
    | VARIABLE 
    | LPAREN expression RPAREN -> expression 
    ; 
+0

救星。謝謝! – Blueberry

+0

不客氣@Blueberry。 –