5

算術式とブール式の文法を書こうとしています。私が間違っていることを理解していません。私の文法については、ANTLR は次のように述べています。

[致命的] ルール 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)=>動作しません。

4

2 に答える 2

4

logic_exprandを次のように変更することを検討してくださいcmp_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発生しているエラーを覆い隠し、価値を追加しないため、ルールを削除しました。

の構文述語を使用することで、ANTLRに、論理記号が続く場合は のみが続くcmp_exprことを伝えることができます。つまり、ANTLR が遭遇する括弧は、論理式ではなく算術式に属している必要があります。arith_exprarith_expr

これにより、logic_exprはブール値arith_exprのみを処理し、数値のみを処理します。


変更した文法でさまざまなシナリオをテストしましたが、ANTLRWorks またはカスタム テスト コードでエラーが発生しません。あなたが見ているものについてもっと情報を投稿できますか?

これが私が使用している完全な文法です。languageJavaでこれをテストできるように、を削除したことに注意してください。アクション/セマンティック述語がないため、これで問題ありません。また、いくつかの小さな変更を加えましたが、それらが重大な修正になるとは思っていません。それらはコメントで示されます。

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' | '_' ;

inputを指定x=(2<3)すると、次の AST ツリーが生成されます。

(= x (< 2 3))

次のようにレンダリングされます。

(= × (< 2 3))

修正された文法は、次のようなより複雑なケースも処理できるようになりましたx = 2 + 3 < 4 || (5 ^ 5 > 30 && 3 == 10 + 2)

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

より複雑なグラフ

したがって、上記の文法をコピーして、エラーが修正されるかどうかを確認してください。そうでない場合は、表示されているエラーについて詳しくお知らせください。

于 2012-12-13T21:31:27.190 に答える
1

私の簡単な提案は、算術式と論理式を組み合わせることです。Java.g などのサンプル文法を参照してください。ANTLR v4 はこれを問題なく処理します。

于 2012-12-13T22:43:30.917 に答える