OLD DOCUMENTATION
JTB GJ1.0 is the special version of JTB for GJ.  It generates syntax trees that work with GJ.  This document describes the difference between this special edition and the standard JTB.  You are required to know JTB 1.2, before you start working on JTB GJ1.0.  If you are not yet familiar with JTB, please see the Documentation page for the specifications of JTB 1.2. 
 

What's GJ

GJ is a design that extends the Java programming language with the generic types and methods.  For example, GJ can support the following codes: 
interface Collection<A> {
   public void add(A x);
   public Iterator<A> iterator();
}
The main benefit of GJ over the current Java programming language lies in the added expressiveness and safety that stems from making type parameters explicit and making type casts implicit.  GJ is designed to be fully backwards compatible with the current Java language, and in particular, one can retrofit existing library classes with generic interfaces without changing their codes.  For details about GJ and downloading GJ compiler, please go to GJ web page
 

JTB GJ1.0

JTB GJ1.0 was upgraded from JTB 1.2.  It preserves the structure of JTB 1.2 and still generates Visitor.java interface and DepthFirstVisitor.java class that support visitors without return value.  Printer and Scheme Tree Builder toolkits still subclass DepthFirstVisitor.  However, the following have been changed in order to utilize generic types and methods provided by GJ: 
  • Node classes in syntaxtree directory

  •  
      public interface Node extends java.io.Serializable {
         public void accept(visitor.Visitor v);
         public <R,A> R accept(visitor.GJVisitor<R,A> v, A argu);
      }


    Every syntax tree node generated by JTB GJ1.0 implements the above interface.  The second accept() method uses generic types provided by GJ.  You don't need to change the syntax tree nodes created by JTB. 
     

  • GJVisitor.java interface and GJDepthFirst.java class

  • JTB GJ1.0 doesn't generate ObjectVisitor interface and ObjectDepthFirst class any longer.  Instead,  it will generate GJVisitor interface and GJDepthFirst class in the visitor directory. GJVisitor looks like: 
     
      public interface GJVisitor<R,A> {
        public R visit(XXXX n, A argu);
        public R visit(YYYY n, A argu);
        ...
      }


    XXXX and YYYY stand for different names of the productions in your grammar.  R and A are type parameters.  GJDepthFirst is the default implementation of GJVisitor.  It simply passes the argument on while visiting each node of the syntax tree.  Each visit() method in GJDepthFirst will return null as default.  The structure of GJDepthFirst is: 
     

      public class GJDepthFirst<R,A> implements GJVisitor<R,A> {
        public R visit(XXXX n, A argu) {
          R _ret=null;
          n.f0.accept(this, argu);
          ...
          return _ret;
        }
        ...
      }


    You may notice that GJDepthFirst still keeps type parameters.  You can specify those type parameters by making your own visitor extand GJDepthFirst.  For further information, please see the example on this page.

Note: All visitor classes must implement the Visitor or GJVisitor interface either directly or by subclassing a class which does so (such as DepthFirstVisitor or GJDepthFirst). 
 

Download

Requirements for JTB GJ1.0:  Instructions to install JTB GJ1.0: 
  • Download jtbgj10.classNOTE: On Windows machines Netscape may save the file as "jtbgj10.exe".  Simply rename the file to jtbgj10.class. 
  • Execute this class using a Java 1.1 (or higher) virtual machine.  For example, on Unix, the command would be:

  •  
      % java jtbgj10
  • Follow the on-screen instructions to complete installation. 

Using JTB GJ1.0

Run JTB GJ1.0 on your .jj grammar file with the command:
% jtbgj yourfile.jj
Generate your parser by running JavaCC on jtb.out.jj with the command:
% javacc jtb.out.jj
Use classes, generated by JTB GJ1.0 and JavaCC, to design your own program according to GJ specifications, then compile it on GJ compiler:
% gjc filename.java
GJ compiler will generate .class files executable on Java Virtual Machine, so you can run your program by:
% java filename

 
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.0 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 JTBGJ 1.0.  For more information, please read the README file included in the above example package.  As a comparison, you can go to the Examples page, and see how to achieve the same goal using standard Java. 

Still have questions?  Suggestions on improving this document?  Feel free to mail Wanjun Wang or Jens Palsberg

Back

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