Reputation: 715
I am using ANTLR4 and have written lexer and parser grammar for a new language that I am designing. I'd like to create a Java POJO by parsing that language.
Language
{dept dept-name="human resources"}
{emp name="john doe" age=23 address="123 Main St, Spring Field, CO 12345" /}
{/dept}
Java POJOs
public class Department {
private final class name;
private final List<Employee>
}
public class Employee {
private final String name;
private final int age;
private final Address address;
}
public class Address {
private final String streetAddress;
private final String city;
private final String state;
private final int zip;
private final int zipExt;
}
I've been able to define the grammar correctly. I was able to use the Antlr tool to generate the Visitor class. The Visitor class takes a generic type, T, and returns an instance of type T while visiting every node. I need to return an Address while visiting the Address section of the AST and an Employee while visiting the Employee section of the AST. So I am not sure what the type T should be for the Visitor implementation.
I am confused about how to go about construct the above Department POJO by implementing the Visitor given out by ANTLR.
PS: Please note that I cannot change the Department, Employee, Address classes. Also, please don't suggest using XML or JSON. I am just trying to learn how such a problem is solved in ANTLR.
Thanks!
Upvotes: 0
Views: 677
Reputation: 780
Assuming this is the head of your parser.g4 grammar
Your entire script is a file
, file
can be made by multiple elements.
Elements can either be a page
or a pageGroup
. And page
and pageGroup
have other components.
parser grammar MyCustomParser;
file: element* EOF;
element: page | pageGroup;
Then once you run Antlr command you will get many generated files, most of them are probably named like MyCustomParser$XXXContext.class
. These file represent Nodes in your parse tree. In our case we will have MyCustomParser.PageContext
, MyCustomParser.PageGroupContext
and so on.
One particular important node is the root node of your parse tree, MyCustomParser.FileContext
. Its children will be element contexts, and element contexts' children will be page contexts or page group contexts mentioned above.
Now with this root node, all you need to do is to recursively visit all the nodes in the parse tree, starting from the root. And when you visit the nodes, you can generate your POJO based on the values stored in those nodes.
To get the root node
//....
MyCustomParser parser = new MyCustomParser(tokens);
MyCustomParser.FileContext fileContext = parser.file();
Notice we called the method file()
. The method name is the same as your root rule name.
You don't have to use the generated tree visitor. It is only there to help your saves some boiler template code, because in most cases we travel this or that tree in the same way.
You mentioned about the generic type issue. Most of the time, your POJO may have a common parent class, or implement a common interface. Then you can just use the parent class or interface. But in your case, you cannot modify the POJO, so it may not be easy to make use of the generated tree.
Upvotes: 1