我知道'+','?'和'*'。但是,如果我想要一些东西重复,比如5次呢?例如,如果标识符必须是长度为5的十六进制数字的字符串
更具体地说,我正在考虑定义一个无限长度的通用词法分析器规则,然后在解析时计算它重复的时间,如果等于5,则将其重命名为另一种类型的令牌,但我怎么能这样做?或者有一些简单的方法吗?
答案 0 :(得分:4)
在解析时计算重复的时间,如果它等于5,则将其重命名为另一种类型的令牌,但我该怎么办呢?或者有一些简单的方法吗?
是的,你可以用消除歧义的语义谓词(explanation)来做到这一点:
grammar T;
parse
: (short_num | long_num)+ EOF
;
short_num
: {input.LT(1).getText().length() == 5}? NUM
;
long_num
: {input.LT(1).getText().length() == 8}? NUM
;
NUM
: '0'..'9'+
;
SP
: ' ' {skip();}
;
将解析输入12345 12345678
,如下所示:
但您也可以根据匹配文本的某些属性更改词法分析器中的标记类型,如下所示:
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 : ;
将导致相同的输入被解析如下:
答案 1 :(得分:1)
您需要指定5次,例如:
ZIPCODE: '0'..'9' '0'..'9' '0'..'9' '0'..'9' '0'..'9';
或者,您可以使用 验证语义谓词 :
DIGIT: '0'..'9';
zipcode
@init { int N = 0; }
: (DIGIT { N++; } )+ { N <= 5 }?
;