こことここで関連する質問をしましたが、新しい質問がありますが、実際には一般的な考え方を求めています。
文法は次のとおりです。
grammar post2;
post2: action_cmd+
;
action_cmd
: cmd_name action_cmd_def
;
action_cmd_def
: (cmd_chars | cmd_literal)+ Semi_colon
;
cmd_name
: 'a'..'z' ('a'..'z' | '0'..'9' | '_' )*
;
cmd_chars
: ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '.' | ':' | '-' |'\\')
;
cmd_literal
: SINGLE_QUOTE ~(SINGLE_QUOTE | '\n' | '\r') SINGLE_QUOTE
;
SINGLE_QUOTE
: '\''
;
Semi_colon
: ';'
;
WS : ('\t' | ' ')+ {$channel = HIDDEN;};
New_Line : ('\r' | '\n')+ {$channel = HIDDEN;};
このエラーが発生したのは当然のことです-
warning(200): post2.g:16:45:
Decision can match input such as "'_'" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
エラーはルール「cmd_name」に関するものです。
その理由は、バートが別のスレッドで示したように、「abc__」などの入力がある場合、「abc_」(cmd_name) および「_」(action_cmd_def/cmd_chars) または「abc__」(cmd_name) として解析できるためだと思います。 )。
ここに私の質問があります:1)それを修正する方法は?cmd_name の前に「options {greedy=true;}」を追加しようとしましたが、エラーは解決しません。
2) cmd_name と action_cmd_def を 1 つに結合すれば、問題はなくなります。これは、文法の粒度の問題につながります。ANTLR には非常に強力なレクサー/パーサー機能があるため、文法を使用して意味のある文字列を除外するのが本当に好きです。この場合、「action_cmd」の入力データはコマンド名文字列で始まり、いくつかの乱雑なもの、だから私は文法が2つの部分を分けるのが好きです; それ以外の場合は、ターゲット言語 (私の場合は C) を使用してアクション部分を作成する必要がありますが、より深い粒度に進むと非常に多くの問題が発生するため、間違った方向に進んでいるかどうか疑問に思います。
これで、文法の粒度の経験則は何ですか? 私は文法を使うことに夢中になっていますか?