KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > java_cup > internal > Main


1
2 package com.sun.java_cup.internal;
3
4 import java.util.Enumeration JavaDoc;
5 import java.io.*;
6
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:
10  * <ul>
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.
19  * </ul>
20  *
21  * Options to the main program include: <dl>
22  * <dt> -package name
23  * <dd> specify package generated classes go in [default none]
24  * <dt> -parser name
25  * <dd> specify parser class name [default "parser"]
26  * <dt> -symbols name
27  * <dd> specify name for symbol constant class [default "sym"]
28  * <dt> -interface
29  * <dd> emit symbol constant <i>interface</i>, rather than class
30  * <dt> -nonterms
31  * <dd> put non terminals in symbol constant class
32  * <dt> -expect #
33  * <dd> number of conflicts expected/allowed [default 0]
34  * <dt> -compact_red
35  * <dd> compact tables by defaulting to most frequent reduce
36  * <dt> -nowarn
37  * <dd> don't warn about useless productions, etc.
38  * <dt> -nosummary
39  * <dd> don't print the usual summary of parse states, etc.
40  * <dt> -progress
41  * <dd> print messages to indicate progress of the system
42  * <dt> -time
43  * <dd> print time usage summary
44  * <dt> -dump_grammar
45  * <dd> produce a dump of the symbols and grammar
46  * <dt> -dump_states
47  * <dd> produce a dump of parse state machine
48  * <dt> -dump_tables
49  * <dd> produce a dump of the parse tables
50  * <dt> -dump
51  * <dd> produce a dump of all of the above
52  * <dt> -debug
53  * <dd> turn on debugging messages within JavaCup
54  * <dt> -nopositions
55  * <dd> don't generate the positions code
56  * <dt> -noscanner
57  * <dd> don't refer to com.sun.java_cup.internal.runtime.Scanner in the parser
58  * (for compatibility with old runtimes)
59  * <dt> -version
60  * <dd> print version information for JavaCUP and halt.
61  * </dl>
62  *
63  * @version last updated: 7/3/96
64  * @author Frank Flannery
65  */

66
67 public class Main {
68
69   /*-----------------------------------------------------------*/
70   /*--- Constructor(s) ----------------------------------------*/
71   /*-----------------------------------------------------------*/
72   /** Only constructor is private, so we do not allocate any instances of this
73       class. */

74   private Main() { }
75
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
92       default action */

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;
101
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;
105
106   /** User option -- should symbols be put in a class or an interface? [CSA]*/
107   protected static boolean sym_interface = false;
108
109   /** User option -- should generator suppress references to
110    * com.sun.java_cup.internal.runtime.Scanner for compatibility with old runtimes? */

111   protected static boolean suppress_scanner = false;
112
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;
142
143   /* Additional timing information is also collected in emit */
144
145   /*-----------------------------------------------------------*/
146   /*--- Main Program ------------------------------------------*/
147   /*-----------------------------------------------------------*/
148
149   /** The main driver for the system.
150    * @param argv an array of strings containing command line arguments.
151    */

152   public static void main(String JavaDoc argv[])
153     throws internal_error, java.io.IOException JavaDoc, java.lang.Exception JavaDoc
154     {
155       boolean did_output = false;
156
157       start_time = System.currentTimeMillis();
158
159       /* process user options and arguments */
160       parse_args(argv);
161
162       /* frankf 6/18/96
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);
169
170       prelim_end = System.currentTimeMillis();
171
172       /* parse spec into internal data structures */
173       if (print_progress)
174     System.err.println("Parsing specification from standard input...");
175       parse_grammar_spec();
176
177       parse_end = System.currentTimeMillis();
178
179       /* don't proceed unless we are error free */
180       if (lexer.error_count == 0)
181     {
182       /* check for unused bits */
183           if (print_progress) System.err.println("Checking specification...");
184           check_unused();
185
186           check_end = System.currentTimeMillis();
187
188       /* build the state machine and parse tables */
189           if (print_progress) System.err.println("Building parse tables...");
190           build_parser();
191
192           build_end = System.currentTimeMillis();
193
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...");
200           open_files();
201           emit_parser();
202           did_output = true;
203       }
204     }
205       /* fix up the times to make the summary easier */
206       emit_end = System.currentTimeMillis();
207
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();
212
213       dump_end = System.currentTimeMillis();
214
215       /* close input/output files */
216       if (print_progress) System.err.println("Closing files...");
217       close_files();
218
219       /* produce a summary if desired */
220       if (!no_summary) emit_summary(did_output);
221
222       /* If there were errors during the run,
223        * exit with non-zero status (makefile-friendliness). --CSA */

224       if (lexer.error_count != 0)
225       System.exit(100);
226     }
227
228   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
229
230   /** Print a "usage message" that described possible command line options,
231    * then exit.
232    * @param message a specific error message to preface the usage message by.
233    */

234   protected static void usage(String JavaDoc message)
235     {
236       System.err.println();
237       System.err.println(message);
238       System.err.println();
239       System.err.println(
240 "Usage: " + version.program_name + " [options]\n" +
241 " and expects a specification file on standard input.\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 com.sun.java_cup.internal.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"
261       );
262       System.exit(1);
263     }
264
265   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
266
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.
270    */

271   protected static void parse_args(String JavaDoc argv[])
272     {
273       int len = argv.length;
274       int i;
275
276       /* parse the options */
277       for (i=0; i<len; i++)
278     {
279       /* try to get the various options */
280       if (argv[i].equals("-package"))
281         {
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");
286
287           /* record the name */
288           emit.package_name = argv[i];
289         }
290       else if (argv[i].equals("-parser"))
291         {
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");
296
297           /* record the name */
298           emit.parser_class_name = argv[i];
299         }
300       else if (argv[i].equals("-symbols"))
301         {
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");
306
307           /* record the name */
308           emit.symbol_const_class_name = argv[i];
309         }
310       else if (argv[i].equals("-nonterms"))
311         {
312           include_non_terms = true;
313         }
314       else if (argv[i].equals("-expect"))
315         {
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");
320
321           /* record the number */
322           try {
323             expect_conflicts = Integer.parseInt(argv[i]);
324           } catch (NumberFormatException JavaDoc e) {
325         usage("-expect must be followed by a decimal integer");
326           }
327         }
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;
339       /* frankf 6/18/96 */
340       else if (argv[i].equals("-nopositions")) lr_values = false;
341       /* CSA 12/21/97 */
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);
348           System.exit(1);
349       }
350       else
351         {
352           usage("Unrecognized option \"" + argv[i] + "\"");
353         }
354     }
355     }
356
357   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
358
359   /*-------*/
360   /* Files */
361   /*-------*/
362
363   /** Input file. This is a buffered version of System.in. */
364   protected static BufferedInputStream input_file;
365
366   /** Output file for the parser class. */
367   protected static PrintWriter parser_class_file;
368
369   /** Output file for the symbol constant class. */
370   protected static PrintWriter symbol_class_file;
371
372   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
373
374   /** Open various files used by the system. */
375   protected static void open_files()
376     {
377       File fil;
378       String JavaDoc out_name;
379
380       /* open each of the output files */
381
382       /* parser class */
383       out_name = emit.parser_class_name + ".java";
384       fil = new File(out_name);
385       try {
386         parser_class_file = new PrintWriter(
387          new BufferedOutputStream(new FileOutputStream(fil), 4096));
388       } catch(Exception JavaDoc e) {
389     System.err.println("Can't open \"" + out_name + "\" for output");
390     System.exit(3);
391       }
392
393       /* symbol constants class */
394       out_name = emit.symbol_const_class_name + ".java";
395       fil = new File(out_name);
396       try {
397         symbol_class_file = new PrintWriter(
398          new BufferedOutputStream(new FileOutputStream(fil), 4096));
399       } catch(Exception JavaDoc e) {
400     System.err.println("Can't open \"" + out_name + "\" for output");
401     System.exit(4);
402       }
403     }
404
405   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
406
407   /** Close various files used by the system. */
408   protected static void close_files() throws java.io.IOException JavaDoc
409     {
410       if (input_file != null) input_file.close();
411       if (parser_class_file != null) parser_class_file.close();
412       if (symbol_class_file != null) symbol_class_file.close();
413     }
414
415   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
416
417   /** Parse the grammar specification from standard input. This produces
418    * sets of terminal, non-terminals, and productions which can be accessed
419    * via static variables of the respective classes, as well as the setting
420    * of various variables (mostly in the emit class) for small user supplied
421    * items such as the code to scan with.
422    */

423   protected static void parse_grammar_spec() throws java.lang.Exception JavaDoc
424     {
425       parser parser_obj;
426
427       /* create a parser and parse with it */
428       parser_obj = new parser();
429       try {
430     if (opt_do_debug)
431           parser_obj.debug_parse();
432     else
433           parser_obj.parse();
434       } catch (Exception JavaDoc e)
435       {
436     /* something threw an exception. catch it and emit a message so we
437        have a line number to work with, then re-throw it */

438     lexer.emit_error("Internal error: Unexpected exception");
439     throw e;
440       }
441     }
442
443   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
444
445   /** Check for unused symbols. Unreduced productions get checked when
446    * tables are created.
447    */

448   protected static void check_unused()
449     {
450       terminal term;
451       non_terminal nt;
452
453       /* check for unused terminals */
454       for (Enumeration JavaDoc t = terminal.all(); t.hasMoreElements(); )
455     {
456       term = (terminal)t.nextElement();
457
458       /* don't issue a message for EOF */
459       if (term == terminal.EOF) continue;
460
461       /* or error */
462       if (term == terminal.error) continue;
463
464       /* is this one unused */
465       if (term.use_count() == 0)
466         {
467           /* count it and warn if we are doing warnings */
468           emit.unused_term++;
469           if (!emit.nowarn)
470         {
471           System.err.println("Warning: Terminal \"" + term.name() +
472                      "\" was declared but never used");
473           lexer.warning_count++;
474         }
475         }
476     }
477
478       /* check for unused non terminals */
479       for (Enumeration JavaDoc n = non_terminal.all(); n.hasMoreElements(); )
480     {
481       nt = (non_terminal)n.nextElement();
482
483       /* is this one unused */
484       if (nt.use_count() == 0)
485         {
486           /* count and warn if we are doing warnings */
487           emit.unused_term++;
488           if (!emit.nowarn)
489         {
490           System.err.println("Warning: Non terminal \"" + nt.name() +
491                      "\" was declared but never used");
492           lexer.warning_count++;
493         }
494         }
495     }
496
497     }
498
499   /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
500   /* . . Internal Results of Generating the Parser . .*/
501   /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
502
503   /** Start state in the overall state machine. */
504   protected static lalr_state start_state;
505
506   /** Resulting parse action table. */
507   protected static parse_action_table action_table;
508
509   /** Resulting reduce-goto table. */
510   protected static parse_reduce_table reduce_table;
511
512   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
513
514   /** Build the (internal) parser from the previously parsed specification.
515    * This includes:<ul>
516    * <li> Computing nullability of non-terminals.
517    * <li> Computing first sets of non-terminals and productions.
518    * <li> Building the viable prefix recognizer machine.
519    * <li> Filling in the (internal) parse tables.
520    * <li> Checking for unreduced productions.
521    * </ul>
522    */

523   protected static void build_parser() throws internal_error
524     {
525       /* compute nullability of all non terminals */
526       if (opt_do_debug || print_progress)
527     System.err.println(" Computing non-terminal nullability...");
528       non_terminal.compute_nullability();
529
530       nullability_end = System.currentTimeMillis();
531
532       /* compute first sets of all non terminals */
533       if (opt_do_debug || print_progress)
534     System.err.println(" Computing first sets...");
535       non_terminal.compute_first_sets();
536
537       first_end = System.currentTimeMillis();
538
539       /* build the LR viable prefix recognition machine */
540       if (opt_do_debug || print_progress)
541     System.err.println(" Building state machine...");
542       start_state = lalr_state.build_machine(emit.start_production);
543
544       machine_end = System.currentTimeMillis();
545
546       /* build the LR parser action and reduce-goto tables */
547       if (opt_do_debug || print_progress)
548     System.err.println(" Filling in tables...");
549       action_table = new parse_action_table();
550       reduce_table = new parse_reduce_table();
551       for (Enumeration JavaDoc st = lalr_state.all(); st.hasMoreElements(); )
552     {
553       lalr_state lst = (lalr_state)st.nextElement();
554       lst.build_table_entries(
555                                   action_table, reduce_table);
556     }
557
558       table_end = System.currentTimeMillis();
559
560       /* check and warn for non-reduced productions */
561       if (opt_do_debug || print_progress)
562     System.err.println(" Checking for non-reduced productions...");
563       action_table.check_reductions();
564
565       reduce_check_end = System.currentTimeMillis();
566
567       /* if we have more conflicts than we expected issue a message and die */
568       if (emit.num_conflicts > expect_conflicts)
569     {
570       System.err.println("*** More conflicts encountered than expected " +
571                  "-- parser generation aborted");
572       lexer.error_count++; // indicate the problem.
573
// we'll die on return, after clean up.
574
}
575     }
576
577   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
578
579   /** Call the emit routines necessary to write out the generated parser. */
580   protected static void emit_parser() throws internal_error
581     {
582       emit.symbols(symbol_class_file, include_non_terms, sym_interface);
583       emit.parser(parser_class_file, action_table, reduce_table,
584           start_state.index(), emit.start_production, opt_compact_red,
585           suppress_scanner);
586     }
587
588   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
589
590   /** Helper routine to optionally return a plural or non-plural ending.
591    * @param val the numerical value determining plurality.
592    */

593   protected static String JavaDoc plural(int val)
594     {
595       if (val == 1)
596     return "";
597       else
598     return "s";
599     }
600
601   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
602
603   /** Emit a long summary message to standard error (System.err) which
604    * summarizes what was found in the specification, how many states were
605    * produced, how many conflicts were found, etc. A detailed timing
606    * summary is also produced if it was requested by the user.
607    * @param output_produced did the system get far enough to generate code.
608    */

609   protected static void emit_summary(boolean output_produced)
610     {
611       final_time = System.currentTimeMillis();
612
613       if (no_summary) return;
614
615       System.err.println("------- " + version.title_str +
616              " Parser Generation Summary -------");
617
618       /* error and warning count */
619       System.err.println(" " + lexer.error_count + " error" +
620      plural(lexer.error_count) + " and " + lexer.warning_count +
621      " warning" + plural(lexer.warning_count));
622
623       /* basic stats */
624       System.err.print(" " + terminal.number() + " terminal" +
625              plural(terminal.number()) + ", ");
626       System.err.print(non_terminal.number() + " non-terminal" +
627              plural(non_terminal.number()) + ", and ");
628       System.err.println(production.number() + " production" +
629              plural(production.number()) + " declared, ");
630       System.err.println(" producing " + lalr_state.number() +
631              " unique parse states.");
632
633       /* unused symbols */
634       System.err.println(" " + emit.unused_term + " terminal" +
635              plural(emit.unused_term) + " declared but not used.");
636       System.err.println(" " + emit.unused_non_term + " non-terminal" +
637              plural(emit.unused_term) + " declared but not used.");
638
639       /* productions that didn't reduce */
640       System.err.println(" " + emit.not_reduced + " production" +
641              plural(emit.not_reduced) + " never reduced.");
642
643       /* conflicts */
644       System.err.println(" " + emit.num_conflicts + " conflict" +
645              plural(emit.num_conflicts) + " detected" +
646                      " (" + expect_conflicts + " expected).");
647
648       /* code location */
649       if (output_produced)
650     System.err.println(" Code written to \"" + emit.parser_class_name +
651             ".java\", and \"" + emit.symbol_const_class_name + ".java\".");
652       else
653     System.err.println(" No code produced.");
654
655       if (opt_show_timing) show_times();
656
657       System.err.println(
658     "---------------------------------------------------- (" +
659      version.version_str + ")");
660     }
661
662   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
663
664   /** Produce the optional timing summary as part of an overall summary. */
665   protected static void show_times()
666     {
667       long total_time = final_time - start_time;
668
669       System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
670       System.err.println(" Timing Summary");
671       System.err.println(" Total time "
672         + timestr(final_time-start_time, total_time));
673       System.err.println(" Startup "
674     + timestr(prelim_end-start_time, total_time));
675       System.err.println(" Parse "
676     + timestr(parse_end-prelim_end, total_time) );
677       if (check_end != 0)
678         System.err.println(" Checking "
679         + timestr(check_end-parse_end, total_time));
680       if (check_end != 0 && build_end != 0)
681         System.err.println(" Parser Build "
682         + timestr(build_end-check_end, total_time));
683       if (nullability_end != 0 && check_end != 0)
684         System.err.println(" Nullability "
685         + timestr(nullability_end-check_end, total_time));
686       if (first_end != 0 && nullability_end != 0)
687         System.err.println(" First sets "
688             + timestr(first_end-nullability_end, total_time));
689       if (machine_end != 0 && first_end != 0)
690         System.err.println(" State build "
691         + timestr(machine_end-first_end, total_time));
692       if (table_end != 0 && machine_end != 0)
693         System.err.println(" Table build "
694         + timestr(table_end-machine_end, total_time));
695       if (reduce_check_end != 0 && table_end != 0)
696         System.err.println(" Checking "
697         + timestr(reduce_check_end-table_end, total_time));
698       if (emit_end != 0 && build_end != 0)
699         System.err.println(" Code Output "
700         + timestr(emit_end-build_end, total_time));
701       if (emit.symbols_time != 0)
702     System.err.println(" Symbols "
703         + timestr(emit.symbols_time, total_time));
704       if (emit.parser_time != 0)
705     System.err.println(" Parser class "
706         + timestr(emit.parser_time, total_time));
707       if (emit.action_code_time != 0)
708     System.err.println(" Actions "
709         + timestr(emit.action_code_time, total_time));
710       if (emit.production_table_time != 0)
711     System.err.println(" Prod table "
712         + timestr(emit.production_table_time, total_time));
713       if (emit.action_table_time != 0)
714     System.err.println(" Action tab "
715         + timestr(emit.action_table_time, total_time));
716       if (emit.goto_table_time != 0)
717     System.err.println(" Reduce tab "
718         + timestr(emit.goto_table_time, total_time));
719
720       System.err.println(" Dump Output "
721     + timestr(dump_end-emit_end, total_time));
722     }
723
724   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
725
726   /** Helper routine to format a decimal based display of seconds and
727    * percentage of total time given counts of milliseconds. Note: this
728    * is broken for use with some instances of negative time (since we don't
729    * use any negative time here, we let if be for now).
730    * @param time_val the value being formatted (in ms).
731    * @param total_time total time percentages are calculated against (in ms).
732    */

733   protected static String JavaDoc timestr(long time_val, long total_time)
734     {
735       boolean neg;
736       long ms = 0;
737       long sec = 0;
738       long percent10;
739       String JavaDoc pad;
740
741       /* work with positives only */
742       neg = time_val < 0;
743       if (neg) time_val = -time_val;
744
745       /* pull out seconds and ms */
746       ms = time_val % 1000;
747       sec = time_val / 1000;
748
749       /* construct a pad to blank fill seconds out to 4 places */
750       if (sec < 10)
751     pad = " ";
752       else if (sec < 100)
753     pad = " ";
754       else if (sec < 1000)
755     pad = " ";
756       else
757     pad = "";
758
759       /* calculate 10 times the percentage of total */
760       percent10 = (time_val*1000)/total_time;
761
762       /* build and return the output string */
763       return (neg ? "-" : "") + pad + sec + "." +
764          ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" +
765          " (" + percent10/10 + "." + percent10%10 + "%)";
766     }
767
768   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
769
770   /** Produce a human readable dump of the grammar. */
771   public static void dump_grammar() throws internal_error
772     {
773       System.err.println("===== Terminals =====");
774       for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
775     {
776       System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
777       if ((cnt+1) % 5 == 0) System.err.println();
778     }
779       System.err.println();
780       System.err.println();
781
782       System.err.println("===== Non terminals =====");
783       for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
784     {
785       System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
786       if ((cnt+1) % 5 == 0) System.err.println();
787     }
788       System.err.println();
789       System.err.println();
790
791
792       System.err.println("===== Productions =====");
793       for (int pidx=0; pidx < production.number(); pidx++)
794     {
795       production prod = production.find(pidx);
796       System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= ");
797       for (int i=0; i<prod.rhs_length(); i++)
798         if (prod.rhs(i).is_action())
799           System.err.print("{action} ");
800         else
801           System.err.print(
802              ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
803       System.err.println();
804     }
805       System.err.println();
806     }
807
808   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
809
810   /** Produce a (semi-) human readable dump of the complete viable prefix
811    * recognition state machine.
812    */

813   public static void dump_machine()
814     {
815       lalr_state ordered[] = new lalr_state[lalr_state.number()];
816
817       /* put the states in sorted order for a nicer display */
818       for (Enumeration JavaDoc s = lalr_state.all(); s.hasMoreElements(); )
819     {
820       lalr_state st = (lalr_state)s.nextElement();
821       ordered[st.index()] = st;
822     }
823
824       System.err.println("===== Viable Prefix Recognizer =====");
825       for (int i = 0; i<lalr_state.number(); i++)
826     {
827       if (ordered[i] == start_state) System.err.print("START ");
828           System.err.println(ordered[i]);
829       System.err.println("-------------------");
830     }
831     }
832
833   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
834
835   /** Produce a (semi-) human readable dumps of the parse tables */
836   public static void dump_tables()
837     {
838       System.err.println(action_table);
839       System.err.println(reduce_table);
840     }
841
842   /*-----------------------------------------------------------*/
843
844 }
845
846
Popular Tags