ANTLRでは、レクサーは文字を扱い、パーサーは抽象トークンを扱います。したがって、「文字ABCから始めて、文字XYZまですべての文字を無差別に読む」と言うときはいつでも、「すべての文字」はレクサーには意味がありますが、パーサー。
author
これらの線に沿って、パーサー規則の英語の定義とC++スタイルの単一行コメントの定型句解析規則の類似性を検討してください。
- An
author
は、「BY:」で始まり、行末まですべての文字が続くテキストです。
- 1行のコメントは、「//」で始まり、行の終わりまですべての文字が続くテキストです。
この種の単一行コメントの字句解析規則は、通常、次の形式に従います。
SINGLE_LINE_COMMENT : '//' ~('\r'|'\n')*;
著者行のレクサールールは次のようになります。
AUTHOR : 'BY: ' ~('\r'|'\n')*;
AUTHOR
ただし、生成されるトークンは「BY:」で始まり、それに続くものだけが必要なため、これは正しく機能しません。次のように、最初の文字を削除するか、できればテキストを最初に区切ることができます。
AUTHOR: BY RESTOFLINE; //TODO ignore BY
この分離は、レクサーフラグメントを使用して実行できます。
AUTHOR : BY RESTOFLINE; //TODO ignore BY
fragment BY : 'BY: ';
fragment RESTOFLINE
: ~('\r'|'\n')*;
レクサーフラグメントは、プライベートレクサーレベルマクロのように動作します。レクサールールで参照されている場合にのみ「アクティブ」であり、レクサールールのみがアクティブにできます。(パーサーは名前でフラグメントを参照できますが、通常は参照しないでください...しかし、それは別のトピックです。)
これで、のテキストAUTHOR
のみを含むトークンが必要になります。RESTOFLINE
これは、レクサーアクションを使用すれば簡単です。
AUTHOR : BY RESTOFLINE {setText($RESTOFLINE.text);};
AUTHOR
ルールがRESTOFLINE
フラグメントの読み取りを終了した後、setText
が呼び出されて、送信AUTHOR
トークンのテキストがフラグメントのみからのテキストに変更されRESTOFLINE
ます。
したがって、新しいレクサールールに対応するようにパーサールールを適応させた後、次のような文法になります。
grammar authors;
prog : author+ DASHES;
author : AUTHOR NEWLINE;
NEWLINE : '\r'? '\n' ;
DASHES : '-'+ NEWLINE;
AUTHOR : BY RESTOFLINE {setText($RESTOFLINE.text);};
fragment BY
: 'BY: ';
fragment RESTOFLINE
: ~('\r'|'\n')*;
簡単なテストケースは次のとおりです。
入力
BY: abc123@gmail.com
BY: myCrazy@#$%ID
BY: first_name second_name
-------------------
生成されたトークン
[AUTHOR : abc123@gmail.com] [NEWLINE : ] [AUTHOR : myCrazy@#$%ID] [NEWLINE : ] [AUTHOR : first_name second_name] [NEWLINE : ] [DASHES : -------------------]
これが一般的な文法設計にどの程度役立つかはわかりませんが、トークンパーサーと文字パーサー/レクサーの違いと、それぞれの制限の少しを示すのに役立つことを願っています。