我正在尝试解决一个非常简单的语法问题(我刚开始学习使用ANTLR
来开发语法;我有点新,所以只跟我一起)这是定义一个带符号的偶数使用ANTLR
。
A '+' or '-'
是可选的,数字可以是1位或更多位,但最后一位必须是偶数(例如,+4394
将是有效的有符号偶数)。
我到目前为止最好的语法如下:
grammar SignedEvenNumber;
DIGIT : '0'..'9';
EVEN_DIGIT : '0' | '2' | '4' | '6' | '8';
signedEvenNumber : ('+' | '-' | ) NUMBER+ EVEN_NUMBER;
我的问题是以强制ANTLR
检查偶数位作为最后一位数的方式定义数字;即它始终将最后一个数字视为DIGIT
,无论它是偶数还是奇数(因为最后一个数字可以是最后一个数字)。可能有一个非常简单的解决方案,我只是没有得到,但任何帮助将不胜感激。
答案 0 :(得分:0)
我对ANTLR 4有更多经验,但我认为首先定义的令牌优先于语法后定义的其他令牌,因此首先定义EVEN_DIGIT:
grammar SignedEvenNumber;
EVEN_DIGIT : '0' | '2' | '4' | '6' | '8';
DIGIT : '0'..'9';
signedEvenNumber : ('+' | '-')? DIGIT+ EVEN_DIGIT;
.tokens文件中的标记是:
DIGIT=4
T__1=1
EVEN_DIGIT=3
T__0=2
'-'=2
'+'=1
对于输入测试:
代币是:1234
[@0,0:0='+',<1>,1:0]
[@1,1:1='1',<4>,1:1]
[@2,2:2='2',<3>,1:2]
[@3,3:3='3',<4>,1:3]
[@4,4:4='4',<3>,1:4]
如果优先级不起作用,您可以重新定义您的令牌并更改此规则:
grammar SignedEvenNumber;
EVEN_DIGIT : '0' | '2' | '4' | '6' | '8';
DIGIT : '1' | '3' | '5' | '7' | '9';
signedEvenNumber : ('+' | '-')? (DIGIT | EVEN_DIGIT)* EVEN_DIGIT;
答案 1 :(得分:0)
如果你将EVEN和NOT_EVEN定义为你可以拥有的不相交的令牌
SignedEvenNumber : ('+' | '-')? (NOT_EVEN* EVEN)+
由于偶数形成常规语言,您可以将其视为DFA。
答案 2 :(得分:0)
是否有必要通过DFA区分?使用规则操作怎么样?
tokens {
EVEN_NUMBER;
ODD_NUMBER;
};
fragment
NUMBER_FRAG: DIGIT+;
NUMBER: t = NUMBER_FRAG
{
if ($t->getText()->lastDigitIsEven())
{ $type = EVEN_NUMBER; }
else
{ $type = ODD_NUMBER; }
};