2010-12-04 6 views
2

Hey ive a commencé à utiliser Antlr avec Java et je voulais savoir comment je pouvais stocker certaines valeurs directement dans un tableau 2d et retourner ce tableau? Je ne peux pas trouver de tutoriels à ce sujet, toute l'aide est appliquée.Antlr Array Help

Répondre

6

Disons que vous voulez analyser un fichier texte contenant des nombres séparés par des espaces. Vous souhaitez analyser cela dans un tableau 2d de int où chaque ligne est une "ligne" dans votre tableau.

La grammaire ANTLR pour un « langage » pourrait ressembler à:

grammar Number; 

parse 
    : line* EOF 
    ; 

line 
    : Number+ (LineBreak | EOF) 
    ; 

Number 
    : ('0'..'9')+ 
    ; 

Space 
    : (' ' | '\t') {skip();} 
    ; 

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

Maintenant, vous aimeriez avoir la règle parse retourner un List de List<Integer> objets. Est-ce que par l'ajout d'un returns [List<List<Integer>> numbers] après votre parse règle qui peut être initialisé dans un @init{ ... } bloc:

parse returns [List<List<Integer>> numbers] 
@init { 
    $numbers = new ArrayList<List<Integer>>(); 
} 
    : line* EOF 
    ; 

Votre line règle semble un peu la même chose, seulement il renvoie une 1 liste dimensions des nombres:

line returns [List<Integer> row] 
@init { 
    $row = new ArrayList<Integer>(); 
} 
    : Number+ (LineBreak | EOF) 
    ; 

L'étape suivante consiste à remplir les List avec les valeurs réelles qui sont en cours d'analyse.Cela peut se faire intégrer le code {$row.add(Integer.parseInt($Number.text));} dans la boucle Number+ dans la règle line:

line returns [List<Integer> row] 
@init { 
    $row = new ArrayList<Integer>(); 
} 
    : (Number {$row.add(Integer.parseInt($Number.text));})+ (LineBreak | EOF) 
    ; 

Et enfin, vous voulez ajouter les List s renvoyés par votre règle line être effectivement ajouté à votre 2D numbers liste de votre règle parse:

parse returns [List<List<Integer>> numbers] 
@init { 
    $numbers = new ArrayList<List<Integer>>(); 
} 
    : (line {$numbers.add($line.row);})* EOF 
    ; 

Voici la grammaire finale:

grammar Number; 

parse returns [List<List<Integer>> numbers] 
@init { 
    $numbers = new ArrayList<List<Integer>>(); 
} 
    : (line {$numbers.add($line.row);})* EOF 
    ; 

line returns [List<Integer> row] 
@init { 
    $row = new ArrayList<Integer>(); 
} 
    : (Number {$row.add(Integer.parseInt($Number.text));})+ (LineBreak | EOF) 
    ; 

Number 
    : ('0'..'9')+ 
    ; 

Space 
    : (' ' | '\t') {skip();} 
    ; 

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

qui peut être testé avec la classe suivante:

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

public class Main { 
    public static void main(String[] args) throws Exception { 
     String source = 
       "1 2  \n" + 
       "3 4 5 6 7 \n" + 
       "  8 \n" + 
       "9 10 11  "; 
     ANTLRStringStream in = new ANTLRStringStream(source); 
     NumberLexer lexer = new NumberLexer(in); 
     CommonTokenStream tokens = new CommonTokenStream(lexer); 
     NumberParser parser = new NumberParser(tokens); 
     List<List<Integer>> numbers = parser.parse(); 
     System.out.println(numbers); 
    } 
} 

Générez un lexer et analyseur de la grammaire:

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

compiler tous les fichiers source .java:

javac -cp antlr-3.2.jar *.java 

et exécuter la classe principale:

// On *nix 
java -cp .:antlr-3.2.jar Main 

// or Windows 
java -cp .;antlr-3.2.jar Main 

qui produit la sortie suivante:

[[1, 2], [3, 4, 5, 6, 7], [8], [9, 10, 11]] 

HTH

+0

Merci beaucoup ce qui est excellent, vous êtes – Jay

+0

@Jay bienvenue. –

0

Voici quelques extraits d'une grammaire que j'ai faite qui analyse les noms des personnes et retourne un objet Name. Devrait être suffisant pour vous montrer comment cela fonctionne. D'autres objets tels que les tableaux sont faits de la même manière.

Dans la grammaire:

grammar PersonNames; 

fullname returns [Name name] 
@init { 
    name = new Name(); 
} 
    : (directory_style[name] | standard[name] | title_without_fname[name] |  family_style[name] | proper_initials[name]) EOF; 

standard[Name name] 
: (title[name] ' ')* fname[name] ' ' (mname[name] ' ')* (nickname[name] ' ')? lname[name] (sep honorifics[name])*; 

fname[Name name] : (f=NAME | f=INITIAL) { name.set(Name.Part.FIRST, toNameCase($f.text)); }; 

dans votre code Java régulier

public static Name parseName(String str) throws RecognitionException { 
    System.err.println("parsing `" + str + "`"); 
    CharStream stream = new ANTLRStringStream(str); 
    PersonNamesLexer lexer = new PersonNamesLexer(stream); 
    CommonTokenStream tokens = new CommonTokenStream(lexer); 
    PersonNamesParser parser = new PersonNamesParser(tokens); 

    return parser.fullname(); 
}