1

ログ ファイルを解析するための ANTLR 文法を作成していて、問題に直面しました。次のように問題を再現するために文法を単純化しました。

stmt1:
  '[ ' elapse ': ' stmt2
  ;

stmt2:
  '[xxx'
  ;

stmt3:
  ': [yyy'
  ;

elapse :
  FLOAT;

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* 
    ;

次の文字列を使用して文法をテストしたとき:

[ 98.9: [xxx

エラーが発生しました:

E:\work\antlr\output\__Test___input.txt line 1:9 mismatched character 'x' expecting 'y'
E:\work\antlr\output\__Test___input.txt line 1:10 no viable alternative at character 'x'
E:\work\antlr\output\__Test___input.txt line 1:11 no viable alternative at character 'x'
E:\work\antlr\output\__Test___input.txt line 1:12 mismatched input '<EOF>' expecting ': '

しかし、ルール「stmt3」を削除すると、同じ文字列が受け入れられます。

何が起こったのかわかりません...

アドバイスをありがとう!

レオン


バートからの助けに感謝します。私は文法を修正しようとしました。ベースラインとして、すべてのトークンを明確にする必要があると思います。そして、ルールを簡素化するために WS トークンを追加します。

stmt1:
  '[' elapse ':' stmt2
  ;

stmt2:
  '[' 'xxx'
  ;

stmt3:
  ':' '[' 'yyy'
  ;

elapse :
  FLOAT;

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* 
    ;

WS : (' ' |'\t' |'\n' |'\r' )+ {skip();} ;   
4

1 に答える 1

4

ANTLR では、レクサー ルール (トークン) とパーサー ルールが厳密に分離されています。パーサー規則内でいくつかのリテラルを定義しましたが、それらは依然としてトークンです。これは、次の文法が (実際には) サンプル文法と同等であることを意味します。

stmt1  : T1 elapse T2 stmt2 ;
stmt2  : T3 ;
stmt3  : T4 ;
elapse : FLOAT;

T1     : '[ ' ;
T2     : ': ' ;
T3     : '[xxx' ;
T4     : ': [yyy' ;
FLOAT  : ('0'..'9')+ '.' ('0'..'9')* ;

ここで、レクサーが入力からトークンを作成しようとすると、トークンとが"[ 98.9: [xxx"正常に作成されますが、 が表示されると、トークンを作成しようとします。しかし、ストリーム内の次の文字が aではなく a である場合、レクサーは で始まる別のトークンを作成しようとします。しかし、そのようなトークンがないため、レクサーは次のエラーを発行します。T1FLOAT ": ["T4"x""y"": ["

[...] 'y' を期待する文字 'x' が一致しません

いいえ、lexer は、 token に一致する文字"["を「あきらめる」ためにバックトラックすることも、トークンを実際に構築できるかどうかを確認するために char-stream を先読みすることもありません。ANTLR の LL(*) はパーサー ルールにのみ適用され、レクサー ルールには適用されません!": ["T2T4

于 2012-10-29T18:45:14.917 に答える