0

次の構文を使用して、算術式の文法を定義しています。より複雑な全体のサブセットですが、論理演算を含めるように文法を拡張したときにのみ問題が発生しました。

antlrworks を使用して gen をコーディングしようとすると、生成を開始するのに非常に長い時間がかかります。expr の先頭へのループが含まれているため、問題は paren のルールにあると思います。これを修正するための助けは素晴らしいでしょう

前もって感謝します

使用されるオプション:

options {   
tokenVocab = MAliceLexer;
backtrack = true;
}

Grammar のコードは次のとおりです。

type returns [ASTTypeNode n]
: NUMBER {$n = new IntegerTypeNode();}
| LETTER {$n = new CharTypeNode();}
| SENTENCE { $n = new StringTypeNode();}
;   

term  returns [ASTNode n]
 : IDENTIFIER {$n = new IdentifierNode($IDENTIFIER.text);}
| CHAR {$n = new LetterNode($CHAR.text.charAt(1));} 
| INTEGER {$n = new NumberNode(Integer.parseInt( $INTEGER.text ));}
| STRING { $n = new StringNode( $STRING.text ); } 
 ;

paren returns [ASTNode n]
:term { $n = $term.n; }
|  LPAR expr RPAR { $n = $expr.n; }
;

negation returns [ASTNode n]
:BITNEG (e = negation) {$n = new BitNotNode($e.n);}
| paren {$n = $paren.n;}
;

unary returns [ASTNode n]
:MINUS (u =unary) {$n = new NegativeNode($u.n);}
| negation {$n = $negation.n;} 
;

mult returns [ASTNode n]
 :  unary DIV (m = mult)  {$n = new DivideNode($unary.n, $m.n);}
 | unary MULT (m = mult) {$n = new MultiplyNode($unary.n, $m.n);}
 | unary MOD (m=mult)  {$n = new ModNode($unary.n, $m.n);} 
 | unary  {$n = $unary.n;}
 ;

binAS returns [ASTNode n]
 : mult PLUS (b=binAS)  {$n = new AdditionNode($mult.n, $b.n);}
 | mult MINUS (b=binAS)  {$n = new SubtractionNode($mult.n, $b.n);} 
 | mult  {$n = $mult.n;}
 ;

 comp returns [ASTNode n]
: binAS GREATEREQ ( e =comp)  {$n = new GreaterEqlNode($binAS.n, $e.n);}
|binAS GREATER ( e = comp )  {$n = new GreaterNode($binAS.n, $e.n);}
|binAS LESS ( e = comp )  {$n = new LessNode($binAS.n, $e.n);}
|binAS LESSEQ ( e = comp )  {$n = new LessEqNode($binAS.n, $e.n);}
|binAS {$n = $binAS.n;}
;

equality returns [ASTNode n]
: comp EQUAL ( e = equality)  {$n = new EqualNode($comp.n, $e.n);}
|comp NOTEQUAL ( e = equality )  {$n = new NotEqualNode($comp.n, $e.n);}
|comp { $n = $comp.n; }
;   

bitAnd returns [ASTNode n]
: equality BITAND (b=bitAnd) {$n = new BitAndNode($equality.n, $b.n);}
| equality {$n = $equality.n;} 
;

bitXOr returns [ASTNode n]
: bitAnd BITXOR (b = bitXOr) {$n = new BitXOrNode($bitAnd.n, $b.n);}
| bitAnd {$n = $bitAnd.n;}
 ;    

bitOr returns [ASTNode n]
: bitXOr BITOR (e =bitOr) {$n = new BitOrNode($bitXOr.n, $e.n);}
| bitXOr {$n = $bitXOr.n;} 
    ;   

logicalAnd returns [ASTNode n]
: bitOr LOGICALAND (e = logicalAnd){ $n = new LogicalAndNode( $bitOr.n, $e.n ); }
| bitOr { $n = $bitOr.n;  }
;       

expr returns [ASTNode n]
: logicalAnd LOGICALOR ( e = expr ) { $n = new LogicalOrNode( $logicalAnd.n, $e.n); }
| IDENTIFIER INC {$n = new IncrementNode(new IdentifierNode($IDENTIFIER.text));}
    | IDENTIFIER DEC {$n = new DecrementNode(new IdentifierNode($IDENTIFIER.text));} 
    | logicalAnd {$n = $logicalAnd.n;} 
;

`

4

1 に答える 1

1

これは、バージョン 3.3 (およびそれ以降) で導入されたバグのようです。ANTLR 3.2 は、文法からパーサーを生成するときに次のエラーを生成します。

警告 (205): Test.g:31:2: ANTLR は、ルールの等価性でこの決定を分析できませんでした。多くの場合、これは代替の左端から見える再帰的なルール参照が原因です。ANTLR は、k=1 の固定先読みで決定を再分析します。その決定に「オプション{k=1;}」を使用し、場合によっては構文述語を追加することを検討してください。error(10): 内部エラー: org.antlr.tool.Grammar.createLookaheadDFA(Grammar.java:1279): 決定 6 で k=1 を実行できませんでした。理由: タイムアウト (>1000ms)

ANTLR 文法の基礎として LR 文法を使用しているように見えます。最初からやり直すことを検討してください。ただし、LL 解析を念頭に置いてください。次の Q&A を見て、ANTLR を使用して式を解析する方法を確認してください。ANTLR: 簡単な例はありますか?

また、非常によく似たトークンを使用しているように見えます: LETTERCHARSENTENCEおよびIDENTIFIER。たとえば、それらすべてが小文字で始まる可能性がある場合、ルールの 1 つだけが一致することを認識する必要があります (最も一致するもの、または同点の場合は、レクサー文法で最初に定義されたもの)。 . レクサーは、パーサーが「要求」するものに基づいてトークンを生成するのではなく、パーサーとは独立してトークンを作成します。

最後に、単純な式パーサーの場合、実際には述語は必要ありません (これにより、ANTLR はすべてのパーサー ルールbacktrack=trueの前に述語を自動的に挿入します!)。

于 2011-12-12T19:32:32.173 に答える