2017-07-26 3 views
1

Juste à la recherche d'un moyen simple d'obtenir ANTLR4 pour générer un analyseur qui effectuer les opérations suivantes (ne pas tenir quoi que ce soit après le ;):Exigent nouvelle ligne ou EOF après un match de déclaration

int #i ; defines an int 
int #j ; see how I have to go to another line for another statement? 

Mon analyseur est comme suivant:

compilationUnit: 
    (statement END?)* 
    statement END? 
    EOF 
; 

statement: 
    intdef | 
    WS 
; 

// 10 - 1F block. 

intdef: 
    'intdef' Identifier 
; 

// Lexer. 

Identifier: '#' Letter LetterOrDigit*; 
fragment Letter: [a-zA-Z_]; 
fragment LetterOrDigit: [a-zA-Z0-9$_]; 

// Whitespace, fragments and terminals. 

WS: [ \t\r\n\u000C]+ -> skip; 
//COMMENT: '/*' .*? '*/' -> channel(HIDDEN); 
END: (';' ~[\r\n]*) | '\n'; 

essentiellement, chaque fois que j'ai un statement, j'ai besoin pour EXIGER un saut de ligne avant qu'un autre est entré. Je me fiche de savoir s'il y a 3 nouvelles lignes et ensuite sur le second un groupe d'onglets persiste, tant qu'il y a une nouvelle ligne.

La question est, le ANTLR4 Parse Arbre semble me donner des erreurs pour les entrées telles que:

. 

(Pretend le point isnt il, son littéralement pas d'entrée)

int #i int #j 

Woops , nous en avons deux sur la même ligne!

Des idées sur comment je peux y parvenir? J'apprécie l'aide.

Répondre

1

J'ai légèrement simplifié votre grammaire, mais je l'ai faite en demandant une séquence de fin de ligne après chaque instruction pour analyser correctement.

grammar Testnl; 

program: (statement)* EOF ; 

statement: 'int' Identifier EOL; 

Identifier: '#' Letter LetterOrDigit*; 
fragment Letter: [a-zA-Z_]; 
fragment LetterOrDigit: [a-zA-Z0-9$_]; 

EOL: ';' .*? '\r\n' 
| ';' .*? '\n' 
; 

WS: [ \t\r\n\u000C]+ -> skip; 

Il parse

int #i ; 
int #j; 


[@0,0:2='int',<'int'>,1:0] 
[@1,4:5='#i',<Identifier>,1:4] 
[@2,7:9=';\r\n',<EOL>,1:7] 
[@3,10:12='int',<'int'>,2:0] 
[@4,14:15='#j',<Identifier>,2:4] 
[@5,16:18=';\r\n',<EOL>,2:6] 
[@6,19:18='<EOF>',<EOF>,3:0] 

Il ignore aussi des choses après la virgule comme seulement une partie du jeton EOL:

[@0,0:2='int',<'int'>,1:0] 
[@1,4:5='#i',<Identifier>,1:4] 
[@2,7:20='; ignore this\n',<EOL>,1:7] 
[@3,21:23='int',<'int'>,2:0] 
[@4,25:26='#j',<Identifier>,2:4] 
[@5,27:28=';\n',<EOL>,2:6] 
[@6,29:28='<EOF>',<EOF>,3:0] 

utilisant ou saut de ligne CarriageReturn-linefeed très bien. Est-ce ce que vous cherchez?

EDIT

par commentaire OP, a fait un petit changement pour permettre des jetons de EOL consécutifs, et également déplacer jeton EOL à statement pour réduire la répétition:

grammaire Testnl;

program: (statement EOL)* EOF ; 

statement: 'int' Identifier; 

Identifier: '#' Letter LetterOrDigit*; 
fragment Letter: [a-zA-Z_]; 
fragment LetterOrDigit: [a-zA-Z0-9$_]; 

EOL: ';' .*? ('\r\n')+ 
| ';' .*? ('\n')+ 
; 

WS: [ \t\r\n\u000C]+ -> skip; 
+0

Merci pour la réponse! C'est exactement ce que je cherche. – finnrayment

+0

En fait, question rapide, y at-il un moyen de me permettre d'avoir des sauts de ligne entre les déclarations et après la dernière déclaration? Pour le moment, ils DOIVENT être insérés les uns après les autres sans ligne de fuite. – finnrayment

+0

@finnrayment Bien sûr, fait, voir la grammaire éditée ci-dessus. À votre santé! – TomServo