Can someone provide a detailed example as to how I can do this using antlr4? Instructions right from installing antlr4 and its dependencies would be highly appreciated.
Here it is.
First, you're gonna buy the ANTLR4 book ;-)
Second, you'll download antlr4 jar and the java grammar (http://pragprog.com/book/tpantlr2/the-definitive-antlr-4-reference)
Then, you can change the grammar a little bit, adding these to the header
(...)
grammar Java;
options
{
language = Java;
}
// starting point for parsing a java file
compilationUnit
(...)
I'll change a little thing in the grammar just to illustrate something.
/*
methodDeclaration
: (type|'void') Identifier formalParameters ('[' ']')*
('throws' qualifiedNameList)?
( methodBody
| ';'
)
;
*/
methodDeclaration
: (type|'void') myMethodName formalParameters ('[' ']')*
('throws' qualifiedNameList)?
( methodBody
| ';'
)
;
myMethodName
: Identifier
;
You see, the original grammar does not let you identify the method identifier from any other identifier, so I've commented the original block and added a new one just to show you how to get what you want.
You'll have to do the same for other elements you want to retrieve, like the comments, that are currently being just skipped. That's for you :-)
Now, create a class like this to generate all the stubs
package mypackage;
public class Gen {
public static void main(String[] args) {
String[] arg0 = { "-visitor", "/home/leoks/EclipseIndigo/workspace2/SO/src/mypackage/Java.g4", "-package", "mypackage" };
org.antlr.v4.Tool.main(arg0);
}
}
Run Gen, and you'll get some java code created for you in mypackage.
Now create a Visitor. Actually, the visitor will parse itself in this example
package mypackage;
import java.io.FileInputStream;
import java.io.IOException;
import mypackage.JavaParser.MyMethodNameContext;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
/**
* @author Leonardo Kenji Feb 4, 2014
*/
public class MyVisitor extends JavaBaseVisitor<Void> {
/**
* Main Method
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
ANTLRInputStream input = new ANTLRInputStream(new FileInputStream("/home/leoks/EclipseIndigo/workspace2/SO/src/mypackage/MyVisitor.java")); // we'll
// parse
// this
// file
JavaLexer lexer = new JavaLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
JavaParser parser = new JavaParser(tokens);
ParseTree tree = parser.compilationUnit(); // see the grammar ->
// starting point for
// parsing a java file
MyVisitor visitor = new MyVisitor(); // extends JavaBaseVisitor<Void>
// and overrides the methods
// you're interested
visitor.visit(tree);
}
/**
* some attribute comment
*/
private String someAttribute;
@Override
public Void visitMyMethodName(MyMethodNameContext ctx) {
System.out.println("Method name:" + ctx.getText());
return super.visitMyMethodName(ctx);
}
}
and that's it.
You'll get something like
Method name:main
Method name:visitMyMethodName
ps. one more thing. While I was writing this code in eclipse, I've got a strange exception. This is caused by Java 7 and can be fixed just adding these parameters to your compiler (thanks to this link http://java.dzone.com/articles/javalangverifyerror-expecting)