我在这里和这里问了相关问题,现在我有一个新问题,但实际上我是在问一些一般的思维规则。
这是语法:
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”有关。
我相信原因是,正如 Bart 在另一个线程中指出的那样,当有“abc__”这样的输入时,它可以被解析为“abc_”(cmd_name)和“_”(action_cmd_def/cmd_chars)或“abc__”(cmd_name )。
这是我的问题:1)如何解决?我尝试在 cmd_name 前添加“options {greedy=true;}”,但错误仍然存在。
2)我知道如果我把cmd_name和action_cmd_def合二为一,那么问题就没有了,这就导致了语法粒度的问题。由于ANTLR有这么强大的lexer/parser功能,我很喜欢用语法来过滤掉有意义的字符串,在这种情况下,我知道“action_cmd”的输入数据必须以命令名称字符串开头,然后跟着一些乱七八糟的东西,所以我喜欢把这两部分分开的语法;否则我将不得不使用目标语言(在我的例子中是 C)来编写动作部分,但是更深入的粒度会带来很多麻烦,我怀疑我是否走错了路。
有了这个,我想问一下,你对语法粒度的经验法则是什么?我在使用语法时会发疯吗?