5

私は次の文法を持っています:

grammar tryout;

tryout :  my_cmd
        ;

my_cmd
    : 'start'   '0'..'9'+  Name_string
    ;

Digit
    : '0'..'9'
    ;

Name_string
    : ('A'..'Z' | 'a'..'z')  ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*
    ;

ANTLRworks でダイアグラムを見ると、'0'..'9'+ が空の要素として表示され、生成されたコードに "if ()" ステートメントがあるため、Java コードのコンパイルが失敗します。コマンドラインで実行すると、コンパイルも失敗します。

修正は、'0'..'9'+ をレクサー ルールに移動することです。

grammar tryout;

tryout :  my_cmd
        ;

my_cmd
    : 'start'   Digit+  Name_string
    ;

Digit
    : '0'..'9'
    ;

Name_string
    : ('A'..'Z' | 'a'..'z')  ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*
    ;

しかし、これはバグなのだろうか。パーサー規則で範囲要素を使用できないのはなぜですか? これはANTLR v3.4にあります。

4

1 に答える 1

1

パーサー ルール内で..は、レクサー ルール内のように、文字の範囲演算子として機能しません。また、パーサー ルール内でリテラルを定義した場合でも、ANTLR はその場でそれらのレクサー ルールを作成し、次のようにすることに注意してください。

my_cmd
 : 'start' '0'..'9'+ Name_string
 ;

に相当:

my_cmd
 : Start D0..D9+ Name_string
 ;

Start : 'start';
D0    : '0';
D9    : '9';

メモリが役立つ場合、以前のバージョンの ANTLR v3 サポーターはパーサー ルール内の範囲演算子を意味します: と の間の任意のトークンに一致しますD0D9、これは非常に脆弱です。D0と の間にルールを追加するとD9、その意味が変わります。

D0    : '0';
FOO   : 'foo';
D9    : '9';

パーサー規則:

my_cmd
 : '0'..'9'+
 ;

次のトークンのいずれかと一致するようになりました: D0FOOまたはD9.

この..パーサー ルール内のサポートは、(少なくとも) v3.3 以降では削除されています。..そのため、パーサー規則内で使用しないでください。

于 2012-12-08T18:39:03.013 に答える