私はANTLR4を使ってパーサーを生成しています。私はパーサーの文法には新しいです。私は非常に役に立ちましたANTLR Mega Tutorialを読んだことがありますが、私はまだレクサーとパーサーの規則を正しく(そして/または書く)方法に固執しています。私は、パーサはこのようなものを扱うことができるようにしたいANTLR4を使用して文法でレクサールールを注文する
:
こんにちは< <名>>、お元気ですか?
実行時に「< < >>」をユーザーの名前に置き換えます。
私はレクサールールで "func"と呼ぶ "< < something"というタグを除いて、ほとんどがテキストワード(と句読点、記号など)を解析しています。ここで
は私の文法である:
doc: item* EOF ;
item: (func | WORD) PUNCT? ;
func: '<<' ID '>>' ;
WS : [ \t\n\r] -> skip ;
fragment LETTER : [a-zA-Z] ;
fragment DIGIT : [0-9] ;
fragment CHAR : (LETTER | DIGIT | SYMB) ;
WORD : CHAR+ ;
ID: LETTER (LETTER | DIGIT)* ;
PUNCT : [.,?!] ;
fragment SYMB : ~[a-zA-Z0-9.,?! |{}<>] ;
サイドノート:私は "PUNCTの?" 追加しました上記の例の文章のように、 "func"の直後にコンマを置くことができるので、 "item"ルールの最後に。しかし、 "WORD"の後にコンマを置くこともできるので、 "func"と "WORD"の両方でなく、 "item"に句読点を入れることにしました。
私は上記の文で、このパーサを実行する場合、私はこのようになります解析木を取得:赤で強調表示
ものはパースエラーです。
したがって、「ID」として二重山括弧内の「ID」は認識されません。おそらくこれは、 "WORD"が私のレクサールールのリストの中で最初に来るからです。しかし、私は "< < WORD >>"というルールはありません。 "< < >>"というルールしかないので、なぜそれが起こっているのかは分かりません。
私は今、彼らはこの順序である、私の文法で「ID」の順と「WORD」を交換する場合: :
ID: LETTER (LETTER | DIGIT)* ;
WORD : CHAR+ ;
"func"ルールと "ID"ルールは適切に処理されていますが、 "WORD"は認識されません。
どうすればこの問題を回避できますか?
「func」ルールを「< < WORD >>」に変更し、すべてを単語として扱い、「ID」で取り除くことが1つの選択肢と考えられます。しかし、私はテキストワードを可変識別子と区別したいと考えました(たとえば、可変識別子に特殊文字は使用できません)。
ありがとうございました!
私はANTLRユーザーではありませんが、ANTLRは私が使った他のパーサジェネレータと同じように動作します:トークンは上から下への文法に関係なく認識されます。したがって、もし何かが 'WORD'と' ID'の両方にマッチすれば、それは常に文法の定義で最初に定義されたトークンとして認識されます。ですから、両方の場所で共通のトークン定義が必要になるでしょう。構文解析後、使用する文字が制作の要件と一致しているかどうかを確認できます。 –