--- /dev/null
+package java_cup;
+
+import java.io.PrintWriter;
+import java.util.Stack;
+import java.util.Enumeration;
+import java.util.Date;
+
+/**
+ * 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
+ */
+
+/* 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";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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;}
+
+ /*-----------------------------------------------------------*/
+ /*--- 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;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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();
+
+ /* 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
+ {
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* class header */
+ out.println();
+ out.println(
+ "/** Cup generated class to encapsulate user supplied action code.*/"
+ );
+ out.println("class " + pre("actions") + " {");
+
+ /* user supplied code */
+ if (action_code != null)
+ {
+ out.println();
+ out.println(action_code);
+ }
+
+ /* field for parser object */
+ out.println(" private final "+parser_class_name+" parser;");
+
+ /* constructor */
+ out.println();
+ out.println(" /** Constructor */");
+ out.println(" " + pre("actions") + "("+parser_class_name+" 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(" java_cup.runtime.Symbol " + pre("result") + ";");
+ 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 */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* case label */
+ out.println(" /*. . . . . . . . . . . . . . . . . . . .*/");
+ out.println(" case " + prod.index() + ": // " +
+ prod.to_simple_string());
+
+ /* give them their own block to work in */
+ out.println(" {");
+
+ /* 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 = null;");
+
+ /* create the PRODSTRING variable, useful for debugging */
+ out.println(" String PRODSTRING = \"" + prod.to_simple_string() + "\";");
+
+ /* 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=0; i<prod.rhs_length(); 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.
+ out.println(" " + "// propagate RESULT from " +
+ s.name());
+ out.println(" " + "if ( " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value != null )");
+ out.println(" " + "RESULT = " +
+ "(" + prod.lhs().the_symbol().stack_type() + ") " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value;");
+ }
+
+ /* 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;
+ int roffset = 0;
+ rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + roffset + ")).right";
+ if (prod.rhs_length() == 0)
+ leftstring = rightstring;
+ else {
+ loffset = prod.rhs_length() - 1;
+ leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + loffset + ")).left";
+ }
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", " + leftstring + ", " + rightstring + ", RESULT);");
+ } else {
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", RESULT);");
+ }
+
+ /* end of their block */
+ out.println(" }");
+
+ /* 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") + ";");
+ out.println();
+ }
+
+ /* 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(" }");
+
+ /* 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*row.size()];
+ int nentries = 0;
+
+ /* do each column */
+ for (int j = 0; j < 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*red_tab.under_state[i].size()];
+ int nentries = 0;
+ /* do each entry in the row */
+ for (int j=0; j<red_tab.under_state[i].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(" */");
+ out.println("public class " + parser_class_name +
+ " 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);}");
+ }
+
+ /* 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(" {");
+ out.println(" action_obj = new " + pre("actions") + "(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;
+ }
+
+ /*-----------------------------------------------------------*/
+}