0

ANTLR 文法を解析する非常に単純な XML (HTML) があります。

wiki: ggg+;

ggg: tag | text;

tag: '<' tx=TEXT { System.out.println($tx.getText()); } '>';

text: tx=TEXT { System.out.println($tx.getText()); };

CHAR: ~('<'|'>');
TEXT: CHAR+;

このような入力で:"<ggg> fff"正常に動作します。

しかし、空白を扱い始めると失敗します。例えば:

  • " <ggg> fff "- 最初から失敗する
  • "<ggg> <hhh> "- 後に失敗する<ggg>
  • "<ggg> fff "- 正常に動作します
  • "<ggg> "- 最後に失敗する

何が悪いのかわかりません。これを処理するための特別な文法オプションがあるかもしれません。ANTLRWorks は私にNoViableAltException.

4

2 に答える 2

3

ANTLR のレクサー ルールは可能な限り一致します。2 つ (またはそれ以上) のルールが同じ文字数に一致する場合にのみ、最初に定義されたルールが「勝ち」ます。'<'そのため、 and以外の単一の文字は、パーサーが「必要とする」ものに関係なく、トークンではなくトークンとしてトークン'>'化されます (レクサーはパーサーから独立して動作します。覚えておいてください!)。および以外の 2 つ以上の文字のみが (単一の)トークンとしてトークン化されています。CHARTEXT'<''>'TEXT

そのため、入力" <ggg> fff "は次の 5 つのトークンを作成します。

type    | text
--------+-----------
CHAR    |   ' '
'<'     |   '<'
TEXT    |   'ggg'
'>'     |   '>'
TEXT    |   ' fff '

また、トークンCHARはパーサー ルールで考慮されていないため、解析は失敗します。

単純に削除CHARして実行します:

TEXT : ~('<'|'>')+;
于 2012-06-24T14:04:28.803 に答える
1

スペースを処理するためのトークンがありません。lexer のスペースは、遭遇する可能性のある他の文字と同じです。

空白が重要でない場合は、次を使用できます。

WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+    { $channel = HIDDEN; } ;

空白が重要な場合:

WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+
CHAR: ~('<'|'>');
TEXT: (CHAR|WHITESPACE)+;
于 2012-06-24T13:20:37.730 に答える