L'idée est de changer le type du jeton sous une certaine condition. Ici voir un ID pour la première fois dans une ligne définit un commutateur à true. La prochaine fois qu'un ID est identifié, le lexeur exécutera le code if
et définira le type sur ID_VALUE
. Je voulais remettre le commutateur en entrant dans la règle function
, mais il ne fonctionne pas:
function
@init {QuestionLexer.id_seen = false; System.out.println("id_seen has been reset" + QuestionLexer.id_seen);}
: FUNCTION_IN OPAR ID COMMA OPAR array CPAR CPAR
ID=name1 seen ? false
ID=Silver seen ? true
...
ID=Platinum seen ? true
[@0,0:1='in',<'in'>,1:0]
[@1,2:2='(',<'('>,1:2]
[@2,3:7='name1',<ID>,1:3]
[@3,8:8=',',<','>,1:8]
[@4,9:9='(',<'('>,1:9]
[@5,10:15='Silver',<10>,1:10]
...
[@12,27:31='name2',<10>,2:3]
...
[@20,52:51='<EOF>',<EOF>,3:0]
Question last update 1336
id_seen has been reset false
id_seen has been reset false
line 2:3 mismatched input 'name2' expecting ID
.
C'est pourquoi je l'ai réinitialisé dans la règle FUNCTION_IN
.
Grammaire Question.g4:
grammar Question;
@lexer::members {
static boolean id_seen = false;
}
tokens { ID_VALUE }
question
@init {System.out.println("Question last update 1352");}
: function+ EOF
;
function
: FUNCTION_IN OPAR ID COMMA OPAR array CPAR CPAR
;
array
: value (COMMA value)*
;
value
: ID_VALUE
| INT
| FLOAT
;
FUNCTION_IN: 'in' {id_seen = false;} ;
ID : [a-zA-Z_] [a-zA-Z_0-9]*
{System.out.println("ID=" + getText() + " seen ? " + id_seen);
if (id_seen) setType(QuestionParser.ID_VALUE); id_seen = true; } ;
OPAR : '(';
CPAR : ')';
COMMA : ',';
INT
: [0-9]+
;
FLOAT
: [0-9]+ '.' [0-9]*
| '.' [0-9]+
;
SPACE
: [ \t\r\n] -> skip
;
OTHER
: .
;
fichier t.text:
in(name1,(Silver,Gold))
in(name2,(Copper,Platinum))
Exécution avec ANTLR 4.6:
$ grun Question question -tokens -diagnostics t.text
ID=name1 seen ? false
ID=Silver seen ? true
ID=Gold seen ? true
ID=name2 seen ? false
ID=Copper seen ? true
ID=Platinum seen ? true
[@0,0:1='in',<'in'>,1:0]
[@1,2:2='(',<'('>,1:2]
[@2,3:7='name1',<ID>,1:3]
[@3,8:8=',',<','>,1:8]
[@4,9:9='(',<'('>,1:9]
[@5,10:15='Silver',<10>,1:10]
[@6,16:16=',',<','>,1:16]
[@7,17:20='Gold',<10>,1:17]
[@8,21:21=')',<')'>,1:21]
[@9,22:22=')',<')'>,1:22]
[@10,24:25='in',<'in'>,2:0]
[@11,26:26='(',<'('>,2:2]
[@12,27:31='name2',<ID>,2:3]
[@13,32:32=',',<','>,2:8]
[@14,33:33='(',<'('>,2:9]
[@15,34:39='Copper',<10>,2:10]
[@16,40:40=',',<','>,2:16]
[@17,41:48='Platinum',<10>,2:17]
[@18,49:49=')',<')'>,2:25]
[@19,50:50=')',<')'>,2:26]
[@20,52:51='<EOF>',<EOF>,3:0]
Question last update 1352
type < 10> est ID_VALUE
comme on le voit dans le fichier .tokens
$ cat Question.tokens
FUNCTION_IN=1
...
OTHER=9
ID_VALUE=10
'in'=1
Ce n'est pas l'analyseur qui est confus, croyez-moi. Il sait toujours quoi analyser :-) Alors, quel est le problème réel? Qu'attendez-vous? –
Votre entrée 'Silver, Gold' est-elle correcte? N'est-ce pas «Silver», «Gold»? Sans apostrophes, il n'y a aucune chance qu'ils soient assortis par la règle 'STRING'. – BernardK
@BernardK: Oui. La grammaire fonctionne avec des chaînes avec des guillemets 'Argent' et 'Or'. Si j'ai supprimé les guillemets, l'analyseur pensera que c'est un identifiant. –