4

次の非常に単純な文法の例は、私が期待したように (まったく) lex しません。

Declaration :   'VAR';
Letter: ('A'..'Z');

message :   Declaration Letter+;

結果として私が期待したのは、文字のシーケンスは個々の文字として lex され、シーケンス 'VAR' は単一のトークンとして lex されることです。

ANTLRWorksインターパーターを見ると、次の結果が表示されます。

  • VARAに解析しますmessage -> "VAR", "A"(期待)
  • VARVA(MismatchedTokenException(-1 != 5) を解析しません。レクサーは 2 番目にヒットし、VAトークン化を試みDeclarationます。期待される:message -> "VAR", "V", "A"
  • VARVPPに解析しますmessage -> "VAR", "V", "P", "P"(期待)
  • VARVALLに解析しmessage -> "VAR", "VALL"ます。

この動作を理解するための助けと、これを修正する方法を提案したいと思います。

具体的には:

  • lexer が で始まるすべての文字列をVADeclaration にトークン化しようとするのはなぜですか?
  • lexer が a で始まるすべての文字列でこれを実行しようとしないのはなぜVですか?
  • そこに追加の文字がある場合、レクサーがこれを実行しようとしないのはなぜですか?
  • この文法を変更して、期待どおりに解析するにはどうすればよいですか?
4

2 に答える 2

5

あなたの4つの例をすべて見てみましょう:

1 「ヴァラ」

ここに画像の説明を入力

すべて大丈夫です。

2 "VARVA"

"VAR"は (明らかに) としてトークン化されますVARが、レクサーはそこにない を「見て」"VA"期待します。"R"次のエラーが発生します。

line 1:5 mismatched character '<EOF>' expecting 'R'
line 1:5 required (...)+ loop did not match anything at input '<EOF>'

"VA"ANTLRWorksのデバッガーを実行するとわかるように、作成される単一のトークンで結果を破棄します(解析の例外は無視してください。実際には存在しません:)):

ここに画像の説明を入力

認識しなければならないことは、レクサーは、すでに一致したものをあきらめないということです。そのため、レクサーが を認識 し、その後に"VA"一致できない場合は、 に一致する他のレクサー ルールを調べます。しかし、それは一致しません (1 文字のみに一致します!) 1 文字以上に一致するように変更すると、ANTLR はそのルールにフォールバックできます。ただし、単一の文字に一致する場合はそうではありません。レクサーは、ルールを一致させるためにfromを放棄しません。それを回避する方法はありません。これが ANTLR のレクサーの仕組みです。"R""VA"LetterLetter"A""VA"Letter

IDENTIFIERこれは、通常、キーワードが一致しない場合にレクサーがフォールバックできる何らかのルールがあるため、問題にはなりません。

3 "VARVPP"

ここに画像の説明を入力

すべて問題ありません:"VAR"が aになり、その後、レクサーは an の後VARに一致しようとしますが、これは起こらないため、レクサーは単一の のルールにフォールバックします。その後、両方とも s としてトークン化されます。"A""V"Letter"V""PP"Letter

4「バーバル」

"VAR"再び になりますVAR。次に、"L"in"VAL"により、レクサーは次のエラー メッセージを生成します。

line 1:5 mismatched character 'L' expecting 'R'

そして最後は次の"L"ようになりますLetter:

ここに画像の説明を入力


最初の 3 つの質問が回答されていると思います (または希望します)。これで、最終的な回答が残ります。

この文法を変更して、期待どおりに解析するにはどうすればよいですか?

lexer が文字ストリームを先読みするように強制することにより、実際に"VAR"先読みがある場合は、次のように、1 つだけ一致し"V"、一致したトークンの型を に変更しますLetter

Declaration
 : ('VAR')=> 'VAR'
 |           'V'   {$type=Letter;}
 ;

私の回答の前に述べたように、この関連する Q&A を参照してください: ANTLR lexer can't lookahead at all

于 2012-12-03T12:42:15.700 に答える
2

レクサーは実際には先読みを実行せず、パーサーのみが実行します。あなたはANTLRでそれについてもっと読むことができますレクサーはまったく先を見越すことができません。したがって、ここでの問題は、レクサーが一致VARしなくなると、これまでに取得したものと一致しようとすることVAです---文字は2文字、つまり1文字と一致できないため、一致するトークンはありません。

解決策としては、簡単な方法は、それを単一のトークンに変更することです。

Message :   'VAR' ('A'..'Z')+;
message :   Message;

ただし、文字ごとに異なるトークンを取得することはありません。

于 2012-12-03T12:14:14.087 に答える