5

我有以下语法:

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' | '_')*
    ;

但我想知道这是否是一个错误。为什么范围元素不能在解析器规则中使用?这是在 ANTLR v3.4 上。

4

1 回答 1

1

在解析器规则中,..不像在词法分析器规则中那样用作字符的范围运算符。另请注意,即使您在解析器规则中定义了文字,ANTLR 也会为它们动态创建词法分析器规则,从而进行以下操作:

my_cmd
 : 'start' '0'..'9'+ Name_string
 ;

相当于:

my_cmd
 : Start D0..D9+ Name_string
 ;

Start : 'start';
D0    : '0';
D9    : '9';

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

D0    : '0';
FOO   : 'foo';
D9    : '9';

解析器规则:

my_cmd
 : '0'..'9'+
 ;

现在将匹配以下标记之一:D0,FOOD9.

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

于 2012-12-08T18:39:03.013 回答