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 ;
}
/*-----------------------------------------------------------*/
}