3 import java.io.PrintWriter;
4 import java.util.ArrayList;
5 import java.util.HashSet;
6 import java.util.Iterator;
9 import java.util.Stack;
10 import java.util.Enumeration;
11 import java.util.Date;
14 * This class handles emitting generated code for the resulting parser.
15 * The various parse tables must be constructed, etc. before calling any
16 * routines in this class.<p>
18 * Three classes are produced by this code:
20 * <dt> symbol constant class
21 * <dd> this contains constant declarations for each terminal (and
22 * optionally each non-terminal).
24 * <dd> this non-public class contains code to invoke all the user actions
25 * that were embedded in the parser specification.
27 * <dd> the specialized parser class consisting primarily of some user
28 * supplied general and initialization code, and the parse tables.
31 * Three parse tables are created as part of the parser class:
33 * <dt> production table
34 * <dd> lists the LHS non terminal number, and the length of the RHS of
37 * <dd> for each state of the parse machine, gives the action to be taken
38 * (shift, reduce, or error) under each lookahead symbol.<br>
39 * <dt> reduce-goto table
40 * <dd> when a reduce on a given production is taken, the parse stack is
41 * popped back a number of elements corresponding to the RHS of the
42 * production. This reveals a prior state, which we transition out
43 * of under the LHS non terminal symbol for the production (as if we
44 * had seen the LHS symbol rather than all the symbols matching the
45 * RHS). This table is indexed by non terminal numbers and indicates
46 * how to make these transitions.
49 * In addition to the method interface, this class maintains a series of
50 * public global variables and flags indicating how misc. parts of the code
51 * and other output is to be produced, and counting things such as number of
52 * conflicts detected (see the source code and public variables below for
55 * This class is "static" (contains only static data and methods).<p>
58 * @version last update: 11/25/95
59 * @author Scott Hudson
62 /* Major externally callable routines here include:
63 symbols - emit the symbol constant class
64 parser - emit the parser class
66 In addition the following major internal routines are provided:
67 emit_package - emit a package declaration
68 emit_action_code - emit the class containing the user's actions
69 emit_production_table - emit declaration and init for the production table
70 do_action_table - emit declaration and init for the action table
71 do_reduce_table - emit declaration and init for the reduce-goto table
73 Finally, this class uses a number of public instance variables to communicate
74 optional parameters and flags used to control how code is generated,
75 as well as to report counts of various things (such as number of conflicts
76 detected). These include:
78 prefix - a prefix string used to prefix names that would
79 otherwise "pollute" someone else's name space.
80 package_name - name of the package emitted code is placed in
81 (or null for an unnamed package.
82 symbol_const_class_name - name of the class containing symbol constants.
83 parser_class_name - name of the class for the resulting parser.
84 action_code - user supplied declarations and other code to be
85 placed in action class.
86 parser_code - user supplied declarations and other code to be
87 placed in parser class.
88 init_code - user supplied code to be executed as the parser
90 scan_code - user supplied code to get the next Symbol.
91 start_production - the start production for the grammar.
92 import_list - list of imports for use with action class.
93 num_conflicts - number of conflicts detected.
94 nowarn - true if we are not to issue warning messages.
95 not_reduced - count of number of productions that never reduce.
96 unused_term - count of unused terminal symbols.
97 unused_non_term - count of unused non terminal symbols.
98 *_time - a series of symbols indicating how long various
99 sub-parts of code generation took (used to produce
100 optional time reports in main).
105 /*-----------------------------------------------------------*/
106 /*--- Constructor(s) ----------------------------------------*/
107 /*-----------------------------------------------------------*/
109 /** Only constructor is private so no instances can be created. */
112 /*-----------------------------------------------------------*/
113 /*--- Static (Class) Variables ------------------------------*/
114 /*-----------------------------------------------------------*/
116 /** The prefix placed on names that pollute someone else's name space. */
117 public static String prefix = "CUP$";
119 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
121 /** Package that the resulting code goes into (null is used for unnamed). */
122 public static String package_name = null;
124 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
126 /** Name of the generated class for symbol constants. */
127 public static String symbol_const_class_name = "sym";
129 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
131 /** Name of the generated parser class. */
132 public static String parser_class_name = "parser";
134 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
136 /** User declarations for direct inclusion in user action class. */
137 public static String action_code = null;
139 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
141 /** User declarations for direct inclusion in parser class. */
142 public static String parser_code = null;
144 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
146 /** User code for user_init() which is called during parser initialization. */
147 public static String init_code = null;
149 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
151 /** User code for scan() which is called to get the next Symbol. */
152 public static String scan_code = null;
154 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
156 /** The start production of the grammar. */
157 public static production start_production = null;
159 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
161 /** List of imports (Strings containing class names) to go with actions. */
162 public static Stack import_list = new Stack();
164 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
166 /** Number of conflict found while building tables. */
167 public static int num_conflicts = 0;
169 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
171 /** Do we skip warnings? */
172 public static boolean nowarn = false;
174 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
176 /** Count of the number on non-reduced productions found. */
177 public static int not_reduced = 0;
179 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
181 /** Count of unused terminals. */
182 public static int unused_term = 0;
184 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
186 /** Count of unused non terminals. */
187 public static int unused_non_term = 0;
189 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
191 /* Timing values used to produce timing report in main.*/
193 /** Time to produce symbol constant class. */
194 public static long symbols_time = 0;
196 /** Time to produce parser class. */
197 public static long parser_time = 0;
199 /** Time to produce action code class. */
200 public static long action_code_time = 0;
202 /** Time to produce the production table. */
203 public static long production_table_time = 0;
205 /** Time to produce the action table. */
206 public static long action_table_time = 0;
208 /** Time to produce the reduce-goto table. */
209 public static long goto_table_time = 0;
212 protected static boolean _lr_values;
214 /** whether or not to emit code for left and right values */
215 public static boolean lr_values() {return _lr_values;}
216 protected static void set_lr_values(boolean b) { _lr_values = b;}
218 /*-----------------------------------------------------------*/
219 /*--- General Methods ---------------------------------------*/
220 /*-----------------------------------------------------------*/
222 /** Build a string with the standard prefix.
223 * @param str string to prefix.
225 protected static String pre(String str) {
226 return prefix + parser_class_name + "$" + str;
229 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
231 /** Emit a package spec if the user wants one.
232 * @param out stream to produce output on.
234 protected static void emit_package(PrintWriter out)
236 /* generate a package spec if we have a name for one */
237 if (package_name != null) {
238 out.println("package " + package_name + ";"); out.println();
242 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
244 /** Emit code for the symbol constant class, optionally including non terms,
245 * if they have been requested.
246 * @param out stream to produce output on.
247 * @param emit_non_terms do we emit constants for non terminals?
248 * @param sym_interface should we emit an interface, rather than a class?
250 public static void symbols(PrintWriter out,
251 boolean emit_non_terms, boolean sym_interface)
255 String class_or_interface = (sym_interface)?"interface":"class";
257 long start_time = System.currentTimeMillis();
261 out.println("//----------------------------------------------------");
262 out.println("// The following code was generated by " +
264 out.println("// " + new Date());
265 out.println("//----------------------------------------------------");
270 out.println("/** CUP generated " + class_or_interface +
271 " containing symbol constants. */");
272 out.println("public " + class_or_interface + " " +
273 symbol_const_class_name + " {");
275 out.println(" /* terminals */");
277 /* walk over the terminals */ /* later might sort these */
278 for (Enumeration e = terminal.all(); e.hasMoreElements(); )
280 term = (terminal)e.nextElement();
282 /* output a constant decl for the terminal */
283 out.println(" public static final int " + term.name() + " = " +
287 /* do the non terminals if they want them (parser doesn't need them) */
291 out.println(" /* non terminals */");
293 /* walk over the non terminals */ /* later might sort these */
294 for (Enumeration e = non_terminal.all(); e.hasMoreElements(); )
296 nt = (non_terminal)e.nextElement();
298 /* output a constant decl for the terminal */
299 out.println(" static final int " + nt.name() + " = " +
308 symbols_time = System.currentTimeMillis() - start_time;
311 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
313 /** Emit code for the non-public class holding the actual action code.
314 * @param out stream to produce output on.
315 * @param start_prod the start production of the grammar.
317 protected static void emit_action_code(PrintWriter out, production start_prod)
318 throws internal_error
320 long start_time = System.currentTimeMillis();
325 "/** Cup generated class to encapsulate user supplied action code.*/"
327 out.println("class " + pre("actions") + " {");
329 /* user supplied code */
330 if (action_code != null)
333 out.println(action_code);
336 /* field for parser object */
337 out.println(" private final "+parser_class_name+" parser;");
341 out.println(" /** Constructor */");
342 out.println(" " + pre("actions") + "("+parser_class_name+" parser) {");
343 out.println(" this.parser = parser;");
346 /* action method head */
348 out.println(" /** Method with the actual generated action code. */");
349 out.println(" public final java_cup.runtime.Symbol " +
350 pre("do_action") + "(");
351 out.println(" int " + pre("act_num,"));
352 out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
353 out.println(" java.util.Stack " + pre("stack,"));
354 out.println(" int " + pre("top)"));
355 out.println(" throws java.lang.Exception");
358 /* declaration of result symbol */
359 /* New declaration!! now return Symbol
361 out.println(" /* Symbol object for return from actions */");
362 out.println(" java_cup.runtime.Symbol " + pre("result") + ";");
365 // hack: divide a production table into halves and generates two methods of switch cases
366 // since we have an issue with Java 64K size limitation.
367 int median=production.number()/2;
368 // divide production table
369 List firsthalf=new ArrayList();
370 List secondhalf=new ArrayList();
371 for(int i=0;i<median;i++){
372 firsthalf.add(production.find(i));
374 for(int i=median;i<production.number();i++){
375 secondhalf.add(production.find(i));
378 // invoke emit_switch_code
379 out.println(" if("+pre("act_num")+" < "+median+" )");
380 out.println(" "+pre("result=")+pre("do_action")+"_1("+ pre("act_num,") +pre("parser,")+ pre("stack,")+ pre("top)")+";");
381 out.println(" else");
382 out.println(" "+pre("result=")+pre("do_action")+"_2("+ pre("act_num,") +pre("parser,") +pre("stack,")+ pre("top)")+";");
385 out.println(" return "+pre("result")+";");
389 emit_switch_code(1,out,start_prod,firsthalf);
390 emit_switch_code(2,out,start_prod,secondhalf);
396 action_code_time = System.currentTimeMillis() - start_time;
399 protected static void emit_switch_code(int funcIdx, PrintWriter out, production start_prod, List prodList) throws internal_error{
402 out.println(" /** Method with the generated switch code. */");
403 out.println(" public final java_cup.runtime.Symbol " +
404 pre("do_action")+"_"+funcIdx + "(");
405 out.println(" int " + pre("act_num,"));
406 out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
407 out.println(" java.util.Stack " + pre("stack,"));
408 out.println(" int " + pre("top)"));
409 out.println(" throws java.lang.Exception");
412 out.println(" /* Symbol object for return from actions */");
413 out.println(" java_cup.runtime.Symbol " + pre("result") + ";");
419 out.println(" /* select the action based on the action number */");
420 out.println(" switch (" + pre("act_num") + ")");
423 /* emit action code for each production as a separate case */
424 for (Iterator iterator = prodList.iterator(); iterator.hasNext();) {
425 prod = (production) iterator.next();
428 out.println(" /*. . . . . . . . . . . . . . . . . . . .*/");
429 out.println(" case " + prod.index() + ": // " +
430 prod.to_simple_string());
432 /* give them their own block to work in */
435 /* create the result symbol */
436 /*make the variable RESULT which will point to the new Symbol (see below)
437 and be changed by action code
439 out.println(" " + prod.lhs().the_symbol().stack_type() +
442 /* Add code to propagate RESULT assignments that occur in
443 * action code embedded in a production (ie, non-rightmost
444 * action code). 24-Mar-1998 CSA
446 for (int i=0; i<prod.rhs_length(); i++) {
447 // only interested in non-terminal symbols.
448 if (!(prod.rhs(i) instanceof symbol_part)) continue;
449 symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
450 if (!(s instanceof non_terminal)) continue;
451 // skip this non-terminal unless it corresponds to
452 // an embedded action production.
453 if (((non_terminal)s).is_embedded_action == false) continue;
454 // OK, it fits. Make a conditional assignment to RESULT.
455 int index = prod.rhs_length() - i - 1; // last rhs is on top.
456 out.println(" " + "// propagate RESULT from " +
458 out.println(" " + "if ( " +
459 "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
460 + emit.pre("top") + "-" + index + ")).value != null )");
461 out.println(" " + "RESULT = " +
462 "(" + prod.lhs().the_symbol().stack_type() + ") " +
463 "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
464 + emit.pre("top") + "-" + index + ")).value;");
467 /* if there is an action string, emit it */
468 if (prod.action() != null && prod.action().code_string() != null &&
469 !prod.action().equals(""))
470 out.println(prod.action().code_string());
472 /* here we have the left and right values being propagated.
473 must make this a command line option.
476 /* Create the code that assigns the left and right values of
477 the new Symbol that the production is reducing to */
478 if (emit.lr_values()) {
480 String leftstring, rightstring;
482 rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
483 emit.pre("top") + "-" + roffset + ")).right";
484 if (prod.rhs_length() == 0)
485 leftstring = rightstring;
487 loffset = prod.rhs_length() - 1;
488 leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
489 emit.pre("top") + "-" + loffset + ")).left";
491 out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
492 prod.lhs().the_symbol().index() + "/*" +
493 prod.lhs().the_symbol().name() + "*/" +
494 ", " + leftstring + ", " + rightstring + ", RESULT);");
496 out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
497 prod.lhs().the_symbol().index() + "/*" +
498 prod.lhs().the_symbol().name() + "*/" +
502 /* end of their block */
505 /* if this was the start production, do action for accept */
506 if (prod == start_prod)
508 out.println(" /* ACCEPT */");
509 out.println(" " + pre("parser") + ".done_parsing();");
512 /* code to return lhs symbol */
513 out.println(" return " + pre("result") + ";");
518 out.println(" /* . . . . . .*/");
519 out.println(" default:");
520 out.println(" throw new Exception(");
521 out.println(" \"Invalid action number found in " +
522 "internal parse table\");");
531 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
533 /** Emit the production table.
534 * @param out stream to produce output on.
536 protected static void emit_production_table(PrintWriter out)
538 production all_prods[];
541 long start_time = System.currentTimeMillis();
543 /* collect up the productions in order */
544 all_prods = new production[production.number()];
545 for (Enumeration p = production.all(); p.hasMoreElements(); )
547 prod = (production)p.nextElement();
548 all_prods[prod.index()] = prod;
552 short[][] prod_table = new short[production.number()][2];
553 for (int i = 0; i<production.number(); i++)
556 // { lhs symbol , rhs size }
557 prod_table[i][0] = (short) prod.lhs().the_symbol().index();
558 prod_table[i][1] = (short) prod.rhs_length();
560 /* do the top of the table */
562 out.println(" /** Production table. */");
563 out.println(" protected static final short _production_table[][] = ");
564 out.print (" unpackFromStrings(");
565 do_table_as_string(out, prod_table);
568 /* do the public accessor method */
570 out.println(" /** Access to production table. */");
571 out.println(" public short[][] production_table() " +
572 "{return _production_table;}");
574 production_table_time = System.currentTimeMillis() - start_time;
577 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
579 /** Emit the action table.
580 * @param out stream to produce output on.
581 * @param act_tab the internal representation of the action table.
582 * @param compact_reduces do we use the most frequent reduce as default?
584 protected static void do_action_table(
586 parse_action_table act_tab,
587 boolean compact_reduces)
588 throws internal_error
590 parse_action_row row;
594 long start_time = System.currentTimeMillis();
596 /* collect values for the action table */
597 short[][] action_table = new short[act_tab.num_states()][];
598 /* do each state (row) of the action table */
599 for (int i = 0; i < act_tab.num_states(); i++)
602 row = act_tab.under_state[i];
604 /* determine the default for the row */
606 row.compute_default();
608 row.default_reduce = -1;
610 /* make temporary table for the row. */
611 short[] temp_table = new short[2*row.size()];
615 for (int j = 0; j < row.size(); j++)
617 /* extract the action from the table */
618 act = row.under_term[j];
620 /* skip error entries these are all defaulted out */
621 if (act.kind() != parse_action.ERROR)
623 /* first put in the symbol index, then the actual entry */
625 /* shifts get positive entries of state number + 1 */
626 if (act.kind() == parse_action.SHIFT)
629 temp_table[nentries++] = (short) j;
630 temp_table[nentries++] = (short)
631 (((shift_action)act).shift_to().index() + 1);
634 /* reduce actions get negated entries of production# + 1 */
635 else if (act.kind() == parse_action.REDUCE)
637 /* if its the default entry let it get defaulted out */
638 red = ((reduce_action)act).reduce_with().index();
639 if (red != row.default_reduce) {
641 temp_table[nentries++] = (short) j;
642 temp_table[nentries++] = (short) (-(red+1));
644 } else if (act.kind() == parse_action.NONASSOC)
646 /* do nothing, since we just want a syntax error */
648 /* shouldn't be anything else */
650 throw new internal_error("Unrecognized action code " +
651 act.kind() + " found in parse table");
655 /* now we know how big to make the row */
656 action_table[i] = new short[nentries + 2];
657 System.arraycopy(temp_table, 0, action_table[i], 0, nentries);
659 /* finish off the row with a default entry */
660 action_table[i][nentries++] = -1;
661 if (row.default_reduce != -1)
662 action_table[i][nentries++] = (short) (-(row.default_reduce+1));
664 action_table[i][nentries++] = 0;
667 /* finish off the init of the table */
669 out.println(" /** Parse-action table. */");
670 out.println(" protected static final short[][] _action_table = ");
671 out.print (" unpackFromStrings(");
672 do_table_as_string(out, action_table);
675 /* do the public accessor method */
677 out.println(" /** Access to parse-action table. */");
678 out.println(" public short[][] action_table() {return _action_table;}");
680 action_table_time = System.currentTimeMillis() - start_time;
683 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
685 /** Emit the reduce-goto table.
686 * @param out stream to produce output on.
687 * @param red_tab the internal representation of the reduce-goto table.
689 protected static void do_reduce_table(
691 parse_reduce_table red_tab)
696 long start_time = System.currentTimeMillis();
698 /* collect values for reduce-goto table */
699 short[][] reduce_goto_table = new short[red_tab.num_states()][];
700 /* do each row of the reduce-goto table */
701 for (int i=0; i<red_tab.num_states(); i++)
703 /* make temporary table for the row. */
704 short[] temp_table = new short[2*red_tab.under_state[i].size()];
706 /* do each entry in the row */
707 for (int j=0; j<red_tab.under_state[i].size(); j++)
710 goto_st = red_tab.under_state[i].under_non_term[j];
712 /* if we have none, skip it */
715 /* make entries for the index and the value */
716 temp_table[nentries++] = (short) j;
717 temp_table[nentries++] = (short) goto_st.index();
720 /* now we know how big to make the row. */
721 reduce_goto_table[i] = new short[nentries+2];
722 System.arraycopy(temp_table, 0, reduce_goto_table[i], 0, nentries);
724 /* end row with default value */
725 reduce_goto_table[i][nentries++] = -1;
726 reduce_goto_table[i][nentries++] = -1;
729 /* emit the table. */
731 out.println(" /** <code>reduce_goto</code> table. */");
732 out.println(" protected static final short[][] _reduce_table = ");
733 out.print (" unpackFromStrings(");
734 do_table_as_string(out, reduce_goto_table);
737 /* do the public accessor method */
739 out.println(" /** Access to <code>reduce_goto</code> table. */");
740 out.println(" public short[][] reduce_table() {return _reduce_table;}");
743 goto_table_time = System.currentTimeMillis() - start_time;
746 // print a string array encoding the given short[][] array.
747 protected static void do_table_as_string(PrintWriter out, short[][] sa) {
748 out.println("new String[] {");
750 int nchar=0, nbytes=0;
751 nbytes+=do_escaped(out, (char)(sa.length>>16));
752 nchar =do_newline(out, nchar, nbytes);
753 nbytes+=do_escaped(out, (char)(sa.length&0xFFFF));
754 nchar =do_newline(out, nchar, nbytes);
755 for (int i=0; i<sa.length; i++) {
756 nbytes+=do_escaped(out, (char)(sa[i].length>>16));
757 nchar =do_newline(out, nchar, nbytes);
758 nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF));
759 nchar =do_newline(out, nchar, nbytes);
760 for (int j=0; j<sa[i].length; j++) {
761 // contents of string are (value+2) to allow for common -1, 0 cases
762 // (UTF-8 encoding is most efficient for 0<c<0x80)
763 nbytes+=do_escaped(out, (char)(2+sa[i][j]));
764 nchar =do_newline(out, nchar, nbytes);
769 // split string if it is very long; start new line occasionally for neatness
770 protected static int do_newline(PrintWriter out, int nchar, int nbytes) {
771 if (nbytes > 65500) { out.println("\", "); out.print(" \""); }
772 else if (nchar > 11) { out.println("\" +"); out.print(" \""); }
776 // output an escape sequence for the given character code.
777 protected static int do_escaped(PrintWriter out, char c) {
778 StringBuffer escape = new StringBuffer();
780 escape.append(Integer.toOctalString(c));
781 while(escape.length() < 3) escape.insert(0, '0');
783 escape.append(Integer.toHexString(c));
784 while(escape.length() < 4) escape.insert(0, '0');
785 escape.insert(0, 'u');
787 escape.insert(0, '\\');
788 out.print(escape.toString());
790 // return number of bytes this takes up in UTF-8 encoding.
791 if (c == 0) return 2;
792 if (c >= 0x01 && c <= 0x7F) return 1;
793 if (c >= 0x80 && c <= 0x7FF) return 2;
797 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
799 /** Emit the parser subclass with embedded tables.
800 * @param out stream to produce output on.
801 * @param action_table internal representation of the action table.
802 * @param reduce_table internal representation of the reduce-goto table.
803 * @param start_st start state of the parse machine.
804 * @param start_prod start production of the grammar.
805 * @param compact_reduces do we use most frequent reduce as default?
806 * @param suppress_scanner should scanner be suppressed for compatibility?
808 public static void parser(
810 parse_action_table action_table,
811 parse_reduce_table reduce_table,
813 production start_prod,
814 boolean compact_reduces,
815 boolean suppress_scanner)
816 throws internal_error
818 long start_time = System.currentTimeMillis();
822 out.println("//----------------------------------------------------");
823 out.println("// The following code was generated by " +
825 out.println("// " + new Date());
826 out.println("//----------------------------------------------------");
830 /* user supplied imports */
831 for (int i = 0; i < import_list.size(); i++)
832 out.println("import " + import_list.elementAt(i) + ";");
836 out.println("/** "+version.title_str+" generated parser.");
837 out.println(" * @version " + new Date());
839 out.println("public class " + parser_class_name +
840 " extends java_cup.runtime.lr_parser {");
842 /* constructors [CSA/davidm, 24-jul-99] */
844 out.println(" /** Default constructor. */");
845 out.println(" public " + parser_class_name + "() {super();}");
846 if (!suppress_scanner) {
848 out.println(" /** Constructor which sets the default scanner. */");
849 out.println(" public " + parser_class_name +
850 "(java_cup.runtime.Scanner s) {super(s);}");
853 /* emit the various tables */
854 emit_production_table(out);
855 do_action_table(out, action_table, compact_reduces);
856 do_reduce_table(out, reduce_table);
858 /* instance of the action encapsulation class */
859 out.println(" /** Instance of action encapsulation class. */");
860 out.println(" protected " + pre("actions") + " action_obj;");
863 /* action object initializer */
864 out.println(" /** Action encapsulation object initializer. */");
865 out.println(" protected void init_actions()");
867 out.println(" action_obj = new " + pre("actions") + "(this);");
871 /* access to action code */
872 out.println(" /** Invoke a user supplied parse action. */");
873 out.println(" public java_cup.runtime.Symbol do_action(");
874 out.println(" int act_num,");
875 out.println(" java_cup.runtime.lr_parser parser,");
876 out.println(" java.util.Stack stack,");
877 out.println(" int top)");
878 out.println(" throws java.lang.Exception");
880 out.println(" /* call code in generated class */");
881 out.println(" return action_obj." + pre("do_action(") +
882 "act_num, parser, stack, top);");
887 /* method to tell the parser about the start state */
888 out.println(" /** Indicates start state. */");
889 out.println(" public int start_state() {return " + start_st + ";}");
891 /* method to indicate start production */
892 out.println(" /** Indicates start production. */");
893 out.println(" public int start_production() {return " +
894 start_production.index() + ";}");
897 /* methods to indicate EOF and error symbol indexes */
898 out.println(" /** <code>EOF</code> Symbol index. */");
899 out.println(" public int EOF_sym() {return " + terminal.EOF.index() +
902 out.println(" /** <code>error</code> Symbol index. */");
903 out.println(" public int error_sym() {return " + terminal.error.index() +
907 /* user supplied code for user_init() */
908 if (init_code != null)
911 out.println(" /** User initialization code. */");
912 out.println(" public void user_init() throws java.lang.Exception");
914 out.println(init_code);
918 /* user supplied code for scan */
919 if (scan_code != null)
922 out.println(" /** Scan to get the next Symbol. */");
923 out.println(" public java_cup.runtime.Symbol scan()");
924 out.println(" throws java.lang.Exception");
926 out.println(scan_code);
930 /* user supplied code */
931 if (parser_code != null)
934 out.println(parser_code);
940 /* put out the action code class */
941 emit_action_code(out, start_prod);
943 parser_time = System.currentTimeMillis() - start_time;
946 /*-----------------------------------------------------------*/