如何使用antlr语法定义固定次数重复的模式规则

如何使用antlr语法定义固定次数重复的模式规则,antlr,grammar,Antlr,Grammar,我知道“+”、“?”和“*”。但是如果我想要某个东西重复,比如说,5次呢?例如,如果标识符必须是长度为5的十六进制数字字符串 更具体地说,我正在考虑定义一个长度不限的通用lexer规则,然后在解析时计算它重复了多少次,如果它等于5,然后将它重命名为另一种类型的令牌,但我如何才能做到这一点?或者有什么简单的方法吗?您需要指定5次,例如: ZIPCODE: '0'..'9' '0'..'9' '0'..'9' '0'..'9' '0'..'9'; 或者,您可以使用验证语义谓词: DIGIT: '

我知道“+”、“?”和“*”。但是如果我想要某个东西重复,比如说,5次呢?例如,如果标识符必须是长度为5的十六进制数字字符串


更具体地说,我正在考虑定义一个长度不限的通用lexer规则,然后在解析时计算它重复了多少次,如果它等于5,然后将它重命名为另一种类型的令牌,但我如何才能做到这一点?或者有什么简单的方法吗?

您需要指定5次,例如:

ZIPCODE: '0'..'9' '0'..'9' '0'..'9' '0'..'9' '0'..'9'; 
或者,您可以使用验证语义谓词

DIGIT: '0'..'9';
zipcode
@init { int N = 0; }
  :  (DIGIT { N++; } )+ { N <= 5 }?
  ;
数字:“0”…'9';
zipcode
@init{int N=0;}
:(数字{N++;})+{N
在解析时,计算它重复了多少次,如果它等于5,那么将它重命名为另一种类型的令牌,但我如何才能做到这一点?或者有什么简单的方法

是的,您可以使用消歧语义谓词()来实现这一点:

它将按如下方式解析输入
12345 12345678

但您也可以根据匹配文本的某些属性更改lexer中标记的类型,如下所示:

grammar T;

parse
 : (SHORT | LONG)+ EOF
 ;

NUM
 : '0'..'9'+
   {
     if(getText().length() == 5) $type = SHORT;
     if(getText().length() == 8) $type = LONG;
     // when the length is other than 5 or 8, the type of the token will stay NUM
   }
 ;

SP
 : ' ' {skip();}
 ;

fragment SHORT : ;
fragment LONG : ;
这将导致对相同的输入进行如下解析:

grammar T;

parse
 : (SHORT | LONG)+ EOF
 ;

NUM
 : '0'..'9'+
   {
     if(getText().length() == 5) $type = SHORT;
     if(getText().length() == 8) $type = LONG;
     // when the length is other than 5 or 8, the type of the token will stay NUM
   }
 ;

SP
 : ' ' {skip();}
 ;

fragment SHORT : ;
fragment LONG : ;

您好,这在语法分析器中有效。可以在Lexer语法中使用吗?好的,我现在在Lexer语法中使用了它。但是我只能有一个这样的规则。如果我想将长度为5的标记命名为短标记,同时将长度为8的标记命名为长标记,是否可以?Antlr投诉“以下标记定义永远无法匹配”。我的意思是,每次{}?计算为false时,这些字符都将被忽略,但我希望lexer检查其他可能的匹配项。谢谢,我尝试了第二种方法。这正是我要找的。