1

これは、次の質問の「フォローアップ」です:括弧で囲まれた階層ルートを解析する方法は? (rootルールの名前が変更されたことに注意してくださいatom)。

私のANTLR文法では、キャストのサポートを追加しようとしました:

cast : '(' type ')' atom -> ^(CAST type atom);

ここで、それを値ツリーの一部にする必要があります。キャストはそれ自体がアトミックであり、階層のベースになることができ、任意のバイナリ演算 (因数、合計、比較) で使用できるため、atom(以前のroot) ルールに準拠する必要があると考えました。

cast : '(' type ')' atom -> ^(CAST type atom);

atom : cast | IDENTIFIER | SELF | literal | constructor | call | indexer | '('! value ')'!;

hierarchy : atom (SUB^ (IDENTIFIER | call | indexer))*;

factor : hierarchy ((MULT^ | DIV^ | MODULO^) hierarchy)*;

sum : factor ((PLUS^ | MINUS^) factor)*;

comparison : sum (comparison_operator^ sum)*;

value : comparison;

幸いなことに、今回はすべてが LL(*) で十分のようです。ただし、からへの無限再帰を取得typetypeます。

type : name=IDENTIFIER (LESSER (generics+=type (SEPARATOR generics+=type)*) GREATER)? -> ^(TYPE $name ^(GENERICS $generics*));

[ルールアトム] 代替案 1 [キャスト]: PAREN_OPEN IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER LESSER IDENTIFIER {LESSER, SEPARATOR} 決定などの入力を照合した後、から型への再帰オーバーフローにより、次に来るものを予測できません

このケースは、 などを反映してい(x<x<x<x<x[</,]ます。

ANTLR のエラーは非常に不可解です。この正確なエラーを説明している章を読み直しましたが、まだわかりません。私が理解していないのは、スタンドアロンベースでは、typeルールが無限再帰の警告をトリガーしなかったということです。

どうすれば修正できますか?そして、ANTLR についての私の理解のために、なぜそれが今トリガーされるのか説明してもらえますか?

4

1 に答える 1

2

ANTLRのエラーメッセージは(すべて)侵入できないとまでは言いませんが、ええ、このエラーは...

IDENTIFIER < atomこの場合、ANTLRには関係式とIDENTIFIER < ...それがの一部であるものを区別するのに問題がありtypeます。これらの選択肢は両方とも、atomルールの始まりになる可能性があります。

これは、ジェネリック型の開始を変更して、リレーショナルLT式の開始と同じにならないようにすることで確認できます。

type
 : IDENTIFIER ('@' (type (',' type)*) '>')?
 ;

または、LT記号を汎用タイプのままにしますが、ルールIDENTIFIERからを削除します。atom

type
 : IDENTIFIER ('<' (type (',' type)*) '>')?
 ;

atom
 : cast 
 //| IDENTIFIER
 | SELF
 | literal
 | constructor
 | call
 | indexer
 | '('! value ')'!
 ;

もちろん、どちらも現実的な選択肢ではありません。

castANTLRを文法に満足させるには、ルールの選択肢の直前に構文述語を追加しますatom(そして、type現在のルールのままにします)。

atom
 : (cast)=> cast 
 | IDENTIFIER
 | SELF
 | literal
 | constructor
 | call
 | indexer
 | '('! value ')'!
 ;

これにより、パーサーは最初に先を見越して、一致する代替案が実際に存在することを確認し、一致しない場合は、ルールcastの後半の代替案にフォールスルーします。atom

ただし、ここでのより良いオプションは、文法を次のような関係式と一致させないことです。

a < b < c

これはあまり意味がありません。リレーショナル式a < bは通常、ブール値と評価されますが、これと比較することはできませんc。また、すべての論理演算子、関係演算子、等式演算子を1つのルールにグループ化して、すべて同じ優先順位を設定します。ほとんどの場合、OR最も低く、AND次に等式、次に関係演算子が続きます。

したがって、代わりに:

value      : comparison;
comparison : sum (comparison_operator^ sum)?;
...

comparison_operator : EQUAL | NOT_EQUAL | GREATER | LESSER
                    | GREATER_OR_EQUAL | LESSER_OR_EQUAL 
                    | AND | OR
                    ;

行う:

value : or;
or    : and (OR^ and)*;
and   : eq (AND^ eq)*;
eq    : rel ((EQUAL | NOT_EQUAL)^ rel)?; // note the '?' and no '*'
rel   : sum ((GREATER | LESSER | GREATER_OR_EQUAL | LESSER_OR_EQUAL)^ sum)?; // note the '?' and no '*'
sum   : factor ((PLUS | MINUS)^ factor)*;
...

type次に、atomルール前に述語を置く必要がなく、演算子が適切な順序で優先されます。

于 2012-05-03T06:50:07.043 に答える