

import Jakarta.util.Util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

//-----------------------------------------------------------------------//
// Main class below (initial version generated by GenCT):
//-----------------------------------------------------------------------//

/**
 * Provides a <code>main</code> method with argument-parsing for a
 * command-line tool.  This version implements a parser test that works as
 * follows.  First, input is read from a file and parsed.  Second, the
 * parse tree is used to generate output that is supposed to match the
 * original input.  Third, the input and output is compared to see if
 * they're equal except for repeated whitespace.  Finally, the exit status
 * is 0 (good) if all work through the comparison succeeds and is non-zero
 * (bad) otherwise.
 *
 * @layer<bali>
 */
    
public class Main {

    /**
     * A globally available {@link Logger} for debugging output.  See
     * {@link Main#main(String[])} for additional configuration.
     *
     * @layer<bali>
     */
    final public static Logger DEBUG = Logger.getLogger( "debug" ) ;

    final public static
        String LINE_SEPARATOR = System.getProperty( "line.separator" ) ;

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

    public Object driver( String[] args ) throws Throwable {

        Main.DEBUG.entering( "bali.Main", "driver", args ) ;
        setVersion( "v2002.09.03" ) ;

        String USAGE = "Usage: bali <input-source-file>" ;

        // Check and parse command-line arguments:
        //
        if ( args.length != 1 )
            throw new IllegalArgumentException( USAGE ) ;
      
        // Read input file into a string:
        //
        String input = file2string( args [0] ) ;

        // Parse the input text:
        //
        Parser parser =  Parser.getInstance( new StringReader( input ) ) ;
        BaliParse parseTree = (BaliParse) parser.parseAll () ;
 
        if ( Util.errorCount() > 0 )
            throw new IllegalStateException( "errors occurred in parse" ) ;

        // Print parse tree into another string:
        //
        String output = parse2string( parseTree ) ;

        // Compare input string against output string, after normalizing
        // whitespace:
        //
        input = normalize( input ) ;
        output = normalize( output ) ;

        if ( ! input.equals( output ) )
            throw new IllegalStateException( "input != output" ) ;

        // Everything went ok, so just return the parse tree:
        //
        Main.DEBUG.exiting( "bali.Main", "driver", "parseTree" ) ;
        return parseTree ;
    }

    public static void main( String[] args ) {

        // Initial configuration for the debugging {@link Logger}:
        //
        Main.DEBUG.setLevel( Level.WARNING ) ;
        Main.DEBUG.setUseParentHandlers( false ) ;
        Main.DEBUG.addHandler( LogHandler.CONSOLE ) ;
            
        try {
            Main instance = new  Main() ;
            instance.driver( args ) ;
        }
        catch ( Throwable thrown ) {
            thrown.printStackTrace() ;
            System.exit( 1 ) ;
        }
    }

    /**
     * Returns a version string for this tool.  Each layer should call
     * {@link Main#setVersion(String)} in {@link Main#driver(String[])}.
     * The version for a tool is the most recent version of the layers.
     *
     * <p>
     * Version strings are in ISO-8601 date form.  For example,
     * "v2002.08.27" means this code was last modified on August 27, 2002.
     *
     * @layer<bali>
     */
    public static String getVersion() {
        if ( versionString == null || versionString.length() < 1 )
            return "v0000.00.00" ;
        return versionString ;
    }

    public static String setVersion( String version ) {
        if ( version.length() < "v0000.00.00".length() )
            throw new IllegalStateException( "bad version " + version ) ;
        if ( versionString == null || versionString.length() < 1 )
            versionString = version ;
        else
            if ( versionString.compareTo( version ) < 0 )
                versionString = version ;
        return versionString ;
    }

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    // Private material:
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    /**
     * Reads a file specified by filename and returns the content as a
     * {@link String}.
     *
     * @layer<bali>
     */
    private static String file2string( String fileName )
    throws IOException {

        Reader reader = new BufferedReader( inputStreamReader( new FileInputStream( new File( fileName ) ) ) ) ;

        Writer writer = new StringWriter( 1024 ) ;

        char[] data = new char [1024] ;
        for ( int size ; ( size = reader.read( data, 0, data.length ) ) >= 0 ; )
            writer.write( data, 0, size ) ;

        writer.flush() ;
        return writer.toString() ;
    }

    /**
     * Constructs an {@link InputStreamReader} on an {@link InputStream},
     * using encoding "ISO-8859-1" in preference to the default.
     *
     * @layer<bali>
     */
    private static InputStreamReader inputStreamReader( InputStream inp )
    throws FileNotFoundException {

        try {
            return new InputStreamReader( inp, "ISO-8859-1" ) ;
        }
        catch ( UnsupportedEncodingException exception ) {
            return new InputStreamReader( inp ) ;
        }
    }

    /**
     * Normalizes a string by removing repeated whitespace characters.
     *
     * @layer<bali>
     */
    private static String normalize( String string ) {

        StringBuffer buffer = new StringBuffer( string.length() ) ;

        StringTokenizer tokenizer = new StringTokenizer( string ) ;
        while ( tokenizer.hasMoreElements() )
            buffer.append( " " ).append( tokenizer.nextToken() ) ;

        return buffer.append( " " ).toString() ;
    }

    /**
     * Converts a {@link BaliParse} tree into a {@link String} by visiting
     * the tree in a depth-first fashion, printing the tokens that form
     * each node (including special "whitespace" tokens).
     *
     * @layer<bali>
     */
    private static String parse2string( BaliParse parse )
    throws IOException {

        StringWriter stringWriter = new StringWriter( 1024 ) ;
        PrintWriter printWriter = new PrintWriter( stringWriter ) ;

        AstProperties props = new  AstProperties();
        props.setProperty( "output", printWriter ) ;
        parse.print( props ) ;
        printWriter.flush() ;

        return stringWriter.toString() ;
    }

    private static String versionString = null ;

}
