
java_cup.Main Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javacup Show documentation
Show all versions of javacup Show documentation
A fork of the Java Cup parser generator with some bug fixes and enhancements. (Forked at version 11b)
The newest version!
package java_cup;
import java_cup.runtime.ComplexSymbolFactory;
import java.io.*;
import java.util.Enumeration;
/**
* This class serves as the main driver for the JavaCup system.
* It accepts user options and coordinates overall control flow.
* The main flow of control includes the following activities:
*
* - Parse user supplied arguments and options.
*
- Open output files.
*
- Parse the specification from standard input.
*
- Check for unused terminals, non-terminals, and productions.
*
- Build the state machine, tables, etc.
*
- Output the generated code.
*
- Close output files.
*
- Print a summary if requested.
*
*
* Options to the main program include:
* - -package name
*
- specify package generated classes go in [default none]
*
- -parser name
*
- specify parser class name [default "parser"]
*
- -symbols name
*
- specify name for symbol constant class [default "sym"]
*
- -interface
*
- emit symbol constant interface, rather than class
*
- -nonterms
*
- put non terminals in symbol constant class
*
- -expect #
*
- number of conflicts expected/allowed [default 0]
*
- -compact_red
*
- compact tables by defaulting to most frequent reduce
*
- -nowarn
*
- don't warn about useless productions, etc.
*
- -nosummary
*
- don't print the usual summary of parse states, etc.
*
- -progress
*
- print messages to indicate progress of the system
*
- -time
*
- print time usage summary
*
- -dump_grammar
*
- produce a dump of the symbols and grammar
*
- -dump_states
*
- produce a dump of parse state machine
*
- -dump_tables
*
- produce a dump of the parse tables
*
- -dump
*
- produce a dump of all of the above
*
- -debug
*
- turn on debugging messages within JavaCup
*
- -nopositions
*
- don't generate the positions code
*
- -locations
*
- generate handles xleft/xright for symbol positions in actions
*
- -noscanner
*
- don't refer to java_cup.runtime.Scanner in the parser
* (for compatibility with old runtimes)
*
- -version
*
- print version information for JavaCUP and halt.
*
*
* @author Frank Flannery
* @version last updated: 7/3/96
*/
public class Main {
/*-----------------------------------------------------------*/
/*--- Constructor(s) ----------------------------------------*/
/*-----------------------------------------------------------*/
/**
* Only constructor is private, so we do not allocate any instances of this
* class.
*/
private Main() {
}
/*-------------------------*/
/* Options set by the user */
/*-------------------------*/
/**
* User option -- do we print progress messages.
*/
protected static boolean print_progress = false;
/**
* User option -- do we produce a dump of the state machine
*/
protected static boolean opt_dump_states = false;
/**
* User option -- do we produce a dump of the parse tables
*/
protected static boolean opt_dump_tables = false;
/**
* User option -- do we produce a dump of the grammar
*/
protected static boolean opt_dump_grammar = false;
/**
* User option -- do we show timing information as a part of the summary
*/
protected static boolean opt_show_timing = false;
/**
* User option -- do we run produce extra debugging messages
*/
protected static boolean opt_do_debug = false;
/**
* User option -- do eclipse debug symbols
*/
protected static boolean opt_do_debugsymbols = false;
/**
* User option -- do we compact tables by making most common reduce the
* default action
*/
protected static boolean opt_compact_red = false;
/**
* User option -- should we include non terminal symbol numbers in the
* symbol constant class.
*/
protected static boolean include_non_terms = false;
/**
* User option -- do not print a summary.
*/
protected static boolean no_summary = false;
/**
* User option -- number of conflicts to expect
*/
protected static int expect_conflicts = 0;
/** the input filename */
private static String input_fileName;
/* frankf added this 6/18/96 */
/**
* User option -- should generator generate code for left/right values?
*/
protected static boolean lr_values = true;
protected static boolean locations = false;
protected static boolean xmlactions = false;
protected static boolean genericlabels = false;
/**
* User option -- should symbols be put in a class or an interface? [CSA]
*/
protected static boolean sym_interface = false;
/**
* User option -- should generator suppress references to
* java_cup.runtime.Scanner for compatibility with old runtimes?
*/
protected static boolean suppress_scanner = false;
/*----------------------------------------------------------------------*/
/* Timing data (not all of these time intervals are mutually exclusive) */
/*----------------------------------------------------------------------*/
/**
* Timing data -- when did we start
*/
protected static long start_time = 0;
/**
* Timing data -- when did we end preliminaries
*/
protected static long prelim_end = 0;
/**
* Timing data -- when did we end parsing
*/
protected static long parse_end = 0;
/**
* Timing data -- when did we end checking
*/
protected static long check_end = 0;
/**
* Timing data -- when did we end dumping
*/
protected static long dump_end = 0;
/**
* Timing data -- when did we end state and table building
*/
protected static long build_end = 0;
/**
* Timing data -- when did we end nullability calculation
*/
protected static long nullability_end = 0;
/**
* Timing data -- when did we end first set calculation
*/
protected static long first_end = 0;
/**
* Timing data -- when did we end state machine construction
*/
protected static long machine_end = 0;
/**
* Timing data -- when did we end table construction
*/
protected static long table_end = 0;
/**
* Timing data -- when did we end checking for non-reduced productions
*/
protected static long reduce_check_end = 0;
/**
* Timing data -- when did we finish emitting code
*/
protected static long emit_end = 0;
/**
* Timing data -- when were we completely done
*/
protected static long final_time = 0;
/* Additional timing information is also collected in emit */
/*-----------------------------------------------------------*/
/*--- Main Program ------------------------------------------*/
/*-----------------------------------------------------------*/
/**
* The main driver for the system.
*
* @param argv an array of strings containing command line arguments.
*/
public static void main(String argv[])
throws internal_error, java.io.IOException, java.lang.Exception {
boolean did_output = false;
start_time = System.currentTimeMillis();
/** clean all static members, that contain remaining stuff from earlier calls */
terminal.clear();
production.clear();
action_production.clear();
emit.clear();
non_terminal.clear();
parse_reduce_row.clear();
parse_action_row.clear();
lalr_state.clear();
/* process user options and arguments */
parse_args(argv);
/* frankf 6/18/96
hackish, yes, but works */
emit.set_lr_values(lr_values);
emit.set_locations(locations);
emit.set_xmlactions(xmlactions);
emit.set_genericlabels(genericlabels);
/* open output set_xmlactionsfiles */
if (print_progress) System.err.println("Opening files...");
/* use a buffered version of standard input */
input_file = new BufferedInputStream(System.in);
prelim_end = System.currentTimeMillis();
/* parse spec into internal data structures */
if (print_progress)
System.err.println("Parsing specification from standard input...");
parse_grammar_spec();
parse_end = System.currentTimeMillis();
/* don't proceed unless we are error free */
if (ErrorManager.getManager().getErrorCount() == 0) {
/* check for unused bits */
if (print_progress) System.err.println("Checking specification...");
check_unused();
check_end = System.currentTimeMillis();
/* build the state machine and parse tables */
if (print_progress) System.err.println("Building parse tables...");
build_parser();
build_end = System.currentTimeMillis();
/* output the generated code, if # of conflicts permits */
if (ErrorManager.getManager().getErrorCount() != 0) {
// conflicts! don't emit code, don't dump tables.
opt_dump_tables = false;
} else { // everything's okay, emit parser.
if (print_progress) System.err.println("Writing parser...");
open_files();
emit_parser();
did_output = true;
}
}
/* fix up the times to make the summary easier */
emit_end = System.currentTimeMillis();
/* do requested dumps */
if (opt_dump_grammar) dump_grammar();
if (opt_dump_states) {
dump_machine();
machineToDot();
}
if (opt_dump_tables) dump_tables();
dump_end = System.currentTimeMillis();
/* close input/output files */
if (print_progress) System.err.println("Closing files...");
close_files();
/* produce a summary if desired */
if (!no_summary) emit_summary(did_output);
/* If there were errors during the run,
* exit with non-zero status (makefile-friendliness). --CSA */
if (ErrorManager.getManager().getErrorCount() != 0)
System.exit(100);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Print a "usage message" that described possible command line options,
* then exit.
*
* @param message a specific error message to preface the usage message by.
*/
protected static void usage(String message) {
System.err.println();
System.err.println(message);
System.err.println();
System.err.println(
version.title_str + "\n" +
"Usage: " + version.program_name + " [options] [filename]\n" +
" and expects a specification file on standard input if no filename is given.\n" +
" Legal options include:\n" +
" -package name specify package generated classes go in [default none]\n" +
" -destdir name specify the destination directory, to store the generated files in\n" +
" -parser name specify parser class name [default \"parser\"]\n" +
" -typearg args specify type arguments for parser class\n" +
" -symbols name specify name for symbol constant class [default \"sym\"]\n" +
" -interface put symbols in an interface, rather than a class\n" +
" -nonterms put non terminals in symbol constant class\n" +
" -expect # number of conflicts expected/allowed [default 0]\n" +
" -compact_red compact tables by defaulting to most frequent reduce\n" +
" -nowarn don't warn about useless productions, etc.\n" +
" -nosummary don't print the usual summary of parse states, etc.\n" +
" -nopositions don't propagate the left and right token position values\n" +
" -locations generate handles xleft/xright for symbol positions in actions\n" +
" -xmlactions make the generated parser yield its parse tree as XML\n" +
" -genericlabels automatically generate labels to all symbols in XML mode\n" +
" -noscanner don't refer to java_cup.runtime.Scanner\n" +
" -progress print messages to indicate progress of the system\n" +
" -time print time usage summary\n" +
" -dump_grammar produce a human readable dump of the symbols and grammar\n" +
" -dump_states produce a dump of parse state machine\n" +
" -dump_tables produce a dump of the parse tables\n" +
" -dump produce a dump of all of the above\n" +
" -version print the version information for CUP and exit\n"
);
System.exit(1);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Parse command line options and arguments to set various user-option
* flags and variables.
*
* @param argv the command line arguments to be parsed.
*/
protected static void parse_args(String argv[]) {
int len = argv.length;
int i;
/* parse the options */
for (i = 0; i < len; i++) {
/* try to get the various options */
if (argv[i].equals("-package")) {
/* must have an arg */
if (++i >= len || argv[i].startsWith("-") ||
argv[i].endsWith(".cup"))
usage("-package must have a name argument");
/* record the name */
emit.package_name = argv[i];
} else if (argv[i].equals("-destdir")) {
/* must have an arg */
if (++i >= len || argv[i].startsWith("-") ||
argv[i].endsWith(".cup"))
usage("-destdir must have a name argument");
/* record the name */
Main.dest_dir = new java.io.File(argv[i]);
} else if (argv[i].equals("-parser")) {
/* must have an arg */
if (++i >= len || argv[i].startsWith("-") ||
argv[i].endsWith(".cup"))
usage("-parser must have a name argument");
/* record the name */
emit.parser_class_name = argv[i];
} else if (argv[i].equals("-symbols")) {
/* must have an arg */
if (++i >= len || argv[i].startsWith("-") ||
argv[i].endsWith(".cup"))
usage("-symbols must have a name argument");
/* record the name */
emit.symbol_const_class_name = argv[i];
} else if (argv[i].equals("-nonterms")) {
include_non_terms = true;
} else if (argv[i].equals("-expect")) {
/* must have an arg */
if (++i >= len || argv[i].startsWith("-") ||
argv[i].endsWith(".cup"))
usage("-expect must have a name argument");
/* record the number */
try {
expect_conflicts = Integer.parseInt(argv[i]);
} catch (NumberFormatException e) {
usage("-expect must be followed by a decimal integer");
}
} else if (argv[i].equals("-compact_red")) opt_compact_red = true;
else if (argv[i].equals("-nosummary")) no_summary = true;
else if (argv[i].equals("-nowarn")) emit.nowarn = true;
else if (argv[i].equals("-dump_states")) opt_dump_states = true;
else if (argv[i].equals("-dump_tables")) opt_dump_tables = true;
else if (argv[i].equals("-progress")) print_progress = true;
else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
else if (argv[i].equals("-dump"))
opt_dump_states = opt_dump_tables = opt_dump_grammar = true;
else if (argv[i].equals("-time")) opt_show_timing = true;
else if (argv[i].equals("-debug")) opt_do_debug = true;
else if (argv[i].equals("-debugsymbols")) opt_do_debugsymbols = true;
/* frankf 6/18/96 */
else if (argv[i].equals("-nopositions")) lr_values = false;
else if (argv[i].equals("-locations")) locations = true;
else if (argv[i].equals("-xmlactions")) xmlactions = true;
else if (argv[i].equals("-genericlabels")) genericlabels = true;
/* CSA 12/21/97 */
else if (argv[i].equals("-interface")) sym_interface = true;
/* CSA 23-Jul-1999 */
else if (argv[i].equals("-noscanner")) suppress_scanner = true;
/* CSA 23-Jul-1999 */
else if (argv[i].equals("-version")) {
System.out.println(version.title_str);
System.exit(1);
}
/* TUM changes; suggested by Henning Niss 20050628*/
else if (argv[i].equals("-typearg")) {
if (++i >= len || argv[i].startsWith("-") ||
argv[i].endsWith(".cup"))
usage("-symbols must have a name argument");
/* record the typearg */
emit.class_type_argument = argv[i];
}
/* CSA 24-Jul-1999; suggestion by Jean Vaucher */
else if (!argv[i].startsWith("-") && i == len - 1) {
/* use input from file. */
try {
input_fileName = argv[i];
System.setIn(new FileInputStream(input_fileName));
} catch (java.io.FileNotFoundException e) {
usage("Unable to open \"" + argv[i] + "\" for input");
}
} else {
usage("Unrecognized option \"" + argv[i] + "\"");
}
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/*-------*/
/* Files */
/*-------*/
/**
* Input file. This is a buffered version of System.in.
*/
protected static BufferedInputStream input_file;
/**
* Output file for the parser class.
*/
protected static PrintWriter parser_class_file;
/**
* Output file for the symbol constant class.
*/
protected static PrintWriter symbol_class_file;
/**
* Output directory.
*/
protected static File dest_dir = null;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Open various files used by the system.
*/
protected static void open_files() {
File fil;
String out_name;
/* open each of the output files */
/* parser class */
out_name = emit.parser_class_name + ".java";
fil = new File(dest_dir, out_name);
try {
parser_class_file = new PrintWriter(
new BufferedOutputStream(new FileOutputStream(fil), 4096));
} catch (Exception e) {
System.err.println("Can't open \"" + out_name + "\" for output");
System.exit(3);
}
/* symbol constants class */
out_name = emit.symbol_const_class_name + ".java";
fil = new File(dest_dir, out_name);
try {
symbol_class_file = new PrintWriter(
new BufferedOutputStream(new FileOutputStream(fil), 4096));
} catch (Exception e) {
System.err.println("Can't open \"" + out_name + "\" for output");
System.exit(4);
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Close various files used by the system.
*/
protected static void close_files() throws java.io.IOException {
if (input_file != null) input_file.close();
if (parser_class_file != null) parser_class_file.close();
if (symbol_class_file != null) symbol_class_file.close();
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Parse the grammar specification from standard input. This produces
* sets of terminal, non-terminals, and productions which can be accessed
* via static variables of the respective classes, as well as the setting
* of various variables (mostly in the emit class) for small user supplied
* items such as the code to scan with.
*/
protected static void parse_grammar_spec() throws java.lang.Exception {
parser parser_obj;
/* create a parser and parse with it */
ComplexSymbolFactory csf = new ComplexSymbolFactory();
parser_obj = new parser(new Lexer(input_fileName ,csf), csf);
parser_obj.setDebugSymbols(opt_do_debugsymbols);
try {
if (opt_do_debug)
parser_obj.debug_parse();
else
parser_obj.parse();
} catch (Exception e) {
/* something threw an exception. catch it and emit a message so we
have a line number to work with, then re-throw it */
ErrorManager.getManager().emit_error("Internal error: Unexpected exception");
throw e;
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Check for unused symbols. Unreduced productions get checked when
* tables are created.
*/
protected static void check_unused() {
terminal term;
non_terminal nt;
/* check for unused terminals */
for (Enumeration t = terminal.all(); t.hasMoreElements(); ) {
term = (terminal) t.nextElement();
/* don't issue a message for EOF */
if (term == terminal.EOF) continue;
/* or error */
if (term == terminal.error) continue;
/* is this one unused */
if (term.use_count() == 0) {
/* count it and warn if we are doing warnings */
emit.unused_term++;
if (!emit.nowarn) {
ErrorManager.getManager().emit_warning("Terminal \"" + term.name() + "\" was declared but never used");
}
}
}
/* check for unused non terminals */
for (Enumeration n = non_terminal.all(); n.hasMoreElements(); ) {
nt = (non_terminal) n.nextElement();
/* is this one unused */
if (nt.use_count() == 0) {
/* count and warn if we are doing warnings */
emit.unused_term++;
if (!emit.nowarn) {
ErrorManager.getManager().emit_warning("Non terminal \"" + nt.name() + "\" was declared but never used");
}
}
}
}
/* . . . . . . . . . . . . . . . . . . . . . . . . .*/
/* . . Internal Results of Generating the Parser . .*/
/* . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Start state in the overall state machine.
*/
protected static lalr_state start_state;
/**
* Resulting parse action table.
*/
protected static parse_action_table action_table;
/**
* Resulting reduce-goto table.
*/
protected static parse_reduce_table reduce_table;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Build the (internal) parser from the previously parsed specification.
* This includes:
* - Computing nullability of non-terminals.
*
- Computing first sets of non-terminals and productions.
*
- Building the viable prefix recognizer machine.
*
- Filling in the (internal) parse tables.
*
- Checking for unreduced productions.
*
*/
protected static void build_parser() throws internal_error {
/* compute nullability of all non terminals */
if (opt_do_debug || print_progress)
System.err.println(" Computing non-terminal nullability...");
non_terminal.compute_nullability();
nullability_end = System.currentTimeMillis();
/* compute first sets of all non terminals */
if (opt_do_debug || print_progress)
System.err.println(" Computing first sets...");
non_terminal.compute_first_sets();
first_end = System.currentTimeMillis();
/* build the LR viable prefix recognition machine */
if (opt_do_debug || print_progress)
System.err.println(" Building state machine...");
start_state = lalr_state.build_machine(emit.start_production);
machine_end = System.currentTimeMillis();
/* build the LR parser action and reduce-goto tables */
if (opt_do_debug || print_progress)
System.err.println(" Filling in tables...");
action_table = new parse_action_table();
reduce_table = new parse_reduce_table();
for (Enumeration st = lalr_state.all(); st.hasMoreElements(); ) {
lalr_state lst = (lalr_state) st.nextElement();
lst.build_table_entries(
action_table, reduce_table);
}
table_end = System.currentTimeMillis();
/* check and warn for non-reduced productions */
if (opt_do_debug || print_progress)
System.err.println(" Checking for non-reduced productions...");
action_table.check_reductions();
reduce_check_end = System.currentTimeMillis();
/* if we have more conflicts than we expected issue a message and die */
if (emit.num_conflicts > expect_conflicts) {
ErrorManager.getManager().emit_error("*** More conflicts encountered than expected " +
"-- parser generation aborted");
// indicate the problem.
// we'll die on return, after clean up.
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Call the emit routines necessary to write out the generated parser.
*/
protected static void emit_parser() throws internal_error {
emit.symbols(symbol_class_file, include_non_terms, sym_interface);
emit.parser(parser_class_file, action_table, reduce_table,
start_state.index(), emit.start_production, opt_compact_red,
suppress_scanner);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Helper routine to optionally return a plural or non-plural ending.
*
* @param val the numerical value determining plurality.
*/
protected static String plural(int val) {
if (val == 1)
return "";
else
return "s";
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Emit a long summary message to standard error (System.err) which
* summarizes what was found in the specification, how many states were
* produced, how many conflicts were found, etc. A detailed timing
* summary is also produced if it was requested by the user.
*
* @param output_produced did the system get far enough to generate code.
*/
protected static void emit_summary(boolean output_produced) {
final_time = System.currentTimeMillis();
if (no_summary) return;
System.err.println("------- " + version.title_str +
" Parser Generation Summary -------");
/* error and warning count */
System.err.println(" " + ErrorManager.getManager().getErrorCount() + " error" +
plural(ErrorManager.getManager().getErrorCount()) + " and " + ErrorManager.getManager().getWarningCount() +
" warning" + plural(ErrorManager.getManager().getWarningCount()));
/* basic stats */
System.err.print(" " + terminal.number() + " terminal" +
plural(terminal.number()) + ", ");
System.err.print(non_terminal.number() + " non-terminal" +
plural(non_terminal.number()) + ", and ");
System.err.println(production.number() + " production" +
plural(production.number()) + " declared, ");
System.err.println(" producing " + lalr_state.number() +
" unique parse states.");
/* unused symbols */
System.err.println(" " + emit.unused_term + " terminal" +
plural(emit.unused_term) + " declared but not used.");
System.err.println(" " + emit.unused_non_term + " non-terminal" +
plural(emit.unused_term) + " declared but not used.");
/* productions that didn't reduce */
System.err.println(" " + emit.not_reduced + " production" +
plural(emit.not_reduced) + " never reduced.");
/* conflicts */
System.err.println(" " + emit.num_conflicts + " conflict" +
plural(emit.num_conflicts) + " detected" +
" (" + expect_conflicts + " expected).");
/* code location */
if (output_produced)
System.err.println(" Code written to \"" + emit.parser_class_name +
".java\", and \"" + emit.symbol_const_class_name + ".java\".");
else
System.err.println(" No code produced.");
if (opt_show_timing) show_times();
System.err.println(
"---------------------------------------------------- (" +
version.title_str + ")");
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Produce the optional timing summary as part of an overall summary.
*/
protected static void show_times() {
long total_time = final_time - start_time;
System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
System.err.println(" Timing Summary");
System.err.println(" Total time "
+ timestr(final_time - start_time, total_time));
System.err.println(" Startup "
+ timestr(prelim_end - start_time, total_time));
System.err.println(" Parse "
+ timestr(parse_end - prelim_end, total_time));
if (check_end != 0)
System.err.println(" Checking "
+ timestr(check_end - parse_end, total_time));
if (check_end != 0 && build_end != 0)
System.err.println(" Parser Build "
+ timestr(build_end - check_end, total_time));
if (nullability_end != 0 && check_end != 0)
System.err.println(" Nullability "
+ timestr(nullability_end - check_end, total_time));
if (first_end != 0 && nullability_end != 0)
System.err.println(" First sets "
+ timestr(first_end - nullability_end, total_time));
if (machine_end != 0 && first_end != 0)
System.err.println(" State build "
+ timestr(machine_end - first_end, total_time));
if (table_end != 0 && machine_end != 0)
System.err.println(" Table build "
+ timestr(table_end - machine_end, total_time));
if (reduce_check_end != 0 && table_end != 0)
System.err.println(" Checking "
+ timestr(reduce_check_end - table_end, total_time));
if (emit_end != 0 && build_end != 0)
System.err.println(" Code Output "
+ timestr(emit_end - build_end, total_time));
if (emit.symbols_time != 0)
System.err.println(" Symbols "
+ timestr(emit.symbols_time, total_time));
if (emit.parser_time != 0)
System.err.println(" Parser class "
+ timestr(emit.parser_time, total_time));
if (emit.action_code_time != 0)
System.err.println(" Actions "
+ timestr(emit.action_code_time, total_time));
if (emit.production_table_time != 0)
System.err.println(" Prod table "
+ timestr(emit.production_table_time, total_time));
if (emit.action_table_time != 0)
System.err.println(" Action tab "
+ timestr(emit.action_table_time, total_time));
if (emit.goto_table_time != 0)
System.err.println(" Reduce tab "
+ timestr(emit.goto_table_time, total_time));
System.err.println(" Dump Output "
+ timestr(dump_end - emit_end, total_time));
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Helper routine to format a decimal based display of seconds and
* percentage of total time given counts of milliseconds. Note: this
* is broken for use with some instances of negative time (since we don't
* use any negative time here, we let if be for now).
*
* @param time_val the value being formatted (in ms).
* @param total_time total time percentages are calculated against (in ms).
*/
protected static String timestr(long time_val, long total_time) {
boolean neg;
long ms = 0;
long sec = 0;
long percent10;
String pad;
/* work with positives only */
neg = time_val < 0;
if (neg) time_val = -time_val;
/* pull out seconds and ms */
ms = time_val % 1000;
sec = time_val / 1000;
/* construct a pad to blank fill seconds out to 4 places */
if (sec < 10)
pad = " ";
else if (sec < 100)
pad = " ";
else if (sec < 1000)
pad = " ";
else
pad = "";
/* calculate 10 times the percentage of total */
percent10 = (time_val * 1000) / total_time;
/* build and return the output string */
return (neg ? "-" : "") + pad + sec + "." +
((ms % 1000) / 100) + ((ms % 100) / 10) + (ms % 10) + "sec" +
" (" + percent10 / 10 + "." + percent10 % 10 + "%)";
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Produce a human readable dump of the grammar.
*/
public static void dump_grammar() throws internal_error {
try (PrintWriter out = new PrintWriter(new FileWriter(dest_dir + "/grammar.txt"))) {
out.println("===== Terminals =====");
for (int tidx = 0, cnt = 0; tidx < terminal.number(); tidx++, cnt++) {
out.print("[" + tidx + "]" + terminal.find(tidx).name() + " ");
if ((cnt + 1) % 5 == 0) out.println();
}
out.println();
out.println();
out.println("===== Non terminals =====");
for (int nidx = 0, cnt = 0; nidx < non_terminal.number(); nidx++, cnt++) {
out.print("[" + nidx + "]" + non_terminal.find(nidx).name() + " ");
if ((cnt + 1) % 5 == 0) out.println();
}
out.println();
out.println();
out.println("===== Productions =====");
for (int pidx = 0; pidx < production.number(); pidx++) {
production prod = production.find(pidx);
out.print("[" + pidx + "] " + prod.lhs().the_symbol().name() + " ::= ");
for (int i = 0; i < prod.rhs_length(); i++)
if (prod.rhs(i).is_action())
out.print("{action} ");
else
out.print(
((symbol_part) prod.rhs(i)).the_symbol().name() + " ");
out.println();
}
out.println();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Produce a (semi-) human readable dump of the complete viable prefix
* recognition state machine.
*/
public static void dump_machine() {
try (PrintWriter out = new PrintWriter(new FileWriter(dest_dir + "/machine.txt"))) {
lalr_state ordered[] = new lalr_state[lalr_state.number()];
/* put the states in sorted order for a nicer display */
for (Enumeration s = lalr_state.all(); s.hasMoreElements(); ) {
lalr_state st = (lalr_state) s.nextElement();
ordered[st.index()] = st;
}
out.println("===== Viable Prefix Recognizer =====");
for (int i = 0; i < lalr_state.number(); i++) {
if (ordered[i] == start_state) out.print("START ");
out.println(ordered[i]);
out.println("-------------------");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* prints the LALR state machine to a dot file
*/
public static void machineToDot() {
lalr_state ordered[] = new lalr_state[lalr_state.number()];
/* put the states in sorted order for a nicer display */
for (Enumeration s = lalr_state.all(); s.hasMoreElements(); ) {
lalr_state st = (lalr_state) s.nextElement();
ordered[st.index()] = st;
}
try (PrintWriter out = new PrintWriter(new FileWriter(dest_dir + "/lalr_machine.dot"))) {
out.println("// compile using graphviz: ");
out.println("// dot lalr_machine.dot -Tsvg -o lalr_machine.svg");
out.println("// fdp lalr_machine.dot -Tsvg -o lalr_machine.svg");
out.println("// neato lalr_machine.dot -Tsvg -o lalr_machine.svg");
out.println("digraph g {");
out.println(" overlap = false;");
out.println(" splines = true;");
out.println("// ===== Viable Prefix Recognizer =====");
for (int i = 0; i < lalr_state.number(); i++) {
lalr_state state = ordered[i];
if (state == start_state) {
out.println("// START ");
}
out.println("\"node" + i + "\" [");
out.print(" label =\"" + i + "\\l");
lalr_item_set items = state._items;
for (Object o_item : items._all.values()) {
lalr_item item = (lalr_item) o_item;
out.print(item+"\\l");
}
out.println("\"\n");
out.println(" shape =\"rect\"");
out.println("];");
for (lalr_transition transition = state.transitions(); transition != null; transition = transition.next()) {
out.println("node" + i + " -> node" + transition.to_state().index() + " [ label=\"" + transition.on_symbol().name() + "\"];");
}
// result = "transition on " + on_symbol().name() + " to state [";
// result += _to_state.index();
// result += "]";
out.println("//-------------------");
}
out.println("}");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/**
* Produce a (semi-) human readable dumps of the parse tables
*/
public static void dump_tables() {
try (PrintWriter out = new PrintWriter(new FileWriter(dest_dir + "/tables.txt"))) {
out.println(action_table);
out.println(reduce_table);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/*-----------------------------------------------------------*/
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy