2012-12-13 40 views
5

我正在嘗試爲算術和布爾表達式編寫一個語法。我不明白我做錯了什麼。對於我的語法,ANTLR說:ANTLR中的布爾和算術表達式語法

[fatal] rule logic_atom由於從alts 1,2可到達的遞歸規則調用而具有非LL(*)決策。通過左分解或使用語法謂詞或使用backtrack = true選項進行解析。

但我不能做左保理。我不想觸摸arith_expr,因爲我有一個代碼。

錯誤logic_atom : LBR logic_expr RBR | cmp_expr ;

我的代碼:

grammar ArithmeticInterpreter; 

options { 
    output = AST; 
    language = C; 
} 
//options{greedy=true;}: 

axiom : lines EOF! ; 
lines : line (SEP! line)* ; 
line : (def_var | print_expr | scan_expr)? ; 

def_var : VARIABLE ASSIGMENT^ logic_expr ; 
print_expr : PRINT_KEYW^ arith_expr ; 
scan_expr : SCAN_KEYW^ VARIABLE ; 

arith_expr : ((PLS | MNS)^)? term ((PLS | MNS)^ term)*; 
term  : power ((MLP | DIV)^ power)*; 
power  : atom (options{greedy=true;}: PWR^ power)*; 
atom  : INT | FLOAT | VARIABLE | LBR arith_expr RBR -> ^(arith_expr); 

logic_expr : logic_atom ((OR | AND)^ logic_atom)*; 
logic_atom : LBR logic_expr RBR | cmp_expr ; 
cmp_expr: arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ) arith_expr; 

WS : (' '| '\t'| '\r') {$channel=HIDDEN;}; 

LBR : '(' ; 
RBR : ')' ; 
PLS : '+' ; 
MNS : '-' ; 
MLP : '*' ; 
DIV : '/' ; 
PWR : '^' ; 

LSS : '<' ; 
LSQ : '<=' ; 
GRT : '>' ; 
GRQ : '>=' ; 
EQL : '==' ; 
NEQ : '!=' ; 
AND : '&&' ; 
OR : '||' ; 
NOT : '!' ; 

ASSIGMENT : '=' ; 
PRINT_KEYW : 'print' ; 
SCAN_KEYW : 'scan' ; 

SEP : '\n' | ';' ; 

INT : ('0'..'9')+; 

FLOAT : INT '.' INT* EXP? | '.' INT EXP? | INT EXP; 
fragment EXP : ('e'|'E') (PLS | MNS)? INT; 

VARIABLE : SS (SS | '0'..'9')* ; 
fragment SS : 'a'..'z' | 'A'..'Z' | '_' ; 

// (LBR arith_expr)=>是不行的。

回答

3

考慮更改logic_exprcmp_expr這樣:

logic_expr : cmp_expr ((OR | AND)^ cmp_expr)*; 
cmp_expr : (arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ))=> arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ)^ arith_expr 
      | LBR logic_expr RBR -> logic_expr 
      ; 

我刪除的規則logic_atom,因爲它掩蓋了你得到,也不會增加值的誤差。

通過cmp_expr使用語法謂詞,你能告訴ANTLR任何arith_expr後跟一個邏輯符號只會跟一個arith_expr,這意味着,ANTLR遇到任何括號必須屬於一個算術表達式和不合邏輯。

這確保logic_expr只處理布爾值,而arith_expr只處理數值。


我用修改後的語法測試了各種場景,我沒有在ANTLRWorks或我的自定義測試代碼中得到錯誤。你能發佈更多關於你所看到的信息嗎?

這是我正在使用的完整語法。請注意,我刪除了language,以便我可以使用Java進行測試。這應該沒問題,因爲沒有動作/語義謂詞。我也做了一些小的改動,但我不認爲他們是認真的修復。他們用評論表示。

grammar ArithmeticInterpreter; 

options { 
    output = AST; 
} 
//options{greedy=true;}: 

axiom : lines EOF! ; 
lines : line (SEP! line)* ; 
line : (def_var | print_expr | scan_expr)? ; 

def_var : VARIABLE ASSIGMENT^ logic_expr ; 
print_expr : PRINT_KEYW^ arith_expr ; 
scan_expr : SCAN_KEYW^ VARIABLE ; 

arith_expr : ((PLS | MNS)^)? term ((PLS | MNS)^ term)*; 
term  : power ((MLP | DIV)^ power)*; 
power  : atom (PWR^ atom)*; //<-- changed 
atom  : INT | FLOAT | VARIABLE 
      | LBR arith_expr RBR -> arith_expr //<-- changed 
      ; 

logic_expr : cmp_expr ((OR | AND)^ cmp_expr)*; 
cmp_expr : (arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ))=> arith_expr (LSS | LSQ | GRT | GRQ | EQL | NEQ)^ arith_expr 
      | LBR logic_expr RBR -> logic_expr 
      ; 

WS : (' '| '\t'| '\r') {$channel=HIDDEN;}; 

LBR : '(' ; 
RBR : ')' ; 
PLS : '+' ; 
MNS : '-' ; 
MLP : '*' ; 
DIV : '/' ; 
PWR : '^' ; 

LSS : '<' ; 
LSQ : '<=' ; 
GRT : '>' ; 
GRQ : '>=' ; 
EQL : '==' ; 
NEQ : '!=' ; 
AND : '&&' ; 
OR : '||' ; 
NOT : '!' ; 

ASSIGMENT : '=' ; 
PRINT_KEYW : 'print' ; 
SCAN_KEYW : 'scan' ; 

SEP : '\n' | ';' ; 

INT : ('0'..'9')+; 

FLOAT : INT '.' INT* EXP? | '.' INT EXP? | INT EXP; 
fragment EXP : ('e'|'E') (PLS | MNS)? INT; 

VARIABLE : SS (SS | '0'..'9')* ; 
fragment SS : 'a'..'z' | 'A'..'Z' | '_' ; 

鑑於輸入x=(2<3),以下AST樹產生:

(= x (< 2 3)) 

這使得像這樣:

(= x (< 2 3))

修飾的語法還可以處理更復雜的現在的案例,如x = 2 + 3 < 4 || (5^5 > 30 && 3 == 10 + 2)

(= x (|| (< (+ 2 3) 4) (&& (> (^ 5 5) 30) (== 3 (+ 10 2))))) 

a more complex graph

所以嘗試複製語法上面,看是否能解決你的錯誤。如果沒有,讓我更多地瞭解你所看到的錯誤。

+0

我也試過了。爲此antlrworks繪製了一個bug樹。例如:'x =(1 <2)'繪製了一個'(... - > cmp_expr - > NoViableAltExpression)' –

+1

@AlexanderLavrukov我用我用於測試的語法和一些示例輸出更新了答案。當你得到時間時,試着自己運行這個語法來看看它是否給你帶來錯誤。 – user1201210

+2

@AlexanderLavrukov,確保你**不**在測試時使用解釋器。改用調試器。 –

1

我的快速建議是結合arith和邏輯表達式。查看任何示例語法,如Java.g或其他。順便說一句,ANTLR v4可以解決這個問題。