2010-01-26 4 views
1

Donc, je pense que cela devrait être facile, mais j'ai du mal avec ça. J'essaye d'analyser un | fichier délimité, et toute ligne qui ne commence pas par un | est un commentaire. Je suppose que je ne comprends pas comment les commentaires fonctionnent. Il commet toujours des erreurs sur une ligne de commentaire. C'est un fichier hérité, donc il n'y a pas de changement. Voici ma grammaire.Utiliser antlr pour analyser a | fichier séparé

grammar Route; 

@header { 
package org.benheath.codegeneration; 
} 

@lexer::header { 
package org.benheath.codegeneration; 
} 

file: line+; 
line: route+ '\n'; 
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ; 
elt: (ELEMENT)*; 

COMMENT: ~'|' .* '\n' ; 
ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ; 
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace 

données:

! a comment 
Another comment 
| a | abc | b | def | ... 
+0

Bienvenue sur SO! Petite astuce: Vous devez mettre en retrait le code de 4 espaces ce qui amènera ce site à analyser et à afficher le code, ce qui peut être fait en surlignant le bloc et en appuyant sur le bouton "Code" en haut ou en appuyant sur Ctrl + K. – RCIX

+0

Merci, ceci est mon premier article sur Stack Overflow, et merci pour l'accueil chaleureux. – Ben

Répondre

0

C'est une bonne idée d'utiliser ANTLR pour un emploi comme ça, même si je pense qu'il est exagéré. Par exemple, il serait très facile à (en pseudo-code):

for each line in file: 
if line begins with '|': 
    fields = /|\s*([a-z]+)\s*/g 

Edit: Eh bien, vous ne pouvez pas exprimer la distinction entre les commentaires et les lignes lexicalement, parce qu'il n'y a rien lexical qui les distingue . Un indice pour vous mettre dans une direction réalisable.

line: comment | fields; 
comment: NONBAR+ (BAR|NONBAR+) '\n'; 
fields = (BAR NONBAR)+; 
+0

Eh bien, je suis d'accord, mais j'essayais de choisir une chose facile à faire avec antlr pour commencer. – Ben

0

Cela semble fonctionner, je jure que je l'ai essayé. Changer le commentaire en minuscule l'a fait passer à l'analyseur par rapport au lexeur, je ne comprends toujours pas.

grammar Route; 

@header { 
    package org.benheath.codegeneration; 
} 

@lexer::header { 
    package org.benheath.codegeneration; 
} 

file: (line|comment)+; 
line: route+ '\n'; 
route: ('|' elt) {System.out.println("element: [" + $elt.text + "]");} ; 
elt: (ELEMENT)*; 

comment : ~'|' .* '\n'; 

ELEMENT: ('a'..'z'|'A'..'Z'|'0'..'9'|'*'|'_'|'@'|'#') ; 
WS: (' '|'\t') {$channel=HIDDEN;} ; // ignore whitespace 
+0

Voir ma réponse. C'est une distinction entre * lexing * (qui transforme le texte en jetons) et * parsing * (qui comprend les jetons). –

1

Une grammaire pour cela ressemblerait à ceci:

parse 
    : line* EOF 
    ; 

line 
    : (comment | values) (NL | EOF) 
    ; 

comment 
    : ELEMENT+ 
    ; 

values 
    : PIPE (ELEMENT PIPE)+ 
    ; 

PIPE 
    : '|'  
    ; 

ELEMENT 
    : ('a'..'z')+ 
    ; 

NL 
    : '\r'? '\n' | '\r' 
    ; 

WS 
    : (' '|'\t') {$channel=HIDDEN;} 
    ; 

Et pour le tester, il vous suffit de saupoudrer un peu de code dans votre grammaire comme ceci:

grammar Route; 

@members { 
    List<List<String>> values = new ArrayList<List<String>>(); 
} 

parse 
    : line* EOF 
    ; 

line 
    : (comment | v=values {values.add($v.line);}) (NL | EOF) 
    ; 

comment 
    : ELEMENT+ 
    ; 

values returns [List<String> line] 
@init {line = new ArrayList<String>();} 
    : PIPE (e=ELEMENT {line.add($e.text);} PIPE)* 
    ; 

PIPE 
    : '|'  
    ; 

ELEMENT 
    : ('a'..'z')+ 
    ; 

NL 
    : '\r'? '\n' | '\r' 
    ; 

WS 
    : (' '|'\t') {$channel=HIDDEN;} 
    ; 

Générez maintenant un lexeur/analyseur en invoquant:

java -cp antlr-3.2.jar org.antlr.Tool Route.g 

créer une classe RouteTest.java:

import org.antlr.runtime.*; 
import java.util.List; 

public class RouteTest { 
    public static void main(String[] args) throws Exception { 
    String data = 
     "a comment\n"+ 
     "| xxxxx | y |  zzz |\n"+ 
     "another comment\n"+ 
     "| a | abc | b | def |"; 
    ANTLRStringStream in = new ANTLRStringStream(data); 
    RouteLexer lexer = new RouteLexer(in); 
    CommonTokenStream tokens = new CommonTokenStream(lexer); 
    RouteParser parser = new RouteParser(tokens); 
    parser.parse(); 
    for(List<String> line : parser.values) { 
     System.out.println(line); 
    } 
    } 
} 

compiler tous les fichiers source:

javac -cp antlr-3.2.jar *.java 

et exécutez la classe RouteTest:

// Windows 
java -cp .;antlr-3.2.jar RouteTest 

// *nix/MacOS 
java -cp .:antlr-3.2.jar RouteTest 

Si tout va bien, vous voyez ce imprimé sur votre console :

[xxxxx, y, zzz] 
[a, abc, b, def] 

Editer: notez que je l'ai simplifié un peu en n'autorisant que des lettres minuscules, vous pouvez toujours élargir l'ensemble du cours.

Questions connexes