JTB 
JAVA TREEBUILDER
SPECIAL EDITION FOR GJ 
EXAMPLES
Special Edition 

JTB GJ Home 

Download 

Documentation 

Examples 

  • Basic Example
  • Comparison
  • Advanced Example

  •  



    Standard JTB Home 
     


    Links: 
  • JavaCC
  • Design Patterns
  • Javasoft
  • GJ
  •  
    Jump to Java!

    Basic Example

    This section contains a very simple example of how to use GJVisitor and GJDepthFirst.  It uses Java1.1.jj (Java grammar that includes the Java 1.1 language extensions provided by JavaCC) as the grammar file.  The function of this example is to count how many tokens, including <EOF>, are in the input Java file. 

    First run JTB GJ1.1.1 on Java1.1.jj, then JavaCC on jtb.out.jj

    % jtbgj Java1.1.jj 
    % javacc jtb.out.jj
    Download Main.java to the directory where you run JTB and JavaCC, and download MyInt.java and Counter.java to the visitor directory generated by JTB.  Finally, compile Main.java with GJ compiler
    % gjc Main.java
    Now you can run the example on any Java source file by: 
    % java Main < inputfile.java
    It will tell you how many tokens are there in inputfile.java.  The following paragraphs will go through the source files of this example and show you how generic types are specified in visitors.  Let's start from MyInt.java
    package visitor; 

    public class MyInt { 
       public MyInt(int n) { count=n; } 
       public int count; 
    }

    An object of MyInt class will be passed on as an argument during the syntax tree traversal.  The reason I put MyInt in the visitor package is that both Main class and Counter class need it.  The next is Counter.java
    package visitor; 
    import syntaxtree.*; 
    import java.util.*; 

    public class Counter extends GJDepthFirst<MyInt,MyInt> { 
       public MyInt visit(NodeToken n, MyInt argu) { 
          argu.count++; 
          return argu; 
       } 
    }

    Counter is a visitor that extends GJDepthFirst.  It specifies the type parameters by GJDepthFirst<MyInt,MyInt>.  The first MyInt stands for the return type, and the second MyInt is the type of the argument.  In this example, the return value is useless.  What Counter does is to increase count field of the object of MyInt.  An object of MyInt will be passed on as the argument, so at the end of the syntax tree traversal, it will record the total number of the tokens.  The last file is Main.java
    import syntaxtree.*; 
    import visitor.*; 

    public class Main { 
       public static void main(String [] args) { 
          try { 
             Node root = new 
                JavaParser(System.in).CompilationUnit(); 
             System.out.println("Program parsed successfully"); 
             MyInt re=new MyInt(0); 
             root.accept(new Counter(),re); 
             System.out.println("Total tokens: " + re.count + "\n"); 
          } 
          catch (ParseException e) { 
             System.out.println(e.toString()); 
          } 
       } 
    }

    There's nothing special about Main.java.  It simply calls the parser (the syntax tree is constructed automatically during parsing) and starts the visitor.  This example doesn't have to be implemented this way.  The whole purpose is to demonstrate the usage of GJDepthFirst and GJVisitor
     

    Comparison

    Let's rewrite the above Counter.java with ObjectDepthFirst class generated by JTB 1.2 and standard Java programming language: 
    package visitor; 
    import syntaxtree.*; 
    import java.util.*; 

    public class Counter extends ObjectDepthFirst { 
       public Object visit(NodeToken n, Object argu) { 
          (MyInt)argu.count++; 
          return argu; 
       } 
    }

    The only difference is that with GJ, there is no type casting at all.  You will find GJ extremely uesful when your visitor is complex and you try to pass parameters and get return values.  All the mismatch types can be found at compile-time in GJ. 
     

    Advanced Example

    Here is an advanced example of how to use GJVisitor and GJDepthFirst
    Expression_GJ.jar
    This example transforms an infix expression to a prefix expression.  It uses the Calc1.jj grammar provided with the JavaCC distribution, version 1.0.  Some changes were made to the original grammar file to fit in with JTB GJ1.1.1.  For more information, please read the README file included in the above example package.  As a comparison, you can go to the standard JTB Examples page, and see how to achieve the same goal using standard Java. 

    You can still find some type castings in the above example.  It is because the grammar is not well organized.  By properly revising the grammar, your visitor can be totally type-casting free, though the revised grammar may be a little bit longer.  Below is a revised version of the same example where all the classes are type-casting free: 

    Expression_GJ_Pro.jar

    Maintained by Wanjun Wang, wanjun@purdue.edu.
    Created September 4, 1997. 
    Last modified Sep. 25, 1999.