2012-06-25 2 views
1

Je suis en train de créer un fichier de grammaire antlr très simple qui doit analyser le fichier suivant:Quel est le problème avec ma grammaire antlr simple?

Report (MyReport) 
Begin 
End 

Ou sans nom du rapport:

Report 
Begin 
End 

Et voici mon fichier de grammaire:

grammar RL; 

options { 
    language = Java; 
} 

report: 
    REPORT ('(' SPACE* STRING_LITERAL SPACE* ')')? 
    BEGIN 
    END 
    ; 

REPORT 
    : 'Report' 
    ;  

BEGIN 
    : 'Begin' 
    ; 

END : 'End'; 

NAME: LETTER (LETTER | DIGIT | '_')*; 

STRING_LITERAL : NAME SPACE*; 

fragment LETTER: LOWER | UPPER; 

fragment LOWER: 'a'..'z'; 

fragment UPPER: 'A'..'Z'; 

fragment DIGIT: '0'..'9'; 

fragment SPACE: ' ' | '\t'; 

WHITESPACE: SPACE+ { $channel = HIDDEN; }; 

rule: ; 

Cependant, lorsque je débogue dans ANTLRWorks, j'obtiens toujours l'erreur suivante:

root -> report -> MismatchedTokenException(0!=0) 

Qu'est-ce qui ne va pas dans mon fichier Grammar?

grâce, vert

Répondre

3

Quelques remarques:

  • Java est la langue par défaut, vous pouvez omettre language=Java;;
  • vous utilisez SPACE à l'intérieur d'une règle d'analyseur, alors que ce jeton SPACE est un fragment: ceci fait que le lexeur ne crée jamais ce jeton: retirez-le de votre règle d'analyse;
  • l'entrée "Report " ("Rapport" suivi d'un seul espace blanc) est en train de devenir un STRING_LITERAL, pas comme un REPORT! Le lexer d'ANTLR consomme des caractères avec avidité, seulement quand deux règles ou plus correspondent au même nombre de caractères, la règle définie en premier aura la priorité. Le lexeur produit et non produit des jetons que l'analyseur essaie de faire correspondre (l'analyse et la segmentation sont effectuées indépendamment!).

Effectuez les opérations suivantes au lieu:

grammar RL; 

report 
: REPORT ('(' NAME ')')? BEGIN END 
; 

REPORT : 'Report';  
BEGIN : 'Begin'; 
END : 'End'; 
NAME : LETTER (LETTER | DIGIT | '_')*; 

fragment LETTER : LOWER | UPPER; 
fragment LOWER : 'a'..'z'; 
fragment UPPER : 'A'..'Z'; 
fragment DIGIT : '0'..'9'; 

SPACE : (' ' | '\t' | '\r' | '\n')+ { $channel = HIDDEN; }; 

green wrote:

What if I want to allow "SPACE" inside Report NAME?

Je sauterais encore des espaces dans le lexer. Accepter des espaces entre des noms mais les ignorer dans d'autres contextes entraînera des règles maladroites. Au lieu de la comptabilisation des espaces entre le nom d'un rapport, je ferais quelque chose comme ceci:

report 
: REPORT ('(' report_name ')')? BEGIN END 
; 

report_name 
: NAME+ 
; 

entraînant l'arbre Parse suivant:

enter image description here

pour l'entrée:

Report (a name with spaces) 
Begin 
End

green wrote:

so is it possible to allow me use reserved words like 'Report' in the name?

Bien sûr, ajoutez-les explicitement dans le report_name Règle:

report_name 
: (NAME | REPORT | BEGIN | END)+ 
; 
+0

Merci beaucoup. Que faire si je souhaite autoriser "ESPACE" dans le champ "NOM du rapport"? –

+0

@vert, je vous en prie. Voir ma réponse éditée. –

+0

J'ai suivi l'approche "nom_rapport" et j'ai obtenu cette erreur: "T: \ tmp \ RL \ RL.g: 11: 1: Les définitions de jeton suivantes ne peuvent jamais être mises en correspondance car les jetons précédents correspondent à la même entrée: REPORT_NAME".Le code source est à https://gist.github.com/2991022 –

Questions connexes