COBOL-85 Abstract Syntax Tree

Having a parser is a nice thing, but it's not much useful by itself. You will need an abstract syntax tree, a tree of java classes representing the structure of the program. The Java Tree Builder will help us greatly in this task.

  1. Download and install the Java Tree Builder.
  2. Compile the COBOL grammar using JTB with the following options :
    -jd -f -pp -tk -printer
    this will create Javadoc- friendly comments, explicit variable names, classes for special tokens and generates a basic pretty-printer visitor.
  3. JTB creates an output grammar named jdb.out.jj, and creates classes for the syntax tree objects, and also some visitor classes.
  4. Change the default code for the TreeFormatter class (change is underlined):
       public void visit(NodeToken n) {
          for ( Enumeration e = cmdQueue.elements(); e.hasMoreElements(); ) {
             FormatCommand cmd = (FormatCommand)e.nextElement();
             switch ( cmd.getCommand() ) {
             case FormatCommand.FORCE :
                curLine += cmd.getNumCommands();
                curColumn = curIndent + 1;
                break;
             case FormatCommand.INDENT :
                curIndent += indentAmt * cmd.getNumCommands();
                break;
             case FormatCommand.OUTDENT :
                if ( curIndent >= indentAmt )
                   curIndent -= indentAmt * cmd.getNumCommands();
                break;
             case FormatCommand.SPACE :
                curColumn += cmd.getNumCommands();
                break;
             default :
                throw new TreeFormatterException(
                   "Invalid value in command queue.");
             }
          }
    
          cmdQueue.removeAllElements();
    
          //
          // Handle all special tokens preceding this NodeToken
          //
          if ( n.numSpecials() > 0 )
             for ( Enumeration e = n.specialTokens.elements();
                   e.hasMoreElements(); ) {
                NodeToken special = (NodeToken)e.nextElement();
    
                //
                // -Place the token.
                //
                placeToken(special, curLine, curColumn);
                //curLine = special.endLine + 1;
                curLine = special.endLine;
                curColumn = special.endColumn;
             }
    
          placeToken(n, curLine, curColumn);
          curLine = n.endLine;
          curColumn = n.endColumn;
       }
    
       private void placeToken(NodeToken n, int line, int column) {
          int length = n.tokenImage.length();
    
          //
          // Find beginning of token.  Only line-wrap for single-line tokens
          //
          if ( !lineWrap || n.tokenImage.indexOf('\n') != -1 ||
               column + length <= wrapWidth )
             n.beginColumn = column;
          else {
             ++line;
             column = curIndent + indentAmt + 1;
             n.beginColumn = column;
          }
    
          n.beginLine = line;
    
          //
          // Find end of token; don't count \n if it's the last character
          //
          for ( int i = 0; i < length; ++i ) {
             if ( n.tokenImage.charAt(i) == '\n' /* && i < length - 1 */ ) {
                ++line;
                column = 1;
             }
             else
                ++column;
          }
    
          n.endLine = line;
          n.endColumn = column;
       }
       
    This is because we want special tokens end of lines to be correctly interpreted here.
  5. Then, write a mainline such as this one :
      public static void parse( String source ) {
        try {
          // open the source file
          File source_file = new File( source );
          FileInputStream is = new FileInputStream( source_file );
    
          // starts parsing
          CobolParser parser = new CobolParser( is );
          CompilationUnit unit = parser.CompilationUnit();
    
          // creates a formatter visitor
          TreeFormatter fmt = new TreeFormatter();
          fmt.visit( unit );
    
          // creates a dumper visitor
          TreeDumper dump = new TreeDumper();
          dump.visit( unit );
        }
        catch( Exception ex ) {
          ex.printStackTrace();
        }
      }
      

You should be able to "pretty-print" a COBOL source. Now it's up to you to add some HTML code in it.

The next step will be to develop specific visitors, for instance to build symbol tables.