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> * * @see java_cup.main * @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). */ 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 ( "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 ; } /*-----------------------------------------------------------*/ }