誰かがこれを手伝ってくれることを本当に願っています。私はRobertStehwienの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'
| '\\' '\"'
| '\\' '\''
| '\\' '\\'
;