Range元素不能用于解析器规则?

my_*_*ion 5 antlr

我有以下语法:

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' | '_')*
    ;
Run Code Online (Sandbox Code Playgroud)

如果我在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' | '_')*
    ;
Run Code Online (Sandbox Code Playgroud)

但我想知道这是不是一个错误.为什么range元素不能用于解析器规则?这是在ANTLR v3.4上.

Bar*_*ers 1

在解析器规则中,..它不像词法分析器规则中那样充当字符的范围运算符。另请注意,即使您在解析器规则中定义了文字,ANTLR 也会动态地为它们创建词法分析器规则,如下所示:

my_cmd
 : 'start' '0'..'9'+ Name_string
 ;
Run Code Online (Sandbox Code Playgroud)

相当于:

my_cmd
 : Start D0..D9+ Name_string
 ;

Start : 'start';
D0    : '0';
D9    : '9';
Run Code Online (Sandbox Code Playgroud)

如果我没记错的话,早期版本的 ANTLR v3 支持解析器规则内的范围运算符,意思是:匹配 和 之间的任何标记D0D9但这非常脆弱。D0在和之间添加规则D9会改变它的含义:

D0    : '0';
FOO   : 'foo';
D9    : '9';
Run Code Online (Sandbox Code Playgroud)

解析器规则:

my_cmd
 : '0'..'9'+
 ;
Run Code Online (Sandbox Code Playgroud)

现在将匹配以下标记之一:D0FOOD9

解析器规则内部的这种..支持已从(至少)v3.3 及更高版本中删除。因此,不要使用..内部解析器规则。