Sunday, January 30, 2011

ANTLR - Java source code rewrite

See ANTLR4 for other solution using Listener
https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Parse+Tree+Listeners
http://media.pragprog.com/titles/tpantlr2/listener.pdf

Using examples from chapter 9 in http://www.pragprog.com/titles/tpantlr/the-definitive-antlr-reference

Java tree grammar used for rewrite example
http://www.antlr.org/grammar/1207932239307/Java1_5Grammars
Dieter Habelitz - A Java 1.5 grammar that builds trees and a tree grammar. Not derived from Java grammar Terence wrote.
original link broken - http://www.antlr3.org/grammar/1207932239307/Java1_5Grammars

Try this on  github
https://github.com/grammarware/slps/tree/master/topics/grammars/java-5/habelitz 

Add template rewrite call into tree grammar JavaTreeParser.g
  |   ^(METHOD_CALL  primaryExpression {$primaryExpression::isMethodCall=true;} genericTypeArgumentList? arguments)
      -> methodCall(methodCallText={$text})


Create template file JavaTreeTemplate.stg
group Java;

methodCall(methodCallText) ::= <<
$methodCallText$;
log("Called $methodCallText$")
>>


import java.io.FileReader;

import generated.JavaLexer;
import generated.JavaParser;
import generated.JavaTreeParser;

import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.TokenRewriteStream;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
import org.antlr.stringtemplate.language.DefaultTemplateLexer;


public class JavaTreeWalker {
    
    public static void main(String[] args) throws Exception {
        
        String templateFileName = "src/JavaTreeTemplate.stg";
        StringTemplateGroup templates = new StringTemplateGroup(new FileReader(templateFileName),
                            DefaultTemplateLexer.class);
        
        ANTLRFileStream input = new ANTLRFileStream(args[0]);
        
        JavaLexer lexer = new JavaLexer(input);
        
        TokenRewriteStream tokens = new TokenRewriteStream(lexer);
        
        JavaParser parser = new JavaParser(tokens);
        
        JavaParser.javaSource_return r = parser.javaSource();
        
        CommonTree t = (CommonTree)r.getTree();
        
        System.out.println(t.toStringTree());
        
        CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
        
        nodes.setTokenStream(tokens);
        
        JavaTreeParser walker = new JavaTreeParser(nodes);
        
        walker.setTemplateLib(templates);
        
        System.out.println("\nWalk tree:\n");
        printTree(t,0);
        
        walker.javaSource();
        
        System.out.println(tokens.toString());
        
    }
    
    public static void printTree(CommonTree t, int indent) {
        if ( t != null ) {
            StringBuffer sb = new StringBuffer(indent);
            for ( int i = 0; i < indent; i++ )
                sb = sb.append("   ");
            for ( int i = 0; i < t.getChildCount(); i++ ) {
                System.out.println(sb.toString() + t.getChild(i).toString());
                printTree((CommonTree)t.getChild(i), indent+1);
            }
        }
    }


}


Original HelloWorld Java program
public class HelloWorld {

    static int x;

    /**
     * This is test class for ANTLR Java source code transformation
     * @param args
     */
    public static void main(String args[]) {

        int x;
        int y;
        
        x = 1; 
        print(x);

        System.out.println("Hello,world!");

    }
    
    private static  void print(int x){
        System.out.println(x);
    }

}


Program after rewrite by ANTLR
public class HelloWorld {

    static int x;

    /**
     * This is test class for ANTLR Java source code transformation
     * @param args
     */
    public static void main(String args[]) {

        int x;
        int y;
        
        x = 1; 
        print(x);
log("Called print(x)");

        System.out.println("Hello,world!");
log("Called System.out.println("Hello,world!")");

    }
    
    private static  void print(int x){
        System.out.println(x);
log("Called System.out.println(x)");
    }

}


ANTLR AST
(JAVA_SOURCE ANNOTATION_LIST (class (MODIFIER_LIST public) HelloWorld (CLASS_TOP_LEVEL_SCOPE (VAR_DECLARATION (MODIFIER_LIST static) (TYPE int) (VAR_DECLARATOR_LIST (VAR_DECLARATOR x))) (VOID_METHOD_DECL (MODIFIER_LIST public static) main (FORMAL_PARAM_LIST (FORMAL_PARAM_STD_DECL LOCAL_MODIFIER_LIST (TYPE (QUALIFIED_TYPE_IDENT String)) (args (ARRAY_DECLARATOR_LIST ARRAY_DECLARATOR)))) (BLOCK_SCOPE (VAR_DECLARATION LOCAL_MODIFIER_LIST (TYPE int) (VAR_DECLARATOR_LIST (VAR_DECLARATOR x))) (VAR_DECLARATION LOCAL_MODIFIER_LIST (TYPE int) (VAR_DECLARATOR_LIST (VAR_DECLARATOR y))) (EXPR (= x 1)) (EXPR (METHOD_CALL print (ARGUMENT_LIST (EXPR x)))) (EXPR (METHOD_CALL (. (. System out) println) (ARGUMENT_LIST (EXPR "Hello,world!")))))) (VOID_METHOD_DECL (MODIFIER_LIST private static) print (FORMAL_PARAM_LIST (FORMAL_PARAM_STD_DECL LOCAL_MODIFIER_LIST (TYPE int) x)) (BLOCK_SCOPE (EXPR (METHOD_CALL (. (. System out) println) (ARGUMENT_LIST (EXPR x)))))))))

Walk tree:

ANNOTATION_LIST
class
   MODIFIER_LIST
      public
   HelloWorld
   CLASS_TOP_LEVEL_SCOPE
      VAR_DECLARATION
         MODIFIER_LIST
            static
         TYPE
            int
         VAR_DECLARATOR_LIST
            VAR_DECLARATOR
               x
      VOID_METHOD_DECL
         MODIFIER_LIST
            public
            static
         main
         FORMAL_PARAM_LIST
            FORMAL_PARAM_STD_DECL
               LOCAL_MODIFIER_LIST
               TYPE
                  QUALIFIED_TYPE_IDENT
                     String
               args
                  ARRAY_DECLARATOR_LIST
                     ARRAY_DECLARATOR
         BLOCK_SCOPE
            VAR_DECLARATION
               LOCAL_MODIFIER_LIST
               TYPE
                  int
               VAR_DECLARATOR_LIST
                  VAR_DECLARATOR
                     x
            VAR_DECLARATION
               LOCAL_MODIFIER_LIST
               TYPE
                  int
               VAR_DECLARATOR_LIST
                  VAR_DECLARATOR
                     y
            EXPR
               =
                  x
                  1
            EXPR
               METHOD_CALL
                  print
                  ARGUMENT_LIST
                     EXPR
                        x
            EXPR
               METHOD_CALL
                  .
                     .
                        System
                        out
                     println
                  ARGUMENT_LIST
                     EXPR
                        "Hello,world!"
      VOID_METHOD_DECL
         MODIFIER_LIST
            private
            static
         print
         FORMAL_PARAM_LIST
            FORMAL_PARAM_STD_DECL
               LOCAL_MODIFIER_LIST
               TYPE
                  int
               x
         BLOCK_SCOPE
            EXPR
               METHOD_CALL
                  .
                     .
                        System
                        out
                     println
                  ARGUMENT_LIST
                     EXPR
                        x

No comments:

Post a Comment