我有以下语法:
grammar tryout;
tryout : my_cmd
;
my_cmd
: 'start' '0'..'9'+ Name_string
;
Digit
: '0'..'9'
;
Name_string
: ('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*
;
如果我在ANTLRworks中看到图表,'0'..'9'+显示为空元素,因此Java代码编译失败,因为生成的代码具有“if()”语句;如果我在命令行运行,编译也会失败。
修复方法是将'0'..'9'+移动到词法分析器规则。
grammar tryout;
tryout : my_cmd
;
my_cmd
: 'start' Digit+ Name_string
;
Digit
: '0'..'9'
;
Name_string
: ('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*
;
但我想知道这是不是一个错误。为什么range元素不能用于解析器规则?这是在ANTLR v3.4上。
答案 0 :(得分:1)
在解析器规则内部,..
不能作为字符的范围运算符,因为它在词法分析器规则中。另请注意,即使您在解析器规则中定义了文字,ANTLR也会为它们动态创建词法规则,如下所示:
my_cmd
: 'start' '0'..'9'+ Name_string
;
相当于:
my_cmd
: Start D0..D9+ Name_string
;
Start : 'start';
D0 : '0';
D9 : '9';
如果内存为我服务,早期版本的ANTLR v3支持解析器规则中的范围运算符表示:匹配D0
和D9
之间的任何标记,但这是非常脆弱的。在D0
和D9
之间添加规则会改变其含义:
D0 : '0';
FOO : 'foo';
D9 : '9';
解析器规则:
my_cmd
: '0'..'9'+
;
现在会匹配以下其中一个令牌:D0
,FOO
或D9
。
解析器规则中的..
支持已从(至少)v3.3及更高版本中删除。因此,不要在解析器规则中使用..
。