多语言和语法粒度的经验法则

时间:2013-02-08 06:39:10

标签: antlr

我问过相关问题herehere,现在我有了一个新问题,但我真的要求一些一般的思考规则。

这是语法:

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具有如此强大的词法分析器/解析器功能,我真的很喜欢使用语法来过滤掉有意义的字符串输出,在这种情况下,我知道“action_cmd”的输入数据必须以命令名字符串开头然后跟着一些凌乱东西,所以我喜欢把语法分开来做两部分;否则我将不得不使用目标语言(在我的情况下为C)编写动作部分,但是更深入的粒度会带来很多麻烦,我怀疑我是否处于错误的轨道。

有了这个,我想问一下,从语法粒度来看,你的经验法则是什么?我疯狂地使用语法吗?

1 个答案:

答案 0 :(得分:-1)

这是一种真正的歧义,但贪婪的选择对你有用。也许它需要处于子规则级别?看看是否有效:

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

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

它等于尝试在句法上匹配谓词。如果它成功,那么它匹配它是真的,如果它失败然后它使用其他选择。例如,在C中你不知道你是否有一个函数声明或定义,直到你看到声明的结尾,它的长度没有下限。所以你使用一个句法谓词说“让我们看看它是否是一个声明,如果是,那么将它与真实匹配,如果不是,那么尝试其他选择。”

externalDef
    :       ( "typedef" | declaration )=> declaration
    |       functionDef
    |       asm_expr
    ;