4 import java.util.Enumeration;
7 /** This class serves as the main driver for the JavaCup system.
8 * It accepts user options and coordinates overall control flow.
9 * The main flow of control includes the following activities:
11 * <li> Parse user supplied arguments and options.
12 * <li> Open output files.
13 * <li> Parse the specification from standard input.
14 * <li> Check for unused terminals, non-terminals, and productions.
15 * <li> Build the state machine, tables, etc.
16 * <li> Output the generated code.
17 * <li> Close output files.
18 * <li> Print a summary if requested.
21 * Options to the main program include: <dl>
23 * <dd> specify package generated classes go in [default none]
25 * <dd> specify parser class name [default "parser"]
27 * <dd> specify name for symbol constant class [default "sym"]
29 * <dd> emit symbol constant <i>interface</i>, rather than class
31 * <dd> put non terminals in symbol constant class
33 * <dd> number of conflicts expected/allowed [default 0]
35 * <dd> compact tables by defaulting to most frequent reduce
37 * <dd> don't warn about useless productions, etc.
39 * <dd> don't print the usual summary of parse states, etc.
41 * <dd> print messages to indicate progress of the system
43 * <dd> print time usage summary
45 * <dd> produce a dump of the symbols and grammar
47 * <dd> produce a dump of parse state machine
49 * <dd> produce a dump of the parse tables
51 * <dd> produce a dump of all of the above
53 * <dd> turn on debugging messages within JavaCup
55 * <dd> don't generate the positions code
57 * <dd> don't refer to java_cup.runtime.Scanner in the parser
58 * (for compatibility with old runtimes)
60 * <dd> print version information for JavaCUP and halt.
63 * @version last updated: 7/3/96
64 * @author Frank Flannery
69 /*-----------------------------------------------------------*/
70 /*--- Constructor(s) ----------------------------------------*/
71 /*-----------------------------------------------------------*/
72 /** Only constructor is private, so we do not allocate any instances of this
76 /*-------------------------*/
77 /* Options set by the user */
78 /*-------------------------*/
79 /** User option -- do we print progress messages. */
80 protected static boolean print_progress = true;
81 /** User option -- do we produce a dump of the state machine */
82 protected static boolean opt_dump_states = false;
83 /** User option -- do we produce a dump of the parse tables */
84 protected static boolean opt_dump_tables = false;
85 /** User option -- do we produce a dump of the grammar */
86 protected static boolean opt_dump_grammar = false;
87 /** User option -- do we show timing information as a part of the summary */
88 protected static boolean opt_show_timing = false;
89 /** User option -- do we run produce extra debugging messages */
90 protected static boolean opt_do_debug = false;
91 /** User option -- do we compact tables by making most common reduce the
93 protected static boolean opt_compact_red = false;
94 /** User option -- should we include non terminal symbol numbers in the
95 symbol constant class. */
96 protected static boolean include_non_terms = false;
97 /** User option -- do not print a summary. */
98 protected static boolean no_summary = false;
99 /** User option -- number of conflicts to expect */
100 protected static int expect_conflicts = 0;
102 /* frankf added this 6/18/96 */
103 /** User option -- should generator generate code for left/right values? */
104 protected static boolean lr_values = true;
106 /** User option -- should symbols be put in a class or an interface? [CSA]*/
107 protected static boolean sym_interface = false;
109 /** User option -- should generator suppress references to
110 * java_cup.runtime.Scanner for compatibility with old runtimes? */
111 protected static boolean suppress_scanner = false;
113 /*----------------------------------------------------------------------*/
114 /* Timing data (not all of these time intervals are mutually exclusive) */
115 /*----------------------------------------------------------------------*/
116 /** Timing data -- when did we start */
117 protected static long start_time = 0;
118 /** Timing data -- when did we end preliminaries */
119 protected static long prelim_end = 0;
120 /** Timing data -- when did we end parsing */
121 protected static long parse_end = 0;
122 /** Timing data -- when did we end checking */
123 protected static long check_end = 0;
124 /** Timing data -- when did we end dumping */
125 protected static long dump_end = 0;
126 /** Timing data -- when did we end state and table building */
127 protected static long build_end = 0;
128 /** Timing data -- when did we end nullability calculation */
129 protected static long nullability_end = 0;
130 /** Timing data -- when did we end first set calculation */
131 protected static long first_end = 0;
132 /** Timing data -- when did we end state machine construction */
133 protected static long machine_end = 0;
134 /** Timing data -- when did we end table construction */
135 protected static long table_end = 0;
136 /** Timing data -- when did we end checking for non-reduced productions */
137 protected static long reduce_check_end = 0;
138 /** Timing data -- when did we finish emitting code */
139 protected static long emit_end = 0;
140 /** Timing data -- when were we completely done */
141 protected static long final_time = 0;
143 /* Additional timing information is also collected in emit */
145 /*-----------------------------------------------------------*/
146 /*--- Main Program ------------------------------------------*/
147 /*-----------------------------------------------------------*/
149 /** The main driver for the system.
150 * @param argv an array of strings containing command line arguments.
152 public static void main(String argv[])
153 throws internal_error, java.io.IOException, java.lang.Exception
155 boolean did_output = false;
157 start_time = System.currentTimeMillis();
159 /* process user options and arguments */
163 hackish, yes, but works */
164 emit.set_lr_values(lr_values);
165 /* open output files */
166 if (print_progress) System.err.println("Opening files...");
167 /* use a buffered version of standard input */
168 input_file = new BufferedInputStream(System.in);
170 prelim_end = System.currentTimeMillis();
172 /* parse spec into internal data structures */
174 System.err.println("Parsing specification from standard input...");
175 parse_grammar_spec();
177 parse_end = System.currentTimeMillis();
179 /* don't proceed unless we are error free */
180 if (lexer.error_count == 0)
182 /* check for unused bits */
183 if (print_progress) System.err.println("Checking specification...");
186 check_end = System.currentTimeMillis();
188 /* build the state machine and parse tables */
189 if (print_progress) System.err.println("Building parse tables...");
192 build_end = System.currentTimeMillis();
194 /* output the generated code, if # of conflicts permits */
195 if (lexer.error_count != 0) {
196 // conflicts! don't emit code, don't dump tables.
197 opt_dump_tables = false;
198 } else { // everything's okay, emit parser.
199 if (print_progress) System.err.println("Writing parser...");
205 /* fix up the times to make the summary easier */
206 emit_end = System.currentTimeMillis();
208 /* do requested dumps */
209 if (opt_dump_grammar) dump_grammar();
210 if (opt_dump_states) dump_machine();
211 if (opt_dump_tables) dump_tables();
213 dump_end = System.currentTimeMillis();
215 /* close input/output files */
216 if (print_progress) System.err.println("Closing files...");
219 /* produce a summary if desired */
220 if (!no_summary) emit_summary(did_output);
222 /* If there were errors during the run,
223 * exit with non-zero status (makefile-friendliness). --CSA */
224 if (lexer.error_count != 0)
228 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
230 /** Print a "usage message" that described possible command line options,
232 * @param message a specific error message to preface the usage message by.
234 protected static void usage(String message)
236 System.err.println();
237 System.err.println(message);
238 System.err.println();
240 "Usage: " + version.program_name + " [options] [filename]\n" +
241 " and expects a specification file on standard input if no filename is given.\n" +
242 " Legal options include:\n" +
243 " -package name specify package generated classes go in [default none]\n" +
244 " -parser name specify parser class name [default \"parser\"]\n" +
245 " -symbols name specify name for symbol constant class [default \"sym\"]\n"+
246 " -interface put symbols in an interface, rather than a class\n" +
247 " -nonterms put non terminals in symbol constant class\n" +
248 " -expect # number of conflicts expected/allowed [default 0]\n" +
249 " -compact_red compact tables by defaulting to most frequent reduce\n" +
250 " -nowarn don't warn about useless productions, etc.\n" +
251 " -nosummary don't print the usual summary of parse states, etc.\n" +
252 " -nopositions don't propagate the left and right token position values\n" +
253 " -noscanner don't refer to java_cup.runtime.Scanner\n" +
254 " -progress print messages to indicate progress of the system\n" +
255 " -time print time usage summary\n" +
256 " -dump_grammar produce a human readable dump of the symbols and grammar\n"+
257 " -dump_states produce a dump of parse state machine\n"+
258 " -dump_tables produce a dump of the parse tables\n"+
259 " -dump produce a dump of all of the above\n"+
260 " -version print the version information for CUP and exit\n"
265 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
267 /** Parse command line options and arguments to set various user-option
268 * flags and variables.
269 * @param argv the command line arguments to be parsed.
271 protected static void parse_args(String argv[])
273 int len = argv.length;
276 /* parse the options */
277 for (i=0; i<len; i++)
279 /* try to get the various options */
280 if (argv[i].equals("-package"))
282 /* must have an arg */
283 if (++i >= len || argv[i].startsWith("-") ||
284 argv[i].endsWith(".cup"))
285 usage("-package must have a name argument");
287 /* record the name */
288 emit.package_name = argv[i];
290 else if (argv[i].equals("-parser"))
292 /* must have an arg */
293 if (++i >= len || argv[i].startsWith("-") ||
294 argv[i].endsWith(".cup"))
295 usage("-parser must have a name argument");
297 /* record the name */
298 emit.parser_class_name = argv[i];
300 else if (argv[i].equals("-symbols"))
302 /* must have an arg */
303 if (++i >= len || argv[i].startsWith("-") ||
304 argv[i].endsWith(".cup"))
305 usage("-symbols must have a name argument");
307 /* record the name */
308 emit.symbol_const_class_name = argv[i];
310 else if (argv[i].equals("-nonterms"))
312 include_non_terms = true;
314 else if (argv[i].equals("-expect"))
316 /* must have an arg */
317 if (++i >= len || argv[i].startsWith("-") ||
318 argv[i].endsWith(".cup"))
319 usage("-expect must have a name argument");
321 /* record the number */
323 expect_conflicts = Integer.parseInt(argv[i]);
324 } catch (NumberFormatException e) {
325 usage("-expect must be followed by a decimal integer");
328 else if (argv[i].equals("-compact_red")) opt_compact_red = true;
329 else if (argv[i].equals("-nosummary")) no_summary = true;
330 else if (argv[i].equals("-nowarn")) emit.nowarn = true;
331 else if (argv[i].equals("-dump_states")) opt_dump_states = true;
332 else if (argv[i].equals("-dump_tables")) opt_dump_tables = true;
333 else if (argv[i].equals("-progress")) print_progress = true;
334 else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
335 else if (argv[i].equals("-dump"))
336 opt_dump_states = opt_dump_tables = opt_dump_grammar = true;
337 else if (argv[i].equals("-time")) opt_show_timing = true;
338 else if (argv[i].equals("-debug")) opt_do_debug = true;
340 else if (argv[i].equals("-nopositions")) lr_values = false;
342 else if (argv[i].equals("-interface")) sym_interface = true;
343 /* CSA 23-Jul-1999 */
344 else if (argv[i].equals("-noscanner")) suppress_scanner = true;
345 /* CSA 23-Jul-1999 */
346 else if (argv[i].equals("-version")) {
347 System.out.println(version.title_str);
350 /* CSA 24-Jul-1999; suggestion by Jean Vaucher */
351 else if (!argv[i].startsWith("-") && i==len-1) {
352 /* use input from file. */
354 System.setIn(new FileInputStream(argv[i]));
355 } catch (java.io.FileNotFoundException e) {
356 usage("Unable to open \"" + argv[i] +"\" for input");
361 usage("Unrecognized option \"" + argv[i] + "\"");
366 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
372 /** Input file. This is a buffered version of System.in. */
373 protected static BufferedInputStream input_file;
375 /** Output file for the parser class. */
376 protected static PrintWriter parser_class_file;
378 /** Output file for the symbol constant class. */
379 protected static PrintWriter symbol_class_file;
381 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
383 /** Open various files used by the system. */
384 protected static void open_files()
389 /* open each of the output files */
392 out_name = emit.parser_class_name + ".java";
393 fil = new File(out_name);
395 parser_class_file = new PrintWriter(
396 new BufferedOutputStream(new FileOutputStream(fil), 4096));
397 } catch(Exception e) {
398 System.err.println("Can't open \"" + out_name + "\" for output");
402 /* symbol constants class */
403 out_name = emit.symbol_const_class_name + ".java";
404 fil = new File(out_name);
406 symbol_class_file = new PrintWriter(
407 new BufferedOutputStream(new FileOutputStream(fil), 4096));
408 } catch(Exception e) {
409 System.err.println("Can't open \"" + out_name + "\" for output");
414 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
416 /** Close various files used by the system. */
417 protected static void close_files() throws java.io.IOException
419 if (input_file != null) input_file.close();
420 if (parser_class_file != null) parser_class_file.close();
421 if (symbol_class_file != null) symbol_class_file.close();
424 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
426 /** Parse the grammar specification from standard input. This produces
427 * sets of terminal, non-terminals, and productions which can be accessed
428 * via static variables of the respective classes, as well as the setting
429 * of various variables (mostly in the emit class) for small user supplied
430 * items such as the code to scan with.
432 protected static void parse_grammar_spec() throws java.lang.Exception
436 /* create a parser and parse with it */
437 parser_obj = new parser();
440 parser_obj.debug_parse();
443 } catch (Exception e)
445 /* something threw an exception. catch it and emit a message so we
446 have a line number to work with, then re-throw it */
447 lexer.emit_error("Internal error: Unexpected exception");
452 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
454 /** Check for unused symbols. Unreduced productions get checked when
455 * tables are created.
457 protected static void check_unused()
462 /* check for unused terminals */
463 for (Enumeration t = terminal.all(); t.hasMoreElements(); )
465 term = (terminal)t.nextElement();
467 /* don't issue a message for EOF */
468 if (term == terminal.EOF) continue;
471 if (term == terminal.error) continue;
473 /* is this one unused */
474 if (term.use_count() == 0)
476 /* count it and warn if we are doing warnings */
480 System.err.println("Warning: Terminal \"" + term.name() +
481 "\" was declared but never used");
482 lexer.warning_count++;
487 /* check for unused non terminals */
488 for (Enumeration n = non_terminal.all(); n.hasMoreElements(); )
490 nt = (non_terminal)n.nextElement();
492 /* is this one unused */
493 if (nt.use_count() == 0)
495 /* count and warn if we are doing warnings */
499 System.err.println("Warning: Non terminal \"" + nt.name() +
500 "\" was declared but never used");
501 lexer.warning_count++;
508 /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
509 /* . . Internal Results of Generating the Parser . .*/
510 /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
512 /** Start state in the overall state machine. */
513 protected static lalr_state start_state;
515 /** Resulting parse action table. */
516 protected static parse_action_table action_table;
518 /** Resulting reduce-goto table. */
519 protected static parse_reduce_table reduce_table;
521 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
523 /** Build the (internal) parser from the previously parsed specification.
525 * <li> Computing nullability of non-terminals.
526 * <li> Computing first sets of non-terminals and productions.
527 * <li> Building the viable prefix recognizer machine.
528 * <li> Filling in the (internal) parse tables.
529 * <li> Checking for unreduced productions.
532 protected static void build_parser() throws internal_error
534 /* compute nullability of all non terminals */
535 if (opt_do_debug || print_progress)
536 System.err.println(" Computing non-terminal nullability...");
537 non_terminal.compute_nullability();
539 nullability_end = System.currentTimeMillis();
541 /* compute first sets of all non terminals */
542 if (opt_do_debug || print_progress)
543 System.err.println(" Computing first sets...");
544 non_terminal.compute_first_sets();
546 first_end = System.currentTimeMillis();
548 /* build the LR viable prefix recognition machine */
549 if (opt_do_debug || print_progress)
550 System.err.println(" Building state machine...");
551 start_state = lalr_state.build_machine(emit.start_production);
553 machine_end = System.currentTimeMillis();
555 /* build the LR parser action and reduce-goto tables */
556 if (opt_do_debug || print_progress)
557 System.err.println(" Filling in tables...");
558 action_table = new parse_action_table();
559 reduce_table = new parse_reduce_table();
560 for (Enumeration st = lalr_state.all(); st.hasMoreElements(); )
562 lalr_state lst = (lalr_state)st.nextElement();
563 lst.build_table_entries(
564 action_table, reduce_table);
567 table_end = System.currentTimeMillis();
569 /* check and warn for non-reduced productions */
570 if (opt_do_debug || print_progress)
571 System.err.println(" Checking for non-reduced productions...");
572 action_table.check_reductions();
574 reduce_check_end = System.currentTimeMillis();
576 /* if we have more conflicts than we expected issue a message and die */
577 if (emit.num_conflicts > expect_conflicts)
579 System.err.println("*** More conflicts encountered than expected " +
580 "-- parser generation aborted");
581 lexer.error_count++; // indicate the problem.
582 // we'll die on return, after clean up.
586 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
588 /** Call the emit routines necessary to write out the generated parser. */
589 protected static void emit_parser() throws internal_error
591 emit.symbols(symbol_class_file, include_non_terms, sym_interface);
592 emit.parser(parser_class_file, action_table, reduce_table,
593 start_state.index(), emit.start_production, opt_compact_red,
597 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
599 /** Helper routine to optionally return a plural or non-plural ending.
600 * @param val the numerical value determining plurality.
602 protected static String plural(int val)
610 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
612 /** Emit a long summary message to standard error (System.err) which
613 * summarizes what was found in the specification, how many states were
614 * produced, how many conflicts were found, etc. A detailed timing
615 * summary is also produced if it was requested by the user.
616 * @param output_produced did the system get far enough to generate code.
618 protected static void emit_summary(boolean output_produced)
620 final_time = System.currentTimeMillis();
622 if (no_summary) return;
624 System.err.println("------- " + version.title_str +
625 " Parser Generation Summary -------");
627 /* error and warning count */
628 System.err.println(" " + lexer.error_count + " error" +
629 plural(lexer.error_count) + " and " + lexer.warning_count +
630 " warning" + plural(lexer.warning_count));
633 System.err.print(" " + terminal.number() + " terminal" +
634 plural(terminal.number()) + ", ");
635 System.err.print(non_terminal.number() + " non-terminal" +
636 plural(non_terminal.number()) + ", and ");
637 System.err.println(production.number() + " production" +
638 plural(production.number()) + " declared, ");
639 System.err.println(" producing " + lalr_state.number() +
640 " unique parse states.");
643 System.err.println(" " + emit.unused_term + " terminal" +
644 plural(emit.unused_term) + " declared but not used.");
645 System.err.println(" " + emit.unused_non_term + " non-terminal" +
646 plural(emit.unused_term) + " declared but not used.");
648 /* productions that didn't reduce */
649 System.err.println(" " + emit.not_reduced + " production" +
650 plural(emit.not_reduced) + " never reduced.");
653 System.err.println(" " + emit.num_conflicts + " conflict" +
654 plural(emit.num_conflicts) + " detected" +
655 " (" + expect_conflicts + " expected).");
659 System.err.println(" Code written to \"" + emit.parser_class_name +
660 ".java\", and \"" + emit.symbol_const_class_name + ".java\".");
662 System.err.println(" No code produced.");
664 if (opt_show_timing) show_times();
667 "---------------------------------------------------- (" +
668 version.version_str + ")");
671 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
673 /** Produce the optional timing summary as part of an overall summary. */
674 protected static void show_times()
676 long total_time = final_time - start_time;
678 System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
679 System.err.println(" Timing Summary");
680 System.err.println(" Total time "
681 + timestr(final_time-start_time, total_time));
682 System.err.println(" Startup "
683 + timestr(prelim_end-start_time, total_time));
684 System.err.println(" Parse "
685 + timestr(parse_end-prelim_end, total_time) );
687 System.err.println(" Checking "
688 + timestr(check_end-parse_end, total_time));
689 if (check_end != 0 && build_end != 0)
690 System.err.println(" Parser Build "
691 + timestr(build_end-check_end, total_time));
692 if (nullability_end != 0 && check_end != 0)
693 System.err.println(" Nullability "
694 + timestr(nullability_end-check_end, total_time));
695 if (first_end != 0 && nullability_end != 0)
696 System.err.println(" First sets "
697 + timestr(first_end-nullability_end, total_time));
698 if (machine_end != 0 && first_end != 0)
699 System.err.println(" State build "
700 + timestr(machine_end-first_end, total_time));
701 if (table_end != 0 && machine_end != 0)
702 System.err.println(" Table build "
703 + timestr(table_end-machine_end, total_time));
704 if (reduce_check_end != 0 && table_end != 0)
705 System.err.println(" Checking "
706 + timestr(reduce_check_end-table_end, total_time));
707 if (emit_end != 0 && build_end != 0)
708 System.err.println(" Code Output "
709 + timestr(emit_end-build_end, total_time));
710 if (emit.symbols_time != 0)
711 System.err.println(" Symbols "
712 + timestr(emit.symbols_time, total_time));
713 if (emit.parser_time != 0)
714 System.err.println(" Parser class "
715 + timestr(emit.parser_time, total_time));
716 if (emit.action_code_time != 0)
717 System.err.println(" Actions "
718 + timestr(emit.action_code_time, total_time));
719 if (emit.production_table_time != 0)
720 System.err.println(" Prod table "
721 + timestr(emit.production_table_time, total_time));
722 if (emit.action_table_time != 0)
723 System.err.println(" Action tab "
724 + timestr(emit.action_table_time, total_time));
725 if (emit.goto_table_time != 0)
726 System.err.println(" Reduce tab "
727 + timestr(emit.goto_table_time, total_time));
729 System.err.println(" Dump Output "
730 + timestr(dump_end-emit_end, total_time));
733 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
735 /** Helper routine to format a decimal based display of seconds and
736 * percentage of total time given counts of milliseconds. Note: this
737 * is broken for use with some instances of negative time (since we don't
738 * use any negative time here, we let if be for now).
739 * @param time_val the value being formatted (in ms).
740 * @param total_time total time percentages are calculated against (in ms).
742 protected static String timestr(long time_val, long total_time)
750 /* work with positives only */
752 if (neg) time_val = -time_val;
754 /* pull out seconds and ms */
755 ms = time_val % 1000;
756 sec = time_val / 1000;
758 /* construct a pad to blank fill seconds out to 4 places */
768 /* calculate 10 times the percentage of total */
769 percent10 = (time_val*1000)/total_time;
771 /* build and return the output string */
772 return (neg ? "-" : "") + pad + sec + "." +
773 ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" +
774 " (" + percent10/10 + "." + percent10%10 + "%)";
777 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
779 /** Produce a human readable dump of the grammar. */
780 public static void dump_grammar() throws internal_error
782 System.err.println("===== Terminals =====");
783 for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
785 System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
786 if ((cnt+1) % 5 == 0) System.err.println();
788 System.err.println();
789 System.err.println();
791 System.err.println("===== Non terminals =====");
792 for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
794 System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
795 if ((cnt+1) % 5 == 0) System.err.println();
797 System.err.println();
798 System.err.println();
801 System.err.println("===== Productions =====");
802 for (int pidx=0; pidx < production.number(); pidx++)
804 production prod = production.find(pidx);
805 System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= ");
806 for (int i=0; i<prod.rhs_length(); i++)
807 if (prod.rhs(i).is_action())
808 System.err.print("{action} ");
811 ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
812 System.err.println();
814 System.err.println();
817 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
819 /** Produce a (semi-) human readable dump of the complete viable prefix
820 * recognition state machine.
822 public static void dump_machine()
824 lalr_state ordered[] = new lalr_state[lalr_state.number()];
826 /* put the states in sorted order for a nicer display */
827 for (Enumeration s = lalr_state.all(); s.hasMoreElements(); )
829 lalr_state st = (lalr_state)s.nextElement();
830 ordered[st.index()] = st;
833 System.err.println("===== Viable Prefix Recognizer =====");
834 for (int i = 0; i<lalr_state.number(); i++)
836 if (ordered[i] == start_state) System.err.print("START ");
837 System.err.println(ordered[i]);
838 System.err.println("-------------------");
842 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
844 /** Produce a (semi-) human readable dumps of the parse tables */
845 public static void dump_tables()
847 System.err.println(action_table);
848 System.err.println(reduce_table);
851 /*-----------------------------------------------------------*/