plmaheu
plmaheu

Reputation: 475

Parse data file

I want to parse a data file like this one (fictive example):

Name: bob
Age: 14
-----
Name: alice
-----

Let's suppose, for this example, that the format of the file is complex enough that I don't want to code it directly. I prefer using ANTLR to get a better parser.

Here is the question: how, with ANTLR, can I map this data to a structure, like a list ? I don't need the complete grammar but only an explanation of how I can map data like that to a data struture.

Upvotes: 2

Views: 1230

Answers (1)

Bart Kiers
Bart Kiers

Reputation: 170308

I couldn't find the answer that BA-S posted in a comment under your question, so I started writing a new answer. Without much explanation (read the other answer for more info), here is an example of how you could parse that simple input using ANTLR into a List<Person>.

The grammar describing your input:

grammar T;

parse
 : person* EOF
 ;

person
 : Name Word (Age Number)? Separator
 ;

Name
 : 'Name:'
 ;

Age
 : 'Age:'
 ;

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

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

Separator
 : '-----'
 ;

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

The same grammar but then including embedded code:

grammar T;

parse returns [List<Person> persons]
@init{$persons = new ArrayList<Person>();}
 : (person {$persons.add($person.p);})* EOF
 ;

person returns [Person p]
 : Name Word (Age Number)? Separator {$p = new Person($Word.text, $Number.text);}
 ;

Name
 : 'Name:'
 ;

Age
 : 'Age:'
 ;

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

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

Separator
 : '-----'
 ;

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

And a small test class (with the class Person):

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;

public class Main {
  public static void main(String[] args) throws Exception {
    TLexer lexer = new TLexer(new ANTLRFileStream("test.txt"));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    java.util.List<Person> persons = parser.parse();
    System.out.println(persons);
  }
}

class Person {

  final String name;
  final int age;

  public Person(String nm, String num) {
    name = nm;
    age = num == null ? -1 : Integer.valueOf(num);
  }

  @Override
  public String toString() {
    return String.format("{name=%s, age=%d}", name, age);
  }
}

where test.txt contains:

Name: bob
Age: 14
-----
Name: alice
-----

If you now run Main, the following will be printed:

[{name=bob, age=14}, {name=alice, age=-1}]

Upvotes: 4

Related Questions