0

我在这里这里问了相关问题,现在我有一个新问题,但实际上我是在问一些一般的思维规则。

这是语法:

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)来编写动作部分,但是更深入的粒度会带来很多麻烦,我怀疑我是否走错了路。

有了这个,我想问一下,你对语法粒度的经验法则是什么?我在使用语法时会发疯吗?

4

1 回答 1

-1

这是一个真正的模棱两可,但贪婪的选择应该适合你。也许它需要在子规则级别?看看这是否有效:

cmd_name
    : 'a'..'z' (options {greedy=true;} : 'a'..'z' | '0'..'9' | '_'  )*

至于你问题的第二部分,我认为你的规则粒度很好。如果存在不只需要贪婪标志来解决的歧义,您还可以求助于使用句法谓词。它在 ANTLR 3 书中有很好的记录,但在网站上却不是很好。

这相当于尝试在语法上匹配谓词。如果它成功,那么它真正匹配它,如果它失败,那么它使用其他替代方案。例如,在 C 语言中,您不知道是否有函数声明或定义,直到看到声明的结尾,声明的长度没有下限。因此,您使用句法谓词说“让我们看看它是否是一个声明,如果是,则将其真正匹配,如果不是,则尝试其他替代方案。

externalDef
    :       ( "typedef" | declaration )=> declaration
    |       functionDef
    |       asm_expr
    ;
于 2013-02-15T19:35:31.427 回答