package java_cup; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.Stack; /** * This class handles emitting generated code for the resulting parser. The * various parse tables must be constructed, etc. before calling any routines in * this class. * <p> * Three classes are produced by this code: * <dl> * <dt> symbol constant class * <dd> this contains constant declarations for each terminal (and optionally * each non-terminal). * <dt> action class * <dd> this non-public class contains code to invoke all the user actions that * were embedded in the parser specification. * <dt> parser class * <dd> the specialized parser class consisting primarily of some user supplied * general and initialization code, and the parse tables. * </dl> * <p> * Three parse tables are created as part of the parser class: * <dl> * <dt> production table * <dd> lists the LHS non terminal number, and the length of the RHS of each * production. * <dt> action table * <dd> for each state of the parse machine, gives the action to be taken * (shift, reduce, or error) under each lookahead symbol.<br> * <dt> reduce-goto table * <dd> when a reduce on a given production is taken, the parse stack is popped * back a number of elements corresponding to the RHS of the production. This * reveals a prior state, which we transition out of under the LHS non terminal * symbol for the production (as if we had seen the LHS symbol rather than all * the symbols matching the RHS). This table is indexed by non terminal numbers * and indicates how to make these transitions. * </dl> * <p> * In addition to the method interface, this class maintains a series of public * global variables and flags indicating how misc. parts of the code and other * output is to be produced, and counting things such as number of conflicts * detected (see the source code and public variables below for more details). * <p> * This class is "static" (contains only static data and methods). * <p> * * @version last update: 11/25/95 * @author Scott Hudson * @author Christian Fehler */ /* * Major externally callable routines here include: symbols - emit the symbol * constant class parser - emit the parser class In addition the following major * internal routines are provided: emit_package - emit a package declaration * emit_action_code - emit the class containing the user's actions * emit_production_table - emit declaration and init for the production table * do_action_table - emit declaration and init for the action table * do_reduce_table - emit declaration and init for the reduce-goto table * Finally, this class uses a number of public instance variables to communicate * optional parameters and flags used to control how code is generated, as well * as to report counts of various things (such as number of conflicts detected). * These include: prefix - a prefix string used to prefix names that would * otherwise "pollute" someone else's name space. package_name - name of the * package emitted code is placed in (or null for an unnamed package. * symbol_const_class_name - name of the class containing symbol constants. * parser_class_name - name of the class for the resulting parser. action_code - * user supplied declarations and other code to be placed in action class. * parser_code - user supplied declarations and other code to be placed in * parser class. init_code - user supplied code to be executed as the parser is * being initialized. scan_code - user supplied code to get the next Symbol. * start_production - the start production for the grammar. import_list - list * of imports for use with action class. num_conflicts - number of conflicts * detected. nowarn - true if we are not to issue warning messages. not_reduced - * count of number of productions that never reduce. unused_term - count of * unused terminal symbols. unused_non_term - count of unused non terminal * symbols. _time - a series of symbols indicating how long various sub-parts of * code generation took (used to produce optional time reports in main). */ @SuppressWarnings ( { "all", "unchecked" } ) public class emit { /*-----------------------------------------------------------*/ /*--- Constructor(s) ----------------------------------------*/ /*-----------------------------------------------------------*/ /** Only constructor is private so no instances can be created. */ private emit () { } /*-----------------------------------------------------------*/ /*--- Static (Class) Variables ------------------------------*/ /*-----------------------------------------------------------*/ /** The prefix placed on names that pollute someone else's name space. */ public static String prefix = "CUP$"; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Package that the resulting code goes into (null is used for unnamed). */ public static String package_name = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Name of the generated class for symbol constants. */ public static String symbol_const_class_name = "sym"; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Name of the generated parser class. */ public static String parser_class_name = "parser"; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * TUM changes; proposed by Henning Niss 20050628: Type arguments for class * declaration */ public static String class_type_argument = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** User declarations for direct inclusion in user action class. */ public static String action_code = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** User declarations for direct inclusion in parser class. */ public static String parser_code = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** User code for user_init() which is called during parser initialization. */ public static String init_code = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** User code for scan() which is called to get the next Symbol. */ public static String scan_code = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** The start production of the grammar. */ public static production start_production = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** List of imports (Strings containing class names) to go with actions. */ public static Stack import_list = new Stack (); /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Number of conflict found while building tables. */ public static int num_conflicts = 0; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Do we skip warnings? */ public static boolean nowarn = false; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Count of the number on non-reduced productions found. */ public static int not_reduced = 0; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Count of unused terminals. */ public static int unused_term = 0; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Count of unused non terminals. */ public static int unused_non_term = 0; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /* Timing values used to produce timing report in main. */ /** Time to produce symbol constant class. */ public static long symbols_time = 0; /** Time to produce parser class. */ public static long parser_time = 0; /** Time to produce action code class. */ public static long action_code_time = 0; /** Time to produce the production table. */ public static long production_table_time = 0; /** Time to produce the action table. */ public static long action_table_time = 0; /** Time to produce the reduce-goto table. */ public static long goto_table_time = 0; /* frankf 6/18/96 */ protected static boolean _lr_values; /** whether or not to emit code for left and right values */ public static boolean lr_values () { return _lr_values; } protected static void set_lr_values ( boolean b ) { _lr_values = b; } // Hm Added clear to clear all static fields public static void clear () { _lr_values = true; action_code = null; import_list = new Stack (); init_code = null; not_reduced = 0; num_conflicts = 0; package_name = null; parser_class_name = "parser"; parser_code = null; scan_code = null; start_production = null; symbol_const_class_name = "sym"; unused_non_term = 0; unused_term = 0; } /*-----------------------------------------------------------*/ /*--- General Methods ---------------------------------------*/ /*-----------------------------------------------------------*/ /** * Build a string with the standard prefix. * * @param str string to prefix. */ protected static String pre ( String str ) { return prefix + parser_class_name + "$" + str; } /** * TUM changes; proposed by Henning Niss 20050628 Build a string with the * specified type arguments, if present, otherwise an empty string. */ protected static String typeArgument () { return class_type_argument == null ? "" : "<" + class_type_argument + ">"; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit a package spec if the user wants one. * * @param out stream to produce output on. */ protected static void emit_package ( PrintWriter out ) { /* generate a package spec if we have a name for one */ if ( package_name != null ) { out.println ( "package " + package_name + ";" ); out.println (); } } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit code for the symbol constant class, optionally including non terms, if * they have been requested. * * @param out stream to produce output on. * @param emit_non_terms do we emit constants for non terminals? * @param sym_interface should we emit an interface, rather than a class? */ public static void symbols ( PrintWriter out, boolean emit_non_terms, boolean sym_interface ) { terminal term; non_terminal nt; String class_or_interface = ( sym_interface ) ? "interface" : "class"; long start_time = System.currentTimeMillis (); /* top of file */ out.println (); out.println ( "//----------------------------------------------------" ); out .println ( "// The following code was generated by " + version.title_str ); out.println ( "// " + new Date () ); out.println ( "//----------------------------------------------------" ); out.println (); emit_package ( out ); /* class header */ out.println ( "/** CUP generated " + class_or_interface + " containing symbol constants. */" ); out.println ( "@ SuppressWarnings ( value = { \"all\" } )" ); out.println ( "public " + class_or_interface + " " + symbol_const_class_name + " {" ); out.println ( " /* terminals */" ); /* walk over the terminals *//* later might sort these */ for ( Enumeration e = terminal.all () ; e.hasMoreElements () ; ) { term = ( terminal ) e.nextElement (); /* output a constant decl for the terminal */ out.println ( " public static final int " + term.name () + " = " + term.index () + ";" ); } /* do the non terminals if they want them (parser doesn't need them) */ if ( emit_non_terms ) { out.println (); out.println ( " /* non terminals */" ); /* walk over the non terminals *//* later might sort these */ for ( Enumeration e = non_terminal.all () ; e.hasMoreElements () ; ) { nt = ( non_terminal ) e.nextElement (); // **** // TUM Comment: here we could add a typesafe enumeration // **** /* output a constant decl for the terminal */ out.println ( " static final int " + nt.name () + " = " + nt.index () + ";" ); } } /* end of class */ out.println ( "}" ); out.println (); symbols_time = System.currentTimeMillis () - start_time; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit code for the non-public class holding the actual action code. * * @param out stream to produce output on. * @param start_prod the start production of the grammar. */ protected static void emit_action_code ( PrintWriter out, production start_prod ) throws internal_error { long start_time = System.currentTimeMillis (); /* class header */ out.println (); out .println ( "/** Cup generated class to encapsulate user supplied action code.*/" ); /* TUM changes; proposed by Henning Niss 20050628: added type arguement */ out.println ( "@ SuppressWarnings ( value = { \"all\" } )" ); out.println ( "class " + pre ( "actions" ) + typeArgument () + " {" ); /* user supplied code */ if ( action_code != null ) { out.println (); out.println ( action_code ); } /* field for parser object */ /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */ out.println ( " private final " + parser_class_name + typeArgument () + " parser;" ); /* constructor */ out.println (); out.println ( " /** Constructor */" ); /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */ out.println ( " " + pre ( "actions" ) + "(" + parser_class_name + typeArgument () + " parser) {" ); out.println ( " this.parser = parser;" ); out.println ( " }" ); /* action method head */ out.println (); out.println ( " /** Method with the actual generated action code. */" ); out.println ( " public final java_cup.runtime.Symbol " + pre ( "do_action" ) + "(" ); out.println ( " int " + pre ( "act_num," ) ); out.println ( " java_cup.runtime.lr_parser " + pre ( "parser," ) ); out.println ( " java.util.Stack " + pre ( "stack," ) ); out.println ( " int " + pre ( "top)" ) ); out.println ( " throws java.lang.Exception" ); out.println ( " {" ); /* declaration of result symbol */ /* * New declaration!! now return Symbol 6/13/96 frankf */ out.println ( " /* Symbol object for return from actions */" ); out.println (); /* switch top */ out.println ( " /* select the action based on the action number */" ); out.println ( " switch (" + pre ( "act_num" ) + ")" ); out.println ( " {" ); /* emit action code for each production as a separate case */ ArrayList list = new ArrayList (); for ( Enumeration p = production.all () ; p.hasMoreElements () ; ) { list.add ( ( production ) p.nextElement () ); } for ( int j = 0 ; j < list.size () ; j++ ) { production prod = ( production ) list.get ( j ); /* case label */ out.println ( " /*. . . . . . . . . . . . . . . . . . . .*/" ); out.println ( " case " + prod.index () + ": // " + prod.to_simple_string () ); /* give them their own block to work in */ out.println ( " return " + pre ( "do_action" ) + prod.index () + " (" + pre ( "act_num," ) + pre ( "parser," ) + pre ( "stack," ) + pre ( "top" ) + ") ;" ); } /* end of switch */ out.println ( " /* . . . . . .*/" ); out.println ( " default:" ); out.println ( " throw new Exception(" ); out.println ( " \"Invalid action number found in " + "internal parse table\");" ); out.println (); out.println ( " }" ); /* end of method */ out.println ( " }" ); for ( int j = 0 ; j < list.size () ; j++ ) { production prod = ( production ) list.get ( j ); out.println (); out.println (); out.println ( " // " + prod.to_simple_string () ); out.println ( " public final java_cup.runtime.Symbol " + pre ( "do_action" ) + +prod.index () + "(" ); out.println ( " int " + pre ( "act_num," ) ); out.println ( " java_cup.runtime.lr_parser " + pre ( "parser," ) ); out.println ( " java.util.Stack " + pre ( "stack," ) ); out.println ( " int " + pre ( "top)" ) ); out.println ( " throws java.lang.Exception" ); out.println ( " {" ); out.println ( " java_cup.runtime.Symbol " + pre ( "result" ) + ";" ); String result = "null"; if ( prod instanceof action_production ) { int lastResult = ( ( action_production ) prod ) .getIndexOfIntermediateResult (); if ( lastResult != -1 ) { result = "(" + prod.lhs ().the_symbol ().stack_type () + ") " + "((java_cup.runtime.Symbol) " + emit.pre ( "stack" ) + // TUM 20050917 ( ( lastResult == 1 ) ? ".peek()" : ( ".elementAt(" + emit.pre ( "top" ) + "-" + ( lastResult - 1 ) + ")" ) ) + ").value"; } } /* create the result symbol */ /* * make the variable RESULT which will point to the new Symbol (see below) * and be changed by action code 6/13/96 frankf */ out.println ( " " + prod.lhs ().the_symbol ().stack_type () + " RESULT =" + result + ";" ); /* * Add code to propagate RESULT assignments that occur in action code * embedded in a production (ie, non-rightmost action code). 24-Mar-1998 * CSA */ for ( int i = prod.rhs_length () - 1 ; i >= 0 ; i-- ) { // only interested in non-terminal symbols. if ( ! ( prod.rhs ( i ) instanceof symbol_part ) ) continue; symbol s = ( ( symbol_part ) prod.rhs ( i ) ).the_symbol (); if ( ! ( s instanceof non_terminal ) ) continue; // skip this non-terminal unless it corresponds to // an embedded action production. if ( ( ( non_terminal ) s ).is_embedded_action == false ) continue; // OK, it fits. Make a conditional assignment to RESULT. int index = prod.rhs_length () - i - 1; // last rhs is on top. // set comment to inform about where the intermediate result came from out.println ( " " + "// propagate RESULT from " + s.name () ); // // look out, whether the intermediate result is null or not // out.println(" " + "if ( " + // "((java_cup.runtime.Symbol) " + emit.pre("stack") + // // TUM 20050917 // ((index==0)?".peek()":(".elementAt(" + emit.pre("top") + "-" + index // + ")"))+ // ").value != null )"); // TUM 20060608: even when its null: who cares? // store the intermediate result into RESULT out.println ( " " + "RESULT = " + "(" + prod.lhs ().the_symbol ().stack_type () + ") " + "((java_cup.runtime.Symbol) " + emit.pre ( "stack" ) + // TUM 20050917 ( ( index == 0 ) ? ".peek()" : ( ".elementAt(" + emit.pre ( "top" ) + "-" + index + ")" ) ) + ").value;" ); break; } /* if there is an action string, emit it */ if ( prod.action () != null && prod.action ().code_string () != null && !prod.action ().equals ( "" ) ) out.println ( prod.action ().code_string () ); /* * here we have the left and right values being propagated. must make this * a command line option. frankf 6/18/96 */ /* * Create the code that assigns the left and right values of the new * Symbol that the production is reducing to */ if ( emit.lr_values () ) { int loffset; String leftstring, rightstring; // TUM 20050917 // int roffset = 0; rightstring = "((java_cup.runtime.Symbol)" + emit.pre ( "stack" ) + // TUM 20050917 // ".elementAt(" + emit.pre("top") + "-" + roffset + "))"+ ".peek()" + // TUM 20060327 removed .right ")"; if ( prod.rhs_length () == 0 ) leftstring = rightstring; else { loffset = prod.rhs_length () - 1; leftstring = "((java_cup.runtime.Symbol)" + emit.pre ( "stack" ) + // TUM 20050917 ( ( loffset == 0 ) ? ( ".peek()" ) : ( ".elementAt(" + emit.pre ( "top" ) + "-" + loffset + ")" ) ) + // TUM 20060327 removed .left ")"; } // out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" + out.println ( " " + pre ( "result" ) + " = parser.getSymbolFactory().newSymbol(" + "\"" + prod.lhs ().the_symbol ().name () + "\"," + prod.lhs ().the_symbol ().index () + ", " + leftstring + ", " + rightstring + ", RESULT);" ); } else { // out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" + out.println ( " " + pre ( "result" ) + " = parser.getSymbolFactory().newSymbol(" + "\"" + prod.lhs ().the_symbol ().name () + "\"," + prod.lhs ().the_symbol ().index () + ", RESULT);" ); } /* if this was the start production, do action for accept */ if ( prod == start_prod ) { out.println ( " /* ACCEPT */" ); out.println ( " " + pre ( "parser" ) + ".done_parsing();" ); } /* code to return lhs symbol */ out.println ( " return " + pre ( "result" ) + ";" ); // End of Method out.println ( " }" ); } /* end of class */ out.println ( "}" ); out.println (); action_code_time = System.currentTimeMillis () - start_time; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit the production table. * * @param out stream to produce output on. */ protected static void emit_production_table ( PrintWriter out ) { production all_prods[]; production prod; long start_time = System.currentTimeMillis (); /* collect up the productions in order */ all_prods = new production [ production.number () ]; for ( Enumeration p = production.all () ; p.hasMoreElements () ; ) { prod = ( production ) p.nextElement (); all_prods [ prod.index () ] = prod; } // make short[][] short [][] prod_table = new short [ production.number () ] [ 2 ]; for ( int i = 0 ; i < production.number () ; i++ ) { prod = all_prods [ i ]; // { lhs symbol , rhs size } prod_table [ i ] [ 0 ] = ( short ) prod.lhs ().the_symbol ().index (); prod_table [ i ] [ 1 ] = ( short ) prod.rhs_length (); } /* do the top of the table */ out.println (); out.println ( " /** Production table. */" ); out.println ( " protected static final short _production_table[][] = " ); out.print ( " unpackFromStrings(" ); do_table_as_string ( out, prod_table ); out.println ( ");" ); /* do the public accessor method */ out.println (); out.println ( " /** Access to production table. */" ); out.println ( " public short[][] production_table() " + "{return _production_table;}" ); production_table_time = System.currentTimeMillis () - start_time; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit the action table. * * @param out stream to produce output on. * @param act_tab the internal representation of the action table. * @param compact_reduces do we use the most frequent reduce as default? */ protected static void do_action_table ( PrintWriter out, parse_action_table act_tab, boolean compact_reduces ) throws internal_error { parse_action_row row; parse_action act; int red; long start_time = System.currentTimeMillis (); /* collect values for the action table */ short [][] action_table = new short [ act_tab.num_states () ] []; /* do each state (row) of the action table */ for ( int i = 0 ; i < act_tab.num_states () ; i++ ) { /* get the row */ row = act_tab.under_state [ i ]; /* determine the default for the row */ if ( compact_reduces ) row.compute_default (); else row.default_reduce = -1; /* make temporary table for the row. */ short [] temp_table = new short [ 2 * parse_action_row.size () ]; int nentries = 0; /* do each column */ for ( int j = 0 ; j < parse_action_row.size () ; j++ ) { /* extract the action from the table */ act = row.under_term [ j ]; /* skip error entries these are all defaulted out */ if ( act.kind () != parse_action.ERROR ) { /* first put in the symbol index, then the actual entry */ /* shifts get positive entries of state number + 1 */ if ( act.kind () == parse_action.SHIFT ) { /* make entry */ temp_table [ nentries++ ] = ( short ) j; temp_table [ nentries++ ] = ( short ) ( ( ( shift_action ) act ) .shift_to ().index () + 1 ); } /* reduce actions get negated entries of production# + 1 */ else if ( act.kind () == parse_action.REDUCE ) { /* if its the default entry let it get defaulted out */ red = ( ( reduce_action ) act ).reduce_with ().index (); if ( red != row.default_reduce ) { /* make entry */ temp_table [ nentries++ ] = ( short ) j; temp_table [ nentries++ ] = ( short ) ( - ( red + 1 ) ); } } else if ( act.kind () == parse_action.NONASSOC ) { /* do nothing, since we just want a syntax error */ } /* shouldn't be anything else */ else throw new internal_error ( "Unrecognized action code " + act.kind () + " found in parse table" ); } } /* now we know how big to make the row */ action_table [ i ] = new short [ nentries + 2 ]; System.arraycopy ( temp_table, 0, action_table [ i ], 0, nentries ); /* finish off the row with a default entry */ action_table [ i ] [ nentries++ ] = -1; if ( row.default_reduce != -1 ) action_table [ i ] [ nentries++ ] = ( short ) ( - ( row.default_reduce + 1 ) ); else action_table [ i ] [ nentries++ ] = 0; } /* finish off the init of the table */ out.println (); out.println ( " /** Parse-action table. */" ); out.println ( " protected static final short[][] _action_table = " ); out.print ( " unpackFromStrings(" ); do_table_as_string ( out, action_table ); out.println ( ");" ); /* do the public accessor method */ out.println (); out.println ( " /** Access to parse-action table. */" ); out.println ( " public short[][] action_table() {return _action_table;}" ); action_table_time = System.currentTimeMillis () - start_time; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit the reduce-goto table. * * @param out stream to produce output on. * @param red_tab the internal representation of the reduce-goto table. */ protected static void do_reduce_table ( PrintWriter out, parse_reduce_table red_tab ) { lalr_state goto_st; parse_action act; long start_time = System.currentTimeMillis (); /* collect values for reduce-goto table */ short [][] reduce_goto_table = new short [ red_tab.num_states () ] []; /* do each row of the reduce-goto table */ for ( int i = 0 ; i < red_tab.num_states () ; i++ ) { /* make temporary table for the row. */ short [] temp_table = new short [ 2 * parse_reduce_row.size () ]; int nentries = 0; /* do each entry in the row */ for ( int j = 0 ; j < parse_reduce_row.size () ; j++ ) { /* get the entry */ goto_st = red_tab.under_state [ i ].under_non_term [ j ]; /* if we have none, skip it */ if ( goto_st != null ) { /* make entries for the index and the value */ temp_table [ nentries++ ] = ( short ) j; temp_table [ nentries++ ] = ( short ) goto_st.index (); } } /* now we know how big to make the row. */ reduce_goto_table [ i ] = new short [ nentries + 2 ]; System.arraycopy ( temp_table, 0, reduce_goto_table [ i ], 0, nentries ); /* end row with default value */ reduce_goto_table [ i ] [ nentries++ ] = -1; reduce_goto_table [ i ] [ nentries++ ] = -1; } /* emit the table. */ out.println (); out.println ( " /** <code>reduce_goto</code> table. */" ); out.println ( " protected static final short[][] _reduce_table = " ); out.print ( " unpackFromStrings(" ); do_table_as_string ( out, reduce_goto_table ); out.println ( ");" ); /* do the public accessor method */ out.println (); out.println ( " /** Access to <code>reduce_goto</code> table. */" ); out.println ( " public short[][] reduce_table() {return _reduce_table;}" ); out.println (); goto_table_time = System.currentTimeMillis () - start_time; } // print a string array encoding the given short[][] array. protected static void do_table_as_string ( PrintWriter out, short [][] sa ) { out.println ( "new String[] {" ); out.print ( " \"" ); int nchar = 0, nbytes = 0; nbytes += do_escaped ( out, ( char ) ( sa.length >> 16 ) ); nchar = do_newline ( out, nchar, nbytes ); nbytes += do_escaped ( out, ( char ) ( sa.length & 0xFFFF ) ); nchar = do_newline ( out, nchar, nbytes ); for ( int i = 0 ; i < sa.length ; i++ ) { nbytes += do_escaped ( out, ( char ) ( sa [ i ].length >> 16 ) ); nchar = do_newline ( out, nchar, nbytes ); nbytes += do_escaped ( out, ( char ) ( sa [ i ].length & 0xFFFF ) ); nchar = do_newline ( out, nchar, nbytes ); for ( int j = 0 ; j < sa [ i ].length ; j++ ) { // contents of string are (value+2) to allow for common -1, 0 cases // (UTF-8 encoding is most efficient for 0<c<0x80) nbytes += do_escaped ( out, ( char ) ( 2 + sa [ i ] [ j ] ) ); nchar = do_newline ( out, nchar, nbytes ); } } out.print ( "\" }" ); } // split string if it is very long; start new line occasionally for neatness protected static int do_newline ( PrintWriter out, int nchar, int nbytes ) { if ( nbytes > 65500 ) { out.println ( "\", " ); out.print ( " \"" ); } else if ( nchar > 11 ) { out.println ( "\" +" ); out.print ( " \"" ); } else return nchar + 1; return 0; } // output an escape sequence for the given character code. protected static int do_escaped ( PrintWriter out, char c ) { StringBuffer escape = new StringBuffer (); if ( c <= 0xFF ) { escape.append ( Integer.toOctalString ( c ) ); while ( escape.length () < 3 ) escape.insert ( 0, '0' ); } else { escape.append ( Integer.toHexString ( c ) ); while ( escape.length () < 4 ) escape.insert ( 0, '0' ); escape.insert ( 0, 'u' ); } escape.insert ( 0, '\\' ); out.print ( escape.toString () ); // return number of bytes this takes up in UTF-8 encoding. if ( c == 0 ) return 2; if ( c >= 0x01 && c <= 0x7F ) return 1; if ( c >= 0x80 && c <= 0x7FF ) return 2; return 3; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Emit the parser subclass with embedded tables. * * @param out stream to produce output on. * @param action_table internal representation of the action table. * @param reduce_table internal representation of the reduce-goto table. * @param start_st start state of the parse machine. * @param start_prod start production of the grammar. * @param compact_reduces do we use most frequent reduce as default? * @param suppress_scanner should scanner be suppressed for compatibility? */ public static void parser ( PrintWriter out, parse_action_table action_table, parse_reduce_table reduce_table, int start_st, production start_prod, boolean compact_reduces, boolean suppress_scanner ) throws internal_error { long start_time = System.currentTimeMillis (); /* top of file */ out.println (); out.println ( "//----------------------------------------------------" ); out .println ( "// The following code was generated by " + version.title_str ); out.println ( "// " + new Date () ); out.println ( "//----------------------------------------------------" ); out.println (); emit_package ( out ); /* user supplied imports */ for ( int i = 0 ; i < import_list.size () ; i++ ) out.println ( "import " + import_list.elementAt ( i ) + ";" ); /* class header */ out.println (); out.println ( "/** " + version.title_str + " generated parser." ); out.println ( " * @version " + new Date () ); out.println ( " */" ); /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */ out.println ( "@ SuppressWarnings ( value = { \"all\" } )" ); out.println ( "public class " + parser_class_name + typeArgument () + " extends java_cup.runtime.lr_parser {" ); /* constructors [CSA/davidm, 24-jul-99] */ out.println (); out.println ( " /** Default constructor. */" ); out.println ( " public " + parser_class_name + "() {super();}" ); if ( !suppress_scanner ) { out.println (); out.println ( " /** Constructor which sets the default scanner. */" ); out.println ( " public " + parser_class_name + "(java_cup.runtime.Scanner s) {super(s);}" ); // TUM 20060327 added SymbolFactory aware constructor out.println (); out.println ( " /** Constructor which sets the default scanner. */" ); out .println ( " public " + parser_class_name + "(java_cup.runtime.Scanner s, java_cup.runtime.SymbolFactory sf) {super(s,sf);}" ); } /* emit the various tables */ emit_production_table ( out ); do_action_table ( out, action_table, compact_reduces ); do_reduce_table ( out, reduce_table ); /* instance of the action encapsulation class */ out.println ( " /** Instance of action encapsulation class. */" ); out.println ( " protected " + pre ( "actions" ) + " action_obj;" ); out.println (); /* action object initializer */ out.println ( " /** Action encapsulation object initializer. */" ); out.println ( " protected void init_actions()" ); out.println ( " {" ); /* TUM changes; proposed by Henning Niss 20050628: added typeArgument */ out.println ( " action_obj = new " + pre ( "actions" ) + typeArgument () + "(this);" ); out.println ( " }" ); out.println (); /* access to action code */ out.println ( " /** Invoke a user supplied parse action. */" ); out.println ( " public java_cup.runtime.Symbol do_action(" ); out.println ( " int act_num," ); out.println ( " java_cup.runtime.lr_parser parser," ); out.println ( " java.util.Stack stack," ); out.println ( " int top)" ); out.println ( " throws java.lang.Exception" ); out.println ( " {" ); out.println ( " /* call code in generated class */" ); out.println ( " return action_obj." + pre ( "do_action(" ) + "act_num, parser, stack, top);" ); out.println ( " }" ); out.println ( "" ); /* method to tell the parser about the start state */ out.println ( " /** Indicates start state. */" ); out.println ( " public int start_state() {return " + start_st + ";}" ); /* method to indicate start production */ out.println ( " /** Indicates start production. */" ); out.println ( " public int start_production() {return " + start_production.index () + ";}" ); out.println (); /* methods to indicate EOF and error symbol indexes */ out.println ( " /** <code>EOF</code> Symbol index. */" ); out.println ( " public int EOF_sym() {return " + terminal.EOF.index () + ";}" ); out.println (); out.println ( " /** <code>error</code> Symbol index. */" ); out.println ( " public int error_sym() {return " + terminal.error.index () + ";}" ); out.println (); /* user supplied code for user_init() */ if ( init_code != null ) { out.println (); out.println ( " /** User initialization code. */" ); out.println ( " public void user_init() throws java.lang.Exception" ); out.println ( " {" ); out.println ( init_code ); out.println ( " }" ); } /* user supplied code for scan */ if ( scan_code != null ) { out.println (); out.println ( " /** Scan to get the next Symbol. */" ); out.println ( " public java_cup.runtime.Symbol scan()" ); out.println ( " throws java.lang.Exception" ); out.println ( " {" ); out.println ( scan_code ); out.println ( " }" ); } /* user supplied code */ if ( parser_code != null ) { out.println (); out.println ( parser_code ); } /* end of class */ out.println ( "}" ); /* put out the action code class */ emit_action_code ( out, start_prod ); parser_time = System.currentTimeMillis () - start_time; } /*-----------------------------------------------------------*/ }