2017-09-26 9 views
0

J'ai fait la déclaration suivante je voudrais analyser:ANTLR4: jeton correspondant à même règle mais avec position différente dans la grammaire

in(name,(Silver,Gold)) 
  • dans: est une fonction.
  • nom: est un ID. (Silver, Gold): est un tableau de chaînes avec les éléments 'Silver' et 'Gold'.

L'analyseur syntaxique est toujours confondu lorsque les éléments d'ID et de groupe de chaînes ont la même règle. L'utilisation de guillemets ou de guillemets doubles pour les chaînes aidera, mais ce n'est pas le cas ici.

De plus, les prédicats n'ont pas beaucoup aidé.

La grammaire:

grammar Rql; 

statement 
: EOF 
| query EOF 
; 

query 
: function 
; 

function 
: FUNCTION_IN OPAR id COMMA OPAR array CPAR CPAR 
; 

array 
: VALUE (COMMA VALUE)* 
; 

FUNCTION_IN: 'in'; 

id 
: {in(}? ID 
; 

ID 
: [a-zA-Z_] [a-zA-Z_0-9]* 
; 

VALUE 
: STRING 
| INT 
| FLOAT 
; 

OPAR : '('; 
CPAR : ')'; 
COMMA : ','; 

INT 
: [0-9]+ 
; 

FLOAT 
: [0-9]+ '.' [0-9]* 
| '.' [0-9]+ 
; 

SPACE 
: [ \t\r\n] -> skip 
; 

STRING 
: [a-zA-Z_] [a-zA-Z_0-9]* 
; 

OTHER 
: . 
; 
+0

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? –

+0

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

+0

@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. –

Répondre

1

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 
+0

Merci pour votre effort! Cette grammaire fonctionne-t-elle sur la génération d'un visiteur/écouteur C#? –

+0

@AmrEllafy L'avantage de ANTLR4 par rapport aux versions précédentes/autres générateurs d'analyseurs est que le code a été déplacé dans les écouteurs/visiteurs. Néanmoins, il existe de nombreuses circonstances où le code est nécessaire dans la grammaire, par ex. prédicats sémantiques. L'inconvénient d'écrire du code dans la grammaire est qu'il doit être écrit dans la langue cible et doit être changé pour une autre cible. Voir des exemples dans [The Mega Tutorial] (https://tomassetti.me/antlr-mega-tutorial). – BernardK