I'm trying to solve a pretty simple grammar problem (I just started learning about using ANTLR
to develop grammars; I'm a bit new so just bear with me) which is to define a signed even number using ANTLR
.
A '+' or '-'
for the start token is optional, and the number can be 1 or more digits but the last digit must be even (for example, +4394
would be a valid signed even number).
The best grammar I have so far is as follows:
grammar SignedEvenNumber;
DIGIT : '0'..'9';
EVEN_DIGIT : '0' | '2' | '4' | '6' | '8';
signedEvenNumber : ('+' | '-' | ) NUMBER+ EVEN_NUMBER;
My issue is defining digits in a way that forces ANTLR
to check for an even digit as the last digit; ie it always sees the last digit as DIGIT
, regardless of it being even or odd (because any digit before the final can be either). There might be a really simple solution that I'm just not getting but any help would be appreciated.
I have more experience with ANTLR 4 but i think that the token defined first has priority over the others defined after in the grammer, so define first EVEN_DIGIT:
grammar SignedEvenNumber;
EVEN_DIGIT : '0' | '2' | '4' | '6' | '8';
DIGIT : '0'..'9';
signedEvenNumber : ('+' | '-')? DIGIT+ EVEN_DIGIT;
the tokens in the .tokens file are:
DIGIT=4
T__1=1
EVEN_DIGIT=3
T__0=2
'-'=2
'+'=1
For Input test:
+1234
the tokens are:
[@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]
if the priority doen't work you can redefine your tokens and change the rule like this:
grammar SignedEvenNumber;
EVEN_DIGIT : '0' | '2' | '4' | '6' | '8';
DIGIT : '1' | '3' | '5' | '7' | '9';
signedEvenNumber : ('+' | '-')? (DIGIT | EVEN_DIGIT)* EVEN_DIGIT;
if you define EVEN and NOT_EVEN as disjoint tokens you could have
SignedEvenNumber : ('+' | '-')? (NOT_EVEN* EVEN)+
since the even numbers form a regular language you can think of it as a DFA.
Is it necessary to be distinguished by DFA? What about using rule actions?
tokens {
EVEN_NUMBER;
ODD_NUMBER;
};
fragment
NUMBER_FRAG: DIGIT+;
NUMBER: t = NUMBER_FRAG
{
if ($t->getText()->lastDigitIsEven())
{ $type = EVEN_NUMBER; }
else
{ $type = ODD_NUMBER; }
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.