auto import from //branches/cupcake_rel/...@138607
diff --git a/tools/dasm/src/java_cup/Main.java b/tools/dasm/src/java_cup/Main.java
new file mode 100644
index 0000000..c816da1
--- /dev/null
+++ b/tools/dasm/src/java_cup/Main.java
@@ -0,0 +1,856 @@
+
+package java_cup;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+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:
+ * <ul>
+ * <li> Parse user supplied arguments and options.
+ * <li> Open output files.
+ * <li> Parse the specification from standard input.
+ * <li> Check for unused terminals, non-terminals, and productions.
+ * <li> Build the state machine, tables, etc.
+ * <li> Output the generated code.
+ * <li> Close output files.
+ * <li> Print a summary if requested.
+ * </ul>
+ *
+ * Options to the main program include: <dl>
+ * <dt> -package name
+ * <dd> specify package generated classes go in [default none]
+ * <dt> -parser name
+ * <dd> specify parser class name [default "parser"]
+ * <dt> -symbols name
+ * <dd> specify name for symbol constant class [default "sym"]
+ * <dt> -nonterms
+ * <dd> put non terminals in symbol constant class
+ * <dt> -expect #
+ * <dd> number of conflicts expected/allowed [default 0]
+ * <dt> -compact_red
+ * <dd> compact tables by defaulting to most frequent reduce
+ * <dt> -nowarn
+ * <dd> don't warn about useless productions, etc.
+ * <dt> -nosummary
+ * <dd> don't print the usual summary of parse states, etc.
+ * <dt> -progress
+ * <dd> print messages to indicate progress of the system
+ * <dt> -time
+ * <dd> print time usage summary
+ * <dt> -dump_grammar
+ * <dd> produce a dump of the symbols and grammar
+ * <dt> -dump_states
+ * <dd> produce a dump of parse state machine
+ * <dt> -dump_tables
+ * <dd> produce a dump of the parse tables
+ * <dt> -dump
+ * <dd> produce a dump of all of the above
+ * <dt> -debug
+ * <dd> turn on debugging messages within JavaCup
+ * </dl>
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+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 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;
+
+ /*----------------------------------------------------------------------*/
+ /* 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 */
+
+ /** Path to create output files */
+ private static String out_path = null;
+
+ /*-----------------------------------------------------------*/
+ /*--- 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();
+
+ /* process user options and arguments */
+ parse_args(argv);
+
+ /* open output files */
+ if (print_progress) System.err.println("Opening files...");
+ open_files();
+
+ 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 (lexer.error_count == 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 (print_progress) System.err.println("Writing parser...");
+ emit_parser();
+ did_output = true;
+
+ emit_end = System.currentTimeMillis();
+ }
+ else
+ {
+ /* fix up the times to make the summary easier */
+ emit_end = parse_end;
+ }
+
+ /* do requested dumps */
+ if (opt_dump_grammar) dump_grammar();
+ if (opt_dump_states) dump_machine();
+ if (opt_dump_tables) dump_tables();
+
+ dump_end = System.currentTimeMillis();
+
+ /* close output files */
+ if (print_progress) System.err.println("Closing files...");
+ close_files();
+
+ /* produce a summary if desired */
+ if (!no_summary) emit_summary(did_output);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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(
+"Usage: " + version.program_name + " [options]\n" +
+" and expects a specification file on standard input.\n" +
+" Legal options include:\n" +
+" -out path specify the output files path [default current directory]\n" +
+" -package name specify package generated classes go in [default none]\n" +
+" -parser name specify parser class name [default \"parser\"]\n" +
+" -symbols name specify name for symbol constant class [default \"sym\"]\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" +
+" -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"
+ );
+ 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("-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("-input")) {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-input must have a name argument");
+
+ /* record the name */
+ emit.input_file_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("-out"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-"))
+ usage("-out must have a path argument");
+
+ /* validate path */
+ if (argv[i].length() != 0) {
+ out_path = argv[i] + File.separator;
+ File f = new File(out_path);
+ if (!f.exists() || !f.isDirectory())
+ out_path = null;
+ }
+ if (out_path == null)
+ usage("-out argument must be a valid existing path");
+ }
+ 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
+ {
+ 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 PrintStream parser_class_file;
+
+ /** Output file for the symbol constant class. */
+ protected static PrintStream symbol_class_file;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Open various files used by the system. */
+ protected static void open_files()
+ {
+ File fil;
+ String out_name;
+
+ /* use a buffered version of standard input */
+ if (emit.input_file_name != null)
+ try {
+ input_file = new BufferedInputStream(new FileInputStream(emit.input_file_name));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(3);
+ }
+ else
+ input_file = new BufferedInputStream(System.in);
+
+ /* open each of the output files */
+ if (out_path == null)
+ out_path = "";
+
+ /* parser class */
+ out_name = out_path + emit.parser_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ parser_class_file = new PrintStream(
+ 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 = out_path + emit.symbol_const_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ symbol_class_file = new PrintStream(
+ 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 */
+ parser_obj = new parser();
+ 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 */
+ lexer.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)
+ {
+ System.err.println("Warning: Terminal \"" + term.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ /* 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)
+ {
+ System.err.println("Warning: Non terminal \"" + nt.name() +
+ "\" was declared but never used");
+ lexer.warning_count++;
+ }
+ }
+ }
+
+ }
+
+ /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* . . 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:<ul>
+ * <li> Computing nullability of non-terminals.
+ * <li> Computing first sets of non-terminals and productions.
+ * <li> Building the viable prefix recognizer machine.
+ * <li> Filling in the (internal) parse tables.
+ * <li> Checking for unreduced productions.
+ * </ul>
+ */
+ 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)st.nextElement()).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)
+ {
+ System.err.println("*** More conflicts encountered than expected " +
+ "-- parser generation aborted");
+ lexer.error_count++;
+ build_end = System.currentTimeMillis();
+
+ /* do dumps and summary as needed */
+ if (opt_dump_grammar) dump_grammar();
+ if (opt_dump_states) dump_machine();
+ if (!no_summary) emit_summary(false);
+
+ System.exit(100);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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);
+ emit.parser(parser_class_file, action_table, reduce_table,
+ start_state.index(), emit.start_production, opt_compact_red);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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(" " + lexer.error_count + " error" +
+ plural(lexer.error_count) + " and " + lexer.warning_count +
+ " warning" + plural(lexer.warning_count));
+
+ /* 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.version_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
+ {
+ int cnt;
+ Enumeration t, n, p;
+ production prod;
+
+ System.err.println("===== Terminals =====");
+ for (t = terminal.all(), cnt=0; t.hasMoreElements(); cnt++)
+ {
+ System.err.print(((terminal)t.nextElement()).name() + " ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+ System.err.println("===== Non terminals =====");
+ for (n=non_terminal.all(), cnt=0; n.hasMoreElements(); cnt++)
+ {
+ System.err.print(((non_terminal)n.nextElement()).name() + " ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+
+ System.err.println("===== Productions =====");
+ for (p=production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+ System.err.print(prod.lhs().the_symbol().name() + " ::= ");
+ for (int i=0; i<prod.rhs_length(); i++)
+ if (prod.rhs(i).is_action())
+ System.err.print("{action} ");
+ else
+ System.err.print(
+ ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
+ System.err.println();
+ }
+ System.err.println();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dump of the complete viable prefix
+ * recognition state machine.
+ */
+ public static void dump_machine()
+ {
+ 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;
+ }
+
+ System.err.println("===== Viable Prefix Recognizer =====");
+ for (int i = 0; i<lalr_state.number(); i++)
+ {
+ if (ordered[i] == start_state) System.err.print("START ");
+ System.err.println(ordered[i]);
+ System.err.println("-------------------");
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a (semi-) human readable dumps of the parse tables */
+ public static void dump_tables()
+ {
+ System.err.println(action_table);
+ System.err.println(reduce_table);
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
diff --git a/tools/dasm/src/java_cup/action_part.java b/tools/dasm/src/java_cup/action_part.java
new file mode 100644
index 0000000..5beb385
--- /dev/null
+++ b/tools/dasm/src/java_cup/action_part.java
@@ -0,0 +1,93 @@
+
+package java_cup;
+
+/**
+ * This class represents a part of a production which contains an
+ * action. These are eventually eliminated from productions and converted
+ * to trailing actions by factoring out with a production that derives the
+ * empty string (and ends with this action).
+ *
+ * @see java_cup.production
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructors ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param code_str string containing the actual user code.
+ */
+ public action_part(String code_str)
+ {
+ super(/* never have a label on code */null);
+ _code_string = code_str;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String containing code for the action in question. */
+ protected String _code_string;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String containing code for the action in question. */
+ public String code_string() {return _code_string;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Set the code string. */
+ public void set_code_string(String new_str) {_code_string = new_str;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Override to report this object as an action. */
+ public boolean is_action() { return true; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for properly typed object. */
+ public boolean equals(action_part other)
+ {
+ /* compare the strings */
+ return other != null && super.equals(other) &&
+ other.code_string().equals(code_string());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof action_part))
+ return false;
+ else
+ return equals((action_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (code_string()==null ? 0 : code_string().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "{" + code_string() + "}";
+ }
+
+ /*-----------------------------------------------------------*/
+};
diff --git a/tools/dasm/src/java_cup/action_production.java b/tools/dasm/src/java_cup/action_production.java
new file mode 100644
index 0000000..112e1eb
--- /dev/null
+++ b/tools/dasm/src/java_cup/action_production.java
@@ -0,0 +1,39 @@
+
+package java_cup;
+
+/** A specialized version of a production used when we split an existing
+ * production in order to remove an embedded action. Here we keep a bit
+ * of extra bookkeeping so that we know where we came from.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class action_production extends production {
+
+ /** Constructor.
+ * @param base the production we are being factored out of.
+ * @param lhs_sym the LHS symbol for this production.
+ * @param rhs_parts array of production parts for the RHS.
+ * @param rhs_len how much of the rhs_parts array is valid.
+ * @param action_str the trailing reduce action for this production.
+ */
+ public action_production(
+ production base,
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_len,
+ String action_str)
+ throws internal_error
+ {
+ super(lhs_sym, rhs_parts, rhs_len, action_str);
+ _base_production = base;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The production we were taken out of. */
+ protected production _base_production;
+
+ /** The production we were taken out of. */
+ public production base_production() {return _base_production;}
+};
diff --git a/tools/dasm/src/java_cup/emit.java b/tools/dasm/src/java_cup/emit.java
new file mode 100644
index 0000000..5c2ce69
--- /dev/null
+++ b/tools/dasm/src/java_cup/emit.java
@@ -0,0 +1,755 @@
+
+package java_cup;
+
+import java.io.PrintStream;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Stack;
+
+/**
+ * This class handles emitting generated code for the resulting parser.
+ * The various parse tables must be constructed, etc. before calling any
+ * routines in this class.<p>
+ *
+ * Three classes are produced by this code:
+ * <dl>
+ * <dt> symbol constant class
+ * <dd> this contains constant declarations for each terminal (and
+ * optionally each non-terminal).
+ * <dt> action class
+ * <dd> this non-public class contains code to invoke all the user actions
+ * that were embedded in the parser specification.
+ * <dt> parser class
+ * <dd> the specialized parser class consisting primarily of some user
+ * supplied general and initialization code, and the parse tables.
+ * </dl><p>
+ *
+ * Three parse tables are created as part of the parser class:
+ * <dl>
+ * <dt> production table
+ * <dd> lists the LHS non terminal number, and the length of the RHS of
+ * each production.
+ * <dt> action table
+ * <dd> for each state of the parse machine, gives the action to be taken
+ * (shift, reduce, or error) under each lookahead symbol.<br>
+ * <dt> reduce-goto table
+ * <dd> when a reduce on a given production is taken, the parse stack is
+ * popped back a number of elements corresponding to the RHS of the
+ * production. This reveals a prior state, which we transition out
+ * of under the LHS non terminal symbol for the production (as if we
+ * had seen the LHS symbol rather than all the symbols matching the
+ * RHS). This table is indexed by non terminal numbers and indicates
+ * how to make these transitions.
+ * </dl><p>
+ *
+ * In addition to the method interface, this class maintains a series of
+ * public global variables and flags indicating how misc. parts of the code
+ * and other output is to be produced, and counting things such as number of
+ * conflicts detected (see the source code and public variables below for
+ * more details).<p>
+ *
+ * This class is "static" (contains only static data and methods).<p>
+ *
+ * @see java_cup.main
+ * @version last update: 11/25/95
+ * @author Scott Hudson
+ */
+
+/* Major externally callable routines here include:
+ symbols - emit the symbol constant class
+ parser - emit the parser class
+
+ In addition the following major internal routines are provided:
+ emit_package - emit a package declaration
+ emit_action_code - emit the class containing the user's actions
+ emit_production_table - emit declaration and init for the production table
+ do_action_table - emit declaration and init for the action table
+ do_reduce_table - emit declaration and init for the reduce-goto table
+
+ Finally, this class uses a number of public instance variables to communicate
+ optional parameters and flags used to control how code is generated,
+ as well as to report counts of various things (such as number of conflicts
+ detected). These include:
+
+ prefix - a prefix string used to prefix names that would
+ otherwise "pollute" someone else's name space.
+ package_name - name of the package emitted code is placed in
+ (or null for an unnamed package.
+ symbol_const_class_name - name of the class containing symbol constants.
+ parser_class_name - name of the class for the resulting parser.
+ action_code - user supplied declarations and other code to be
+ placed in action class.
+ parser_code - user supplied declarations and other code to be
+ placed in parser class.
+ init_code - user supplied code to be executed as the parser
+ is being initialized.
+ scan_code - user supplied code to get the next token.
+ start_production - the start production for the grammar.
+ import_list - list of imports for use with action class.
+ num_conflicts - number of conflicts detected.
+ nowarn - true if we are not to issue warning messages.
+ not_reduced - count of number of productions that never reduce.
+ unused_term - count of unused terminal symbols.
+ unused_non_term - count of unused non terminal symbols.
+ *_time - a series of symbols indicating how long various
+ sub-parts of code generation took (used to produce
+ optional time reports in main).
+*/
+
+public class emit {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Only constructor is private so no instances can be created. */
+ private emit() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ public static String input_file_name;
+
+ /** The prefix placed on names that pollute someone else's name space. */
+ public static String prefix = "CUP$";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Package that the resulting code goes into (null is used for unnamed). */
+ public static String package_name = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated class for symbol constants. */
+ public static String symbol_const_class_name = "sym";
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the generated parser class. */
+ public static String parser_class_name = "parser";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in user action class. */
+ public static String action_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User declarations for direct inclusion in parser class. */
+ public static String parser_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for user_init() which is called during parser initialization. */
+ public static String init_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for scan() which is called to get the next token. */
+ public static String scan_code = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The start production of the grammar. */
+ public static production start_production = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of imports (Strings containing class names) to go with actions. */
+ public static Stack import_list = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Number of conflict found while building tables. */
+ public static int num_conflicts = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do we skip warnings? */
+ public static boolean nowarn = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of the number on non-reduced productions found. */
+ public static int not_reduced = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused terminals. */
+ public static int unused_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of unused non terminals. */
+ public static int unused_non_term = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Timing values used to produce timing report in main.*/
+
+ /** Time to produce symbol constant class. */
+ public static long symbols_time = 0;
+
+ /** Time to produce parser class. */
+ public static long parser_time = 0;
+
+ /** Time to produce action code class. */
+ public static long action_code_time = 0;
+
+ /** Time to produce the production table. */
+ public static long production_table_time = 0;
+
+ /** Time to produce the action table. */
+ public static long action_table_time = 0;
+
+ /** Time to produce the reduce-goto table. */
+ public static long goto_table_time = 0;
+
+ /** Do we produce calls debug_gammar in generated parser? */
+ public static String debug_grammar = null;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Build a string with the standard prefix.
+ * @param str string to prefix.
+ */
+ protected static String pre(String str) {return prefix + str;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a package spec if the user wants one.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_package(PrintStream out)
+ {
+ /* generate a package spec if we have a name for one */
+ if (package_name != null)
+ out.println("package " + package_name + ";\n");
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the symbol constant class, optionally including non terms,
+ * if they have been requested.
+ * @param out stream to produce output on.
+ * @param emit_non_terms do we emit constants for non terminals?
+ */
+ public static void symbols(PrintStream out, boolean emit_non_terms)
+ {
+ terminal term;
+ non_terminal nt;
+
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* class header */
+ out.println(
+ "/** JavaCup generated class containing symbol constants. */");
+ out.println("public class " + symbol_const_class_name + " {");
+
+ out.println(" /* terminals */");
+
+ /* walk over the terminals */ /* later might sort these */
+ for (Enumeration e = terminal.all(); e.hasMoreElements(); )
+ {
+ term = (terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" static final int " + term.name() + " = " +
+ term.index() + ";");
+ }
+
+ /* do the non terminals if they want them (parser doesn't need them) */
+ if (emit_non_terms)
+ {
+ out.println("\n /* non terminals */");
+
+ /* walk over the non terminals */ /* later might sort these */
+ for (Enumeration e = non_terminal.all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* output a constant decl for the terminal */
+ out.println(" static final int " + nt.name() + " = " +
+ nt.index() + ";");
+ }
+ }
+
+ /* end of class */
+ out.println("};\n");
+
+ symbols_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit code for the non-public class holding the actual action code.
+ * @param out stream to produce output on.
+ * @param start_prod the start production of the grammar.
+ */
+ protected static void emit_action_code(PrintStream out, production start_prod)
+ throws internal_error
+ {
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* class header */
+ out.println();
+ out.println(
+ "/** JavaCup generated class to encapsulate user supplied action code.*/"
+ );
+ out.println("class " + pre("actions") + " {");
+
+ /* user supplied code */
+ if (action_code != null)
+ {
+ out.println();
+ out.println(action_code);
+ }
+
+ /* constructor */
+ out.println();
+ out.println(" /** Constructor */");
+ out.println(" " + pre("actions") + "() { }");
+
+ /* action method head */
+ out.println();
+ out.println(" /** Method with the actual generated action code. */");
+ out.println(" public final java_cup.runtime.symbol " +
+ pre("do_action") + "(");
+ out.println(" int " + pre("act_num,"));
+ out.println(" java_cup.runtime.lr_parser " + pre("parser,"));
+ out.println(" java.util.Stack " + pre("stack,"));
+ out.println(" int " + pre("top)"));
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+
+ /* declaration of result symbol */
+ out.println(" /* object for return from actions */");
+ out.println(" java_cup.runtime.symbol " + pre("result") + ";");
+ out.println();
+
+ /* switch top */
+ out.println(" /* select the action based on the action number */");
+ out.println(" switch (" + pre("act_num") + ")");
+ out.println(" {");
+
+ /* emit action code for each production as a separate case */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* case label */
+ out.println(" /*. . . . . . . . . . . . . . . . . . . .*/");
+ out.println(" case " + prod.index() + ": // " +
+ prod.to_simple_string());
+
+ /* give them their own block to work in */
+ out.println(" {");
+
+ /* user supplied code for debug_grammar() */
+ if (debug_grammar != null)
+ out.println(" " +debug_grammar+ "(\"" +
+ prod.to_simple_string() + "\");");
+
+ /* create the result symbol */
+ out.println(" " + pre("result") + " = new " +
+ prod.lhs().the_symbol().stack_type() + "(/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ prod.lhs().the_symbol().index() + ");");
+
+ /* if there is an action string, emit it */
+ if (prod.action() != null && prod.action().code_string() != null &&
+ !prod.action().equals(""))
+ out.println(" " + prod.action().code_string());
+
+ /* end of their block */
+ out.println(" }");
+
+ /* if this was the start production, do action for accept */
+ if (prod == start_prod)
+ {
+ out.println(" /* ACCEPT */");
+ out.println(" " + pre("parser") + ".done_parsing();");
+ }
+
+ /* code to return lhs symbol */
+ out.println(" return " + pre("result") + ";");
+ out.println();
+ }
+
+ /* end of switch */
+ out.println(" /* . . . . . .*/");
+ out.println(" default:");
+ out.println(" throw new Exception(");
+ out.println(" \"Invalid action number found in " +
+ "internal parse table\");");
+ out.println();
+ out.println(" }");
+
+ /* end of method */
+ out.println(" }");
+
+ /* end of class */
+ out.println("};\n");
+
+ action_code_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the production table.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_production_table(PrintStream out)
+ {
+ production all_prods[];
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* do the top of the table */
+ out.println();
+ out.println(" /** production table */");
+ out.println(" protected static final short _production_table[][] = {");
+
+ /* collect up the productions in order */
+ all_prods = new production[production.number()];
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+ all_prods[prod.index()] = prod;
+ }
+
+ /* do one entry per production */
+ out.print(" ");
+ for (int i = 0; i<production.number(); i++)
+ {
+ prod = all_prods[i];
+
+ /* make the table entry */
+ out.print(" {");
+ out.print(/* lhs symbol # */ prod.lhs().the_symbol().index() + ", ");
+ out.print(/* rhs size */ prod.rhs_length() + "}");
+
+ /* put in a comma if we aren't at the end */
+ if (i < production.number()-1) out.print(", ");
+
+ /* 5 entries per line */
+ if ((i+1) % 5 == 0)
+ {
+ out.println();
+ out.print(" ");
+ }
+ }
+
+ /* finish off the table initializer */
+ out.println(" };");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** access to production table */");
+ out.println(" public short[][] production_table() " +
+ "{return _production_table;}");
+
+ production_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the action table.
+ * @param out stream to produce output on.
+ * @param act_tab the internal representation of the action table.
+ * @param compact_reduces do we use the most frequent reduce as default?
+ */
+ protected static void do_action_table(
+ PrintStream out,
+ parse_action_table act_tab,
+ boolean compact_reduces)
+ throws internal_error
+ {
+ parse_action_row row;
+ parse_action act;
+ int red;
+
+ long start_time = System.currentTimeMillis();
+
+ out.println();
+ out.println(" /** parse action table */");
+ out.println(" protected static final short[][] _action_table = {");
+
+ /* do each state (row) of the action table */
+ for (int i = 0; i < act_tab.num_states(); i++)
+ {
+ /* get the row */
+ row = act_tab.under_state[i];
+
+ /* determine the default for the row */
+ if (compact_reduces)
+ row.compute_default();
+ else
+ row.default_reduce = -1;
+
+ out.print(" /*" + i + "*/{");
+
+ /* do each column */
+ for (int j = 0; j < row.size(); j++)
+ {
+ /* extract the action from the table */
+ act = row.under_term[j];
+
+ /* skip error entries these are all defaulted out */
+ if (act.kind() != parse_action.ERROR)
+ {
+ /* first put in the symbol index, then the actual entry */
+
+ /* shifts get positive entries of state number + 1 */
+ if (act.kind() == parse_action.SHIFT)
+ {
+ out.print(j + "," +
+ (((shift_action)act).shift_to().index() + 1) + ",");
+ }
+
+ /* reduce actions get negated entries of production# + 1 */
+ else if (act.kind() == parse_action.REDUCE)
+ {
+ /* if its the default entry let it get defaulted out */
+ red = ((reduce_action)act).reduce_with().index();
+ if (red != row.default_reduce)
+ out.print(j + "," + (-(red+1)) + ",");
+ }
+
+ /* shouldn't be anything else */
+ else
+ throw new internal_error("Unrecognized action code " +
+ act.kind() + " found in parse table");
+ }
+ }
+
+ /* finish off the row with a default entry */
+ if (row.default_reduce != -1)
+ out.println("-1," + (-(row.default_reduce+1)) + "},");
+ else
+ out.println("-1,0},");
+ }
+
+ /* finish off the init of the table */
+ out.println(" };");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** access to parse action table */");
+ out.println(" public short[][] action_table() {return _action_table;}");
+
+ action_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the reduce-goto table.
+ * @param out stream to produce output on.
+ * @param red_tab the internal representation of the reduce-goto table.
+ */
+ protected static void do_reduce_table(
+ PrintStream out,
+ parse_reduce_table red_tab)
+ {
+ lalr_state goto_st;
+ parse_action act;
+
+ long start_time = System.currentTimeMillis();
+
+ out.println();
+ out.println(" /** reduce_goto table */");
+ out.println(" protected static final short[][] _reduce_table = {");
+
+ /* do each row of the reduce-goto table */
+ for (int i=0; i<red_tab.num_states(); i++)
+ {
+ out.print(" /*" + i + "*/{");
+
+ /* do each entry in the row */
+ for (int j=0; j<red_tab.under_state[i].size(); j++)
+ {
+ /* get the entry */
+ goto_st = red_tab.under_state[i].under_non_term[j];
+
+ /* if we have none, skip it */
+ if (goto_st != null)
+ {
+ /* make entries for the index and the value */
+ out.print(j + "," + goto_st.index() + ",");
+ }
+ }
+
+ /* end row with default value */
+ out.println("-1,-1},");
+ }
+
+ /* finish off the init of the table */
+ out.println(" };");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** access to reduce_goto table */");
+ out.println(" public short[][] reduce_table() {return _reduce_table;}");
+ out.println();
+
+ goto_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the parser subclass with embedded tables.
+ * @param out stream to produce output on.
+ * @param action_table internal representation of the action table.
+ * @param reduce_table internal representation of the reduce-goto table.
+ * @param start_st start state of the parse machine.
+ * @param start_prod start production of the grammar.
+ * @param compact_reduces do we use most frequent reduce as default?
+ */
+ public static void parser(
+ PrintStream out,
+ parse_action_table action_table,
+ parse_reduce_table reduce_table,
+ int start_st,
+ production start_prod,
+ boolean compact_reduces)
+ throws internal_error
+ {
+ long start_time = System.currentTimeMillis();
+
+ /* top of file */
+ out.println();
+ out.println("//----------------------------------------------------");
+ out.println("// The following code was generated by " +
+ version.title_str);
+ out.println("// " + new Date());
+ out.println("//----------------------------------------------------");
+ out.println();
+ emit_package(out);
+
+ /* user supplied imports */
+ for (int i = 0; i < import_list.size(); i++)
+ out.println("import " + import_list.elementAt(i) + ";");
+
+ /* class header */
+ out.println();
+ out.println("public class " + parser_class_name +
+ " extends java_cup.runtime.lr_parser {");
+
+ /* constructor */
+ out.println();
+ out.println(" /** constructor */");
+ out.println(" public " + parser_class_name + "() {super();}");
+
+ /* emit the various tables */
+ emit_production_table(out);
+ do_action_table(out, action_table, compact_reduces);
+ do_reduce_table(out, reduce_table);
+
+ /* instance of the action encapsulation class */
+ out.println(" /** instance of action encapsulation class */");
+ out.println(" protected " + pre("actions") + " action_obj;");
+ out.println();
+
+ /* action object initializer */
+ out.println(" /** action encapsulation object initializer */");
+ out.println(" protected void init_actions()");
+ out.println(" {");
+ out.println(" action_obj = new " + pre("actions") + "();");
+ out.println(" }");
+ out.println();
+
+ /* access to action code */
+ out.println(" /** invoke a user supplied parse action */");
+ out.println(" public java_cup.runtime.symbol do_action(");
+ out.println(" int act_num,");
+ out.println(" java_cup.runtime.lr_parser parser,");
+ out.println(" java.util.Stack stack,");
+ out.println(" int top)");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(" /* call code in generated class */");
+ out.println(" return action_obj." + pre("do_action(") +
+ "act_num, parser, stack, top);");
+ out.println(" }");
+ out.println("");
+
+
+ /* method to tell the parser about the start state */
+ out.println(" /** start state */");
+ out.println(" public int start_state() {return " + start_st + ";}");
+
+ /* method to indicate start production */
+ out.println(" /** start production */");
+ out.println(" public int start_production() {return " +
+ start_production.index() + ";}");
+ out.println();
+
+ /* methods to indicate EOF and error symbol indexes */
+ out.println(" /** EOF symbol index */");
+ out.println(" public int EOF_sym() {return " + terminal.EOF.index() +
+ ";}");
+ out.println();
+ out.println(" /** error symbol index */");
+ out.println(" public int error_sym() {return " + terminal.error.index() +
+ ";}");
+ out.println();
+
+ /* user supplied code for user_init() */
+ if (init_code != null)
+ {
+ out.println();
+ out.println(" /** user initialization */");
+ out.println(" public void user_init() throws java.lang.Exception");
+ out.println(" {");
+ out.println(init_code);
+ out.println(" }");
+ }
+
+ /* user supplied code for scan */
+ if (scan_code != null)
+ {
+ out.println();
+ out.println(" /** scan to get the next token */");
+ out.println(" public java_cup.runtime.token scan()");
+ out.println(" throws java.lang.Exception");
+ out.println(" {");
+ out.println(scan_code);
+ out.println(" }");
+ }
+
+ /* user supplied code */
+ if (parser_code != null)
+ {
+ out.println();
+ out.println(parser_code);
+ }
+
+ /* end of class */
+ out.println("};");
+
+ /* put out the action code class */
+ emit_action_code(out, start_prod);
+
+ parser_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*-----------------------------------------------------------*/
+};
diff --git a/tools/dasm/src/java_cup/internal_error.java b/tools/dasm/src/java_cup/internal_error.java
new file mode 100644
index 0000000..2a05b26
--- /dev/null
+++ b/tools/dasm/src/java_cup/internal_error.java
@@ -0,0 +1,22 @@
+
+package java_cup;
+
+/** Exception subclass for reporting internal errors in JavaCup. */
+public class internal_error extends Exception
+ {
+ /** Constructor with a message */
+ public internal_error(String msg)
+ {
+ super(msg);
+ }
+
+ /** Method called to do a forced error exit on an internal error
+ for cases when we can't actually throw the exception. */
+ public void crash()
+ {
+ System.err.println("JavaCUP Fatal Internal Error Detected");
+ System.err.println(getMessage());
+ printStackTrace();
+ System.exit(-1);
+ }
+ };
diff --git a/tools/dasm/src/java_cup/lalr_item.java b/tools/dasm/src/java_cup/lalr_item.java
new file mode 100644
index 0000000..dfa09e1
--- /dev/null
+++ b/tools/dasm/src/java_cup/lalr_item.java
@@ -0,0 +1,329 @@
+package java_cup;
+
+import java.util.Stack;
+
+/** This class represents an LALR item. Each LALR item consists of
+ * a production, a "dot" at a position within that production, and
+ * a set of lookahead symbols (terminal). (The first two of these parts
+ * are provide by the super class). An item is designed to represent a
+ * configuration that the parser may be in. For example, an item of the
+ * form: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * indicates that the parser is in the middle of parsing the production <pre>
+ * A ::= B C d E
+ * </pre>
+ * that B has already been parsed, and that we will expect to see a lookahead
+ * of either a, b, or c once the complete RHS of this production has been
+ * found.<p>
+ *
+ * Items may initially be missing some items from their lookahead sets.
+ * Links are maintained from each item to the set of items that would need
+ * to be updated if symbols are added to its lookahead set. During
+ * "lookahead propagation", we add symbols to various lookahead sets and
+ * propagate these changes across these dependency links as needed.
+ *
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class lalr_item extends lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod the production for the item.
+ * @param pos the position of the "dot" within the production.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, int pos, terminal_set look)
+ throws internal_error
+ {
+ super(prod, pos);
+ _lookahead = look;
+ _propagate_items = new Stack();
+ needs_propagation = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position (dot at start).
+ * @param prod the production for the item.
+ * @param look the set of lookahead symbols.
+ */
+ public lalr_item(production prod, terminal_set look) throws internal_error
+ {
+ this(prod,0,look);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default position and empty lookahead set.
+ * @param prod the production for the item.
+ */
+ public lalr_item(production prod) throws internal_error
+ {
+ this(prod,0,new terminal_set());
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The lookahead symbols of the item. */
+ protected terminal_set _lookahead;
+
+ /** The lookahead symbols of the item. */
+ public terminal_set lookahead() {return _lookahead;};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Links to items that the lookahead needs to be propagated to. */
+ protected Stack _propagate_items;
+
+ /** Links to items that the lookahead needs to be propagated to */
+ public Stack propagate_items() {return _propagate_items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Flag to indicate that this item needs to propagate its lookahead
+ * (whether it has changed or not).
+ */
+ protected boolean needs_propagation;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a new item to the set of items we propagate to. */
+ public void add_propagate(lalr_item prop_to)
+ {
+ _propagate_items.push(prop_to);
+ needs_propagation = true;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Propagate incoming lookaheads through this item to others need to
+ * be changed.
+ * @params incoming symbols to potentially be added to lookahead of this item.
+ */
+ public void propagate_lookaheads(terminal_set incoming) throws internal_error
+ {
+ boolean change = false;
+
+ /* if we don't need to propagate, then bail out now */
+ if (!needs_propagation && (incoming == null || incoming.empty()))
+ return;
+
+ /* if we have null incoming, treat as an empty set */
+ if (incoming != null)
+ {
+ /* add the incoming to the lookahead of this item */
+ change = lookahead().add(incoming);
+ }
+
+ /* if we changed or need it anyway, propagate across our links */
+ if (change || needs_propagation)
+ {
+ /* don't need to propagate again */
+ needs_propagation = false;
+
+ /* propagate our lookahead into each item we are linked to */
+ for (int i = 0; i < propagate_items().size(); i++)
+ ((lalr_item)propagate_items().elementAt(i))
+ .propagate_lookaheads(lookahead());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce the new lalr_item that results from shifting the dot one position
+ * to the right.
+ */
+ public lalr_item shift() throws internal_error
+ {
+ lalr_item result;
+
+ /* can't shift if we have dot already at the end */
+ if (dot_at_end())
+ throw new internal_error("Attempt to shift past end of an lalr_item");
+
+ /* create the new item w/ the dot shifted by one */
+ result = new lalr_item(the_production(), dot_pos()+1,
+ new terminal_set(lookahead()));
+
+ /* change in our lookahead needs to be propagated to this item */
+ add_propagate(result);
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Calculate lookahead representing symbols that could appear after the
+ * symbol that the dot is currently in front of. Note: this routine must
+ * not be invoked before first sets and nullability has been calculated
+ * for all non terminals.
+ */
+ public terminal_set calc_lookahead(terminal_set lookahead_after)
+ throws internal_error
+ {
+ terminal_set result;
+ int pos;
+ production_part part;
+ symbol sym;
+
+ /* sanity check */
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to calculate a lookahead set with a completed item");
+
+ /* start with an empty result */
+ result = new terminal_set();
+
+ /* consider all nullable symbols after the one to the right of the dot */
+ for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* consider what kind of production part it is -- skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal add it in and we are done */
+ if (!sym.is_non_term())
+ {
+ result.add((terminal)sym);
+ return result;
+ }
+ else
+ {
+ /* otherwise add in first set of the non terminal */
+ result.add(((non_terminal)sym).first_set());
+
+ /* if its nullable we continue adding, if not, we are done */
+ if (!((non_terminal)sym).nullable())
+ return result;
+ }
+ }
+ }
+
+ /* if we get here everything past the dot was nullable
+ we add in the lookahead for after the production and we are done */
+ result.add(lookahead_after);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if everything from the symbol one beyond the dot all the
+ * way to the end of the right hand side is nullable. This would indicate
+ * that the lookahead of this item must be included in the lookaheads of
+ * all items produced as a closure of this item. Note: this routine should
+ * not be invoked until after first sets and nullability have been
+ * calculated for all non terminals.
+ */
+ public boolean lookahead_visible() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+
+ /* if the dot is at the end, we have a problem, but the cleanest thing
+ to do is just return true. */
+ if (dot_at_end()) return true;
+
+ /* walk down the rhs and bail if we get a non-nullable symbol */
+ for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
+ {
+ part = the_production().rhs(pos);
+
+ /* skip actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we fail */
+ if (!sym.is_non_term()) return false;
+
+ /* if its not nullable we fail */
+ if (!((non_terminal)sym).nullable()) return false;
+ }
+ }
+
+ /* if we get here its all nullable */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison -- here we only require the cores to be equal since
+ * we need to do sets of items based only on core equality (ignoring
+ * lookahead sets).
+ */
+ public boolean equals(lalr_item other)
+ {
+ if (other == null) return false;
+ return super.equals(other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item))
+ return false;
+ else
+ return equals((lalr_item)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return a hash code -- here we only hash the core since we only test core
+ * matching in LALR items.
+ */
+ public int hashCode()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result = "";
+
+ // additional output for debugging:
+ // result += "(" + hashCode() + ")";
+ result += "[";
+ result += super.toString();
+ result += ", ";
+ if (lookahead() != null)
+ {
+ result += "{";
+ for (int t = 0; t < terminal.number(); t++)
+ if (lookahead().contains(t))
+ result += terminal.find(t).name() + " ";
+ result += "}";
+ }
+ else
+ result += "NULL LOOKAHEAD!!";
+ result += "]";
+
+ // additional output for debugging:
+ // result += " -> ";
+ // for (int i = 0; i<propagate_items().size(); i++)
+ // result += propagate_items().elementAt(i).hashCode() + " ";
+ //
+ // if (needs_propagation) result += " NP";
+
+ return result;
+ }
+ /*-----------------------------------------------------------*/
+};
diff --git a/tools/dasm/src/java_cup/lalr_item_set.java b/tools/dasm/src/java_cup/lalr_item_set.java
new file mode 100644
index 0000000..9abc8db
--- /dev/null
+++ b/tools/dasm/src/java_cup/lalr_item_set.java
@@ -0,0 +1,366 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/** This class represents a set of LALR items. For purposes of building
+ * these sets, items are considered unique only if they have unique cores
+ * (i.e., ignoring differences in their lookahead sets).<p>
+ *
+ * This class provides fairly conventional set oriented operations (union,
+ * sub/super-set tests, etc.), as well as an LALR "closure" operation (see
+ * compute_closure()).
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class lalr_item_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public lalr_item_set() { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other indicates set we should copy from.
+ */
+ public lalr_item_set(lalr_item_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to implement the set. We store the items using themselves
+ * as keys.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cached hashcode for this set. */
+ protected Integer hashcode_cache = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Size of the set */
+ public int size() {return _all.size();}
+
+ /*-----------------------------------------------------------*/
+ /*--- Set Operation Methods ---------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Does the set contain a particular item?
+ * @param itm the item in question.
+ */
+ public boolean contains(lalr_item itm) {return _all.containsKey(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the item in the set matching a particular item (or null if not
+ * found)
+ * @param itm the item we are looking for.
+ */
+ public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) subset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_subset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((lalr_item)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is this set an (improper) superset of another?
+ * @param other the other set in question.
+ */
+ public boolean is_superset_of(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a singleton item, merging lookahead sets if the item is already
+ * part of the set. returns the element of the set that was added or
+ * merged into.
+ * @param itm the item being added.
+ */
+ public lalr_item add(lalr_item itm) throws internal_error
+ {
+ lalr_item other;
+
+ not_null(itm);
+
+ /* see if an item with a matching core is already there */
+ other = (lalr_item)_all.get(itm);
+
+ /* if so, merge this lookahead into the original and leave it */
+ if (other != null)
+ {
+ other.lookahead().add(itm.lookahead());
+ return other;
+ }
+ /* otherwise we just go in the set */
+ else
+ {
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ _all.put(itm,itm);
+ return itm;
+ }
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single item if it is in the set.
+ * @param itm the item to remove.
+ */
+ public void remove(lalr_item itm) throws internal_error
+ {
+ not_null(itm);
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* remove it from hash table implementing set */
+ _all.remove(itm);
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a complete set, merging lookaheads where items are already in
+ * the set
+ * @param other the set to be added.
+ */
+ public void add(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ add((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set to remove.
+ */
+ public void remove(lalr_item_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((lalr_item)e.nextElement());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove and return one item from the set (done in hash order). */
+ public lalr_item get_one() throws internal_error
+ {
+ Enumeration the_set;
+ lalr_item result;
+
+ the_set = all();
+ if (the_set.hasMoreElements())
+ {
+ result = (lalr_item)the_set.nextElement();
+ remove(result);
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function for null test. Throws an interal_error exception if its
+ * parameter is null.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute the closure of the set using the LALR closure rules. Basically
+ * for every item of the form: <pre>
+ * [L ::= a *N alpha, l]
+ * </pre>
+ * (where N is a a non terminal and alpha is a string of symbols) make
+ * sure there are also items of the form: <pre>
+ * [N ::= *beta, first(alpha l)]
+ * </pre>
+ * corresponding to each production of N. Items with identical cores but
+ * differing lookahead sets are merged by creating a new item with the same
+ * core and the union of the lookahead sets (the LA in LALR stands for
+ * "lookahead merged" and this is where the merger is). This routine
+ * assumes that nullability and first sets have been computed for all
+ * productions before it is called.
+ */
+ public void compute_closure()
+ throws internal_error
+ {
+ lalr_item_set consider;
+ lalr_item itm, new_itm, add_itm;
+ non_terminal nt;
+ terminal_set new_lookaheads;
+ Enumeration p;
+ production prod;
+ boolean need_prop;
+
+ /* invalidate cached hashcode */
+ hashcode_cache = null;
+
+ /* each current element needs to be considered */
+ consider = new lalr_item_set(this);
+
+ /* repeat this until there is nothing else to consider */
+ while (consider.size() > 0)
+ {
+ /* get one item to consider */
+ itm = consider.get_one();
+
+ /* do we have a dot before a non terminal */
+ nt = itm.dot_before_nt();
+ if (nt != null)
+ {
+ /* create the lookahead set based on first after dot */
+ new_lookaheads = itm.calc_lookahead(itm.lookahead());
+
+ /* are we going to need to propagate our lookahead to new item */
+ need_prop = itm.lookahead_visible();
+
+ /* create items for each production of that non term */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* create new item with dot at start and that lookahead */
+ new_itm = new lalr_item(prod,new_lookaheads);
+
+ /* add/merge item into the set */
+ add_itm = add(new_itm);
+
+ /* if propagation is needed link to that item */
+ if (need_prop)
+ itm.add_propagate(add_itm);
+
+ /* was this was a new item*/
+ if (add_itm == new_itm)
+ {
+ /* that may need further closure, consider it also */
+ consider.add(new_itm);
+ }
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_item_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw error from here (because superclass doesn't) so crash */
+ e.crash();
+ return false;
+ }
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_item_set))
+ return false;
+ else
+ return equals((lalr_item_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ Enumeration e;
+ int cnt;
+
+ /* only compute a new one if we don't have it cached */
+ if (hashcode_cache == null)
+ {
+ /* hash together codes from at most first 5 elements */
+ for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++)
+ result ^= ((lalr_item)e.nextElement()).hashCode();
+
+ hashcode_cache = new Integer(result);
+ }
+
+ return hashcode_cache.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ StringBuffer result = new StringBuffer();
+
+ result.append("{\n");
+ for (Enumeration e=all(); e.hasMoreElements(); )
+ {
+ result.append(" " + (lalr_item)e.nextElement() + "\n");
+ }
+ result.append("}");
+
+ return result.toString();
+ }
+ /*-----------------------------------------------------------*/
+};
+
diff --git a/tools/dasm/src/java_cup/lalr_state.java b/tools/dasm/src/java_cup/lalr_state.java
new file mode 100644
index 0000000..9782ceb
--- /dev/null
+++ b/tools/dasm/src/java_cup/lalr_state.java
@@ -0,0 +1,749 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Stack;
+
+/** This class represents a state in the LALR viable prefix recognition machine.
+ * A state consists of an LALR item set and a set of transitions to other
+ * states under terminal and non-terminal symbols. Each state represents
+ * a potential configuration of the parser. If the item set of a state
+ * includes an item such as: <pre>
+ * [A ::= B * C d E , {a,b,c}]
+ * </pre>
+ * this indicates that when the parser is in this state it is currently
+ * looking for an A of the given form, has already seen the B, and would
+ * expect to see an a, b, or c after this sequence is complete. Note that
+ * the parser is normally looking for several things at once (represented
+ * by several items). In our example above, the state would also include
+ * items such as: <pre>
+ * [C ::= * X e Z, {d}]
+ * [X ::= * f, {e}]
+ * </pre>
+ * to indicate that it was currently looking for a C followed by a d (which
+ * would be reduced into a C, matching the first symbol in our production
+ * above), and the terminal f followed by e.<p>
+ *
+ * At runtime, the parser uses a viable prefix recognition machine made up
+ * of these states to parse. The parser has two operations, shift and reduce.
+ * In a shift, it consumes one token and makes a transition to a new state.
+ * This corresponds to "moving the dot past" a terminal in one or more items
+ * in the state (these new shifted items will then be found in the state at
+ * the end of the transition). For a reduce operation, the parser is
+ * signifying that it is recognizing the RHS of some production. To do this
+ * it first "backs up" by popping a stack of previously saved states. It
+ * pops off the same number of states as are found in the RHS of the
+ * production. This leaves the machine in the same state is was in when the
+ * parser first attempted to find the RHS. From this state it makes a
+ * transition based on the non-terminal on the LHS of the production. This
+ * corresponds to placing the parse in a configuration equivalent to having
+ * replaced all the symbols from the the input corresponding to the RHS with
+ * the symbol on the LHS.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_transition
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ *
+ */
+
+public class lalr_state {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for building a state from a set of items.
+ * @param itms the set of items that makes up this state.
+ */
+ public lalr_state(lalr_item_set itms) throws internal_error
+ {
+ /* don't allow null or duplicate item sets */
+ if (itms == null)
+ throw new internal_error(
+ "Attempt to construct an LALR state from a null item set");
+
+ if (find_state(itms) != null)
+ throw new internal_error(
+ "Attempt to construct a duplicate LALR state");
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* store the items */
+ _items = itms;
+
+ /* add to the global collection, keyed with its item set */
+ _all.put(_items,this);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Collection of all states. */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Collection of all states. */
+ public static Enumeration all() {return _all.elements();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate total number of states there are. */
+ public static int number() {return _all.size();}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash table to find states by their kernels (i.e, the original,
+ * unclosed, set of items -- which uniquely define the state). This table
+ * stores state objects using (a copy of) their kernel item sets as keys.
+ */
+ protected static Hashtable _all_kernels = new Hashtable();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Find and return state with a given a kernel item set (or null if not
+ * found). The kernel item set is the subset of items that were used to
+ * originally create the state. These items are formed by "shifting the
+ * dot" within items of other states that have a transition to this one.
+ * The remaining elements of this state's item set are added during closure.
+ * @param itms the kernel set of the state we are looking for.
+ */
+ public static lalr_state find_state(lalr_item_set itms)
+ {
+ if (itms == null)
+ return null;
+ else
+ return (lalr_state)_all.get(itms);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for assigning unique state indexes. */
+ protected static int next_index = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The item set for this state. */
+ protected lalr_item_set _items;
+
+ /** The item set for this state. */
+ public lalr_item_set items() {return _items;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** List of transitions out of this state. */
+ protected lalr_transition _transitions = null;
+
+ /** List of transitions out of this state. */
+ public lalr_transition transitions() {return _transitions;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this state in the parse tables */
+ protected int _index;
+
+ /** Index of this state in the parse tables */
+ public int index() {return _index;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper routine for debugging -- produces a dump of the given state
+ * onto System.out.
+ */
+ protected static void dump_state(lalr_state st) throws internal_error
+ {
+ lalr_item_set itms;
+ lalr_item itm;
+ production_part part;
+
+ if (st == null)
+ {
+ System.out.println("NULL lalr_state");
+ return;
+ }
+
+ System.out.println("lalr_state [" + st.index() + "] {");
+ itms = st.items();
+ for (Enumeration e = itms.all(); e.hasMoreElements(); )
+ {
+ itm = (lalr_item)e.nextElement();
+ System.out.print(" [");
+ System.out.print(itm.the_production().lhs().the_symbol().name());
+ System.out.print(" ::= ");
+ for (int i = 0; i<itm.the_production().rhs_length(); i++)
+ {
+ if (i == itm.dot_pos()) System.out.print("(*) ");
+ part = itm.the_production().rhs(i);
+ if (part.is_action())
+ System.out.print("{action} ");
+ else
+ System.out.print(((symbol_part)part).the_symbol().name() + " ");
+ }
+ if (itm.dot_at_end()) System.out.print("(*) ");
+ System.out.println("]");
+ }
+ System.out.println("}");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets through the constructed viable prefix
+ * recognizer. When the machine is constructed, each item that results
+ in the creation of another such that its lookahead is included in the
+ other's will have a propagate link set up for it. This allows additions
+ to the lookahead of one item to be included in other items that it
+ was used to directly or indirectly create.
+ */
+ protected static void propagate_all_lookaheads() throws internal_error
+ {
+ /* iterate across all states */
+ for (Enumeration st = all(); st.hasMoreElements(); )
+ {
+ /* propagate lookaheads out of that state */
+ ((lalr_state)st.nextElement()).propagate_lookaheads();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Add a transition out of this state to another.
+ * @param on_sym the symbol the transition is under.
+ * @param to_st the state the transition goes to.
+ */
+ public void add_transition(symbol on_sym, lalr_state to_st)
+ throws internal_error
+ {
+ lalr_transition trans;
+
+ /* create a new transition object and put it in our list */
+ trans = new lalr_transition(on_sym, to_st, _transitions);
+ _transitions = trans;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Build an LALR viable prefix recognition machine given a start
+ * production. This method operates by first building a start state
+ * from the start production (based on a single item with the dot at
+ * the beginning and EOF as expected lookahead). Then for each state
+ * it attempts to extend the machine by creating transitions out of
+ * the state to new or existing states. When considering extension
+ * from a state we make a transition on each symbol that appears before
+ * the dot in some item. For example, if we have the items: <pre>
+ * [A ::= a b * X c, {d,e}]
+ * [B ::= a b * X d, {a,b}]
+ * </pre>
+ * in some state, then we would be making a transition under X to a new
+ * state. This new state would be formed by a "kernel" of items
+ * corresponding to moving the dot past the X. In this case: <pre>
+ * [A ::= a b X * c, {d,e}]
+ * [B ::= a b X * Y, {a,b}]
+ * </pre>
+ * The full state would then be formed by "closing" this kernel set of
+ * items so that it included items that represented productions of things
+ * the parser was now looking for. In this case we would items
+ * corresponding to productions of Y, since various forms of Y are expected
+ * next when in this state (see lalr_item_set.compute_closure() for details
+ * on closure). <p>
+ *
+ * The process of building the viable prefix recognizer terminates when no
+ * new states can be added. However, in order to build a smaller number of
+ * states (i.e., corresponding to LALR rather than canonical LR) the state
+ * building process does not maintain full loookaheads in all items.
+ * Consequently, after the machine is built, we go back and propagate
+ * lookaheads through the constructed machine using a call to
+ * propagate_all_lookaheads(). This makes use of propagation links
+ * constructed during the closure and transition process.
+ *
+ * @param start_prod the start production of the grammar
+ * @see java_cup.lalr_item_set#compute_closure
+ * @see java_cup.lalr_state#propagate_all_lookaheads
+ */
+
+ public static lalr_state build_machine(production start_prod)
+ throws internal_error
+ {
+ lalr_state start_state;
+ lalr_item_set start_items;
+ lalr_item_set new_items;
+ lalr_item_set linked_items;
+ lalr_item_set kernel;
+ Stack work_stack = new Stack();
+ lalr_state st, new_st;
+ symbol_set outgoing;
+ lalr_item itm, new_itm, existing, fix_itm;
+ symbol sym, sym2;
+ Enumeration i, s, fix;
+
+ /* sanity check */
+ if (start_prod == null)
+ throw new internal_error(
+ "Attempt to build viable prefix recognizer using a null production");
+
+ /* build item with dot at front of start production and EOF lookahead */
+ start_items = new lalr_item_set();
+ itm = new lalr_item(start_prod);
+ itm.lookahead().add(terminal.EOF);
+ start_items.add(itm);
+
+ /* create copy the item set to form the kernel */
+ kernel = new lalr_item_set(start_items);
+
+ /* create the closure from that item set */
+ start_items.compute_closure();
+
+ /* build a state out of that item set and put it in our work set */
+ start_state = new lalr_state(start_items);
+ work_stack.push(start_state);
+
+ /* enter the state using the kernel as the key */
+ _all_kernels.put(kernel, start_state);
+
+ /* continue looking at new states until we have no more work to do */
+ while (!work_stack.empty())
+ {
+ /* remove a state from the work set */
+ st = (lalr_state)work_stack.pop();
+
+ /* gather up all the symbols that appear before dots */
+ outgoing = new symbol_set();
+ for (i = st.items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* add the symbol before the dot (if any) to our collection */
+ sym = itm.symbol_after_dot();
+ if (sym != null) outgoing.add(sym);
+ }
+
+ /* now create a transition out for each individual symbol */
+ for (s = outgoing.all(); s.hasMoreElements(); )
+ {
+ sym = (symbol)s.nextElement();
+
+ /* will be keeping the set of items with propagate links */
+ linked_items = new lalr_item_set();
+
+ /* gather up shifted versions of all the items that have this
+ symbol before the dot */
+ new_items = new lalr_item_set();
+ for (i = st.items().all(); i.hasMoreElements();)
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* if this is the symbol we are working on now, add to set */
+ sym2 = itm.symbol_after_dot();
+ if (sym.equals(sym2))
+ {
+ /* add to the kernel of the new state */
+ new_items.add(itm.shift());
+
+ /* remember that itm has propagate link to it */
+ linked_items.add(itm);
+ }
+ }
+
+ /* use new items as state kernel */
+ kernel = new lalr_item_set(new_items);
+
+ /* have we seen this one already? */
+ new_st = (lalr_state)_all_kernels.get(kernel);
+
+ /* if we haven't, build a new state out of the item set */
+ if (new_st == null)
+ {
+ /* compute closure of the kernel for the full item set */
+ new_items.compute_closure();
+
+ /* build the new state */
+ new_st = new lalr_state(new_items);
+
+ /* add the new state to our work set */
+ work_stack.push(new_st);
+
+ /* put it in our kernel table */
+ _all_kernels.put(kernel, new_st);
+ }
+ /* otherwise relink propagation to items in existing state */
+ else
+ {
+ /* walk through the items that have links to the new state */
+ for (fix = linked_items.all(); fix.hasMoreElements(); )
+ {
+ fix_itm = (lalr_item)fix.nextElement();
+
+ /* look at each propagate link out of that item */
+ for (int l =0; l < fix_itm.propagate_items().size(); l++)
+ {
+ /* pull out item linked to in the new state */
+ new_itm =
+ (lalr_item)fix_itm.propagate_items().elementAt(l);
+
+ /* find corresponding item in the existing state */
+ existing = new_st.items().find(new_itm);
+
+ /* fix up the item so it points to the existing set */
+ if (existing != null)
+ fix_itm.propagate_items().setElementAt(existing ,l);
+ }
+ }
+ }
+
+ /* add a transition from current state to that state */
+ st.add_transition(sym, new_st);
+ }
+ }
+
+ /* all done building states */
+
+ /* propagate complete lookahead sets throughout the states */
+ propagate_all_lookaheads();
+
+ return start_state;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Propagate lookahead sets out of this state. This recursively
+ * propagates to all items that have propagation links from some item
+ * in this state.
+ */
+ protected void propagate_lookaheads() throws internal_error
+ {
+ /* recursively propagate out from each item in the state */
+ for (Enumeration itm = items().all(); itm.hasMoreElements(); )
+ ((lalr_item)itm.nextElement()).propagate_lookaheads(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fill in the parse table entries for this state. There are two
+ * parse tables that encode the viable prefix recognition machine, an
+ * action table and a reduce-goto table. The rows in each table
+ * correspond to states of the machine. The columns of the action table
+ * are indexed by terminal symbols and correspond to either transitions
+ * out of the state (shift entries) or reductions from the state to some
+ * previous state saved on the stack (reduce entries). All entries in the
+ * action table that are not shifts or reduces, represent errors. The
+ * reduce-goto table is indexed by non terminals and represents transitions
+ * out of a state on that non-terminal.<p>
+ * Conflicts occur if more than one action needs to go in one entry of the
+ * action table (this cannot happen with the reduce-goto table). Conflicts
+ * are resolved by always shifting for shift/reduce conflicts and choosing
+ * the lowest numbered production (hence the one that appeared first in
+ * the specification) in reduce/reduce conflicts. All conflicts are
+ * reported and if more conflicts are detected than were declared by the
+ * user, code generation is aborted.
+ *
+ * @param act_table the action table to put entries in.
+ * @param reduce_table the reduce-goto table to put entries in.
+ */
+ public void build_table_entries(
+ parse_action_table act_table,
+ parse_reduce_table reduce_table)
+ throws internal_error
+ {
+ parse_action_row our_act_row;
+ parse_reduce_row our_red_row;
+ lalr_item itm;
+ parse_action act, other_act;
+ symbol sym;
+ boolean conflicted = false;
+
+ /* pull out our rows from the tables */
+ our_act_row = act_table.under_state[index()];
+ our_red_row = reduce_table.under_state[index()];
+
+ /* consider each item in our state */
+ for (Enumeration i = items().all(); i.hasMoreElements(); )
+ {
+ itm = (lalr_item)i.nextElement();
+
+ /* if its completed (dot at end) then reduce under the lookahead */
+ if (itm.dot_at_end())
+ {
+ act = new reduce_action(itm.the_production());
+
+ /* consider each lookahead symbol */
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ /* skip over the ones not in the lookahead */
+ if (!itm.lookahead().contains(t)) continue;
+
+ /* if we don't already have an action put this one in */
+ if (our_act_row.under_term[t].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[t] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ conflicted = true;
+
+ other_act = our_act_row.under_term[t];
+
+ /* if the other act was not a shift */
+ if (other_act.kind() != parse_action.SHIFT)
+ {
+ /* if we have lower index hence priority, replace it*/
+ if (itm.the_production().index() <
+ ((reduce_action)other_act).reduce_with().index())
+ {
+ /* replace the action */
+ our_act_row.under_term[t] = act;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* consider each outgoing transition */
+ for (lalr_transition trans=transitions(); trans!=null; trans=trans.next())
+ {
+ /* if its on an terminal add a shift entry */
+ sym = trans.on_symbol();
+ if (!sym.is_non_term())
+ {
+ act = new shift_action(trans.to_state());
+
+ /* if we don't already have an action put this one in */
+ if ( our_act_row.under_term[sym.index()].kind() ==
+ parse_action.ERROR)
+ {
+ our_act_row.under_term[sym.index()] = act;
+ }
+ else
+ {
+ /* we now have at least one conflict */
+ conflicted = true;
+
+ /* shift always wins */
+ our_act_row.under_term[sym.index()] = act;
+ }
+ }
+ else
+ {
+ /* for non terminals add an entry to the reduce-goto table */
+ our_red_row.under_non_term[sym.index()] = trans.to_state();
+ }
+ }
+
+ /* if we end up with conflict(s), report them */
+ if (conflicted)
+ report_conflicts();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce warning messages for all conflicts found in this state. */
+ protected void report_conflicts()
+ throws internal_error
+ {
+ lalr_item itm, compare;
+ symbol shift_sym;
+ terminal_set conflict_set;
+ boolean after_itm;
+
+ /* consider each element */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* clear the S/R conflict set for this item */
+ conflict_set = new terminal_set();
+
+ /* if it results in a reduce, it could be a conflict */
+ if (itm.dot_at_end())
+ {
+ /* not yet after itm */
+ after_itm = false;
+
+ /* compare this item against all others looking for conflicts */
+ for (Enumeration comps = items().all(); comps.hasMoreElements(); )
+ {
+ compare = (lalr_item)comps.nextElement();
+
+ /* if this is the item, next one is after it */
+ if (itm == compare) after_itm = true;
+
+ /* only look at it if its not the same item */
+ if (itm != compare)
+ {
+ /* is it a reduce */
+ if (compare.dot_at_end())
+ {
+ /* only look at reduces after itm */
+ if (after_itm)
+ /* does the comparison item conflict? */
+ if (compare.lookahead().intersects(itm.lookahead()))
+ /* report a reduce/reduce conflict */
+ report_reduce_reduce(itm, compare);
+ }
+ /* must be a shift on a terminal or non-terminal */
+ else
+ {
+ /* is it a shift on a terminal */
+ shift_sym = compare.symbol_after_dot();
+ if (!shift_sym.is_non_term())
+ {
+ /* does the terminal conflict with our item */
+ if (itm.lookahead().contains((terminal)shift_sym))
+ /* remember the terminal symbol in conflict */
+ conflict_set.add((terminal)shift_sym);
+ }
+ }
+ }
+ }
+ /* report S/R conflicts under all the symbols we conflict under */
+ for (int t = 0; t < terminal.number(); t++)
+ if (conflict_set.contains(t))
+ report_shift_reduce(itm,t);
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one reduce/reduce conflict.
+ *
+ * @param itm1 first item in conflict.
+ * @param itm2 second item in conflict.
+ */
+ protected void report_reduce_reduce(lalr_item itm1, lalr_item itm2)
+ throws internal_error
+ {
+ boolean comma_flag = false;
+
+ System.err.println("*** Reduce/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(itm1.to_simple_string());
+ System.err.print (" and ");
+ System.err.println(itm2.to_simple_string());
+ System.err.print(" under symbols: {" );
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (itm1.lookahead().contains(t) && itm2.lookahead().contains(t))
+ {
+ if (comma_flag) System.err.print(", "); else comma_flag = true;
+ System.err.print(terminal.find(t).name());
+ }
+ }
+ System.err.println("}");
+ System.err.print(" Resolved in favor of ");
+ if (itm1.the_production().index() < itm2.the_production().index())
+ System.err.println("the first production.\n");
+ else
+ System.err.println("the second production.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a warning message for one shift/reduce conflict.
+ *
+ * @param red_itm the item with the reduce.
+ * @param conflict_sym the index of the symbol conflict occurs under.
+ */
+ protected void report_shift_reduce(
+ lalr_item red_itm,
+ int conflict_sym)
+ throws internal_error
+ {
+ lalr_item itm;
+ symbol shift_sym;
+
+ /* emit top part of message including the reduce item */
+ System.err.println("*** Shift/Reduce conflict found in state #"+index());
+ System.err.print (" between ");
+ System.err.println(red_itm.to_simple_string());
+
+ /* find and report on all items that shift under our conflict symbol */
+ for (Enumeration itms = items().all(); itms.hasMoreElements(); )
+ {
+ itm = (lalr_item)itms.nextElement();
+
+ /* only look if its not the same item and not a reduce */
+ if (itm != red_itm && !itm.dot_at_end())
+ {
+ /* is it a shift on our conflicting terminal */
+ shift_sym = itm.symbol_after_dot();
+ if (!shift_sym.is_non_term() && shift_sym.index() == conflict_sym)
+ {
+ /* yes, report on it */
+ System.err.println(" and " + itm.to_simple_string());
+ }
+ }
+ }
+ System.err.println(" under symbol "+ terminal.find(conflict_sym).name());
+ System.err.println(" Resolved in favor of shifting.\n");
+
+ /* count the conflict */
+ emit.num_conflicts++;
+ lexer.warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lalr_state other)
+ {
+ /* we are equal if our item sets are equal */
+ return other != null && items().equals(other.items());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lalr_state))
+ return false;
+ else
+ return equals((lalr_state)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use the item set hash code */
+ return items().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_transition tr;
+
+ /* dump the item set */
+ result = "lalr_state [" + index() + "]: " + _items + "\n";
+
+ /* do the transitions */
+ for (tr = transitions(); tr != null; tr = tr.next())
+ {
+ result += tr;
+ result += "\n";
+ }
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+};
diff --git a/tools/dasm/src/java_cup/lalr_transition.java b/tools/dasm/src/java_cup/lalr_transition.java
new file mode 100644
index 0000000..5e5075c
--- /dev/null
+++ b/tools/dasm/src/java_cup/lalr_transition.java
@@ -0,0 +1,93 @@
+package java_cup;
+
+/** This class represents a transition in an LALR viable prefix recognition
+ * machine. Transitions can be under terminals for non-terminals. They are
+ * internally linked together into singly linked lists containing all the
+ * transitions out of a single state via the _next field.
+ *
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ *
+ */
+public class lalr_transition {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ * @param nxt next transition in linked list.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st, lalr_transition nxt)
+ throws internal_error
+ {
+ /* sanity checks */
+ if (on_sym == null)
+ throw new internal_error("Attempt to create transition on null symbol");
+ if (to_st == null)
+ throw new internal_error("Attempt to create transition to null state");
+
+ /* initialize */
+ _on_symbol = on_sym;
+ _to_state = to_st;
+ _next = nxt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with null next.
+ * @param on_sym symbol we are transitioning on.
+ * @param to_st state we transition to.
+ */
+ public lalr_transition(symbol on_sym, lalr_state to_st) throws internal_error
+ {
+ this(on_sym, to_st, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol we make the transition on. */
+ protected symbol _on_symbol;
+
+ /** The symbol we make the transition on. */
+ public symbol on_symbol() {return _on_symbol;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The state we transition to. */
+ protected lalr_state _to_state;
+
+ /** The state we transition to. */
+ public lalr_state to_state() {return _to_state;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Next transition in linked list of transitions out of a state */
+ protected lalr_transition _next;
+
+ /** Next transition in linked list of transitions out of a state */
+ public lalr_transition next() {return _next;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ result = "transition on " + on_symbol().name() + " to state [";
+ result += _to_state.index();
+ result += "]";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+};
diff --git a/tools/dasm/src/java_cup/lexer.java b/tools/dasm/src/java_cup/lexer.java
new file mode 100644
index 0000000..2b0a056
--- /dev/null
+++ b/tools/dasm/src/java_cup/lexer.java
@@ -0,0 +1,475 @@
+package java_cup;
+
+import java.util.Hashtable;
+
+import java_cup.runtime.str_token;
+import java_cup.runtime.token;
+
+/** This class implements a small scanner (aka lexical analyzer or lexer) for
+ * the JavaCup specification. This scanner reads characters from standard
+ * input (System.in) and returns integers corresponding to the terminal
+ * number of the next token. Once end of input is reached the EOF token is
+ * returned on every subsequent call.<p>
+ * Tokens currently returned include: <pre>
+ * Symbol Constant Returned Symbol Constant Returned
+ * ------ ----------------- ------ -----------------
+ * "package" PACKAGE "import" IMPORT
+ * "code" CODE "action" ACTION
+ * "parser" PARSER "terminal" TERMINAL
+ * "non" NON "init" INIT
+ * "scan" SCAN "with" WITH
+ * "start" START ; SEMI
+ * , COMMA * STAR
+ * . DOT : COLON
+ * ::= COLON_COLON_EQUALS | BAR
+ * identifier ID {:...:} CODE_STRING
+ * "debug" DEBUG
+ * </pre>
+ * All symbol constants are defined in sym.java which is generated by
+ * JavaCup from parser.cup.<p>
+ *
+ * In addition to the scanner proper (called first via init() then with
+ * next_token() to get each token) this class provides simple error and
+ * warning routines and keeps a count of errors and warnings that is
+ * publicly accessible.<p>
+ *
+ * This class is "static" (i.e., it has only static members and methods).
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class lexer {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The only constructor is private, so no instances can be created. */
+ private lexer() { }
+
+ /*-----------------------------------------------------------*/
+ /*--- Static (Class) Variables ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** First character of lookahead. */
+ protected static int next_char;
+
+ /** Second character of lookahead. */
+ protected static int next_char2;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** EOF constant. */
+ protected static final int EOF_CHAR = -1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of keywords. Keywords are initially treated as identifiers.
+ * Just before they are returned we look them up in this table to see if
+ * they match one of the keywords. The string of the name is the key here,
+ * which indexes Integer objects holding the symbol number.
+ */
+ protected static Hashtable keywords = new Hashtable(23);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of single character symbols. For ease of implementation, we
+ * store all unambiguous single character tokens in this table of Integer
+ * objects keyed by Integer objects with the numerical value of the
+ * appropriate char (currently Character objects have a bug which precludes
+ * their use in tables).
+ */
+ protected static Hashtable char_symbols = new Hashtable(11);
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Current line number for use in error messages. */
+ protected static int current_line = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int current_position = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of total errors detected so far. */
+ public static int error_count = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of warnings issued so far */
+ public static int warning_count = 0;
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Initialize the scanner. This sets up the keywords and char_symbols
+ * tables and reads the first two characters of lookahead.
+ */
+ public static void init() throws java.io.IOException
+ {
+ /* set up the keyword table */
+ keywords.put("package", new Integer(sym.PACKAGE));
+ keywords.put("import", new Integer(sym.IMPORT));
+ keywords.put("code", new Integer(sym.CODE));
+ keywords.put("action", new Integer(sym.ACTION));
+ keywords.put("parser", new Integer(sym.PARSER));
+ keywords.put("terminal", new Integer(sym.TERMINAL));
+ keywords.put("non", new Integer(sym.NON));
+ keywords.put("init", new Integer(sym.INIT));
+ keywords.put("scan", new Integer(sym.SCAN));
+ keywords.put("with", new Integer(sym.WITH));
+ keywords.put("start", new Integer(sym.START));
+ keywords.put("debug", new Integer(sym.DEBUG));
+
+ /* set up the table of single character symbols */
+ char_symbols.put(new Integer(';'), new Integer(sym.SEMI));
+ char_symbols.put(new Integer(','), new Integer(sym.COMMA));
+ char_symbols.put(new Integer('*'), new Integer(sym.STAR));
+ char_symbols.put(new Integer('.'), new Integer(sym.DOT));
+ char_symbols.put(new Integer('|'), new Integer(sym.BAR));
+
+ /* read two characters of lookahead */
+ next_char = System.in.read();
+ if (next_char == EOF_CHAR)
+ next_char2 = EOF_CHAR;
+ else
+ next_char2 = System.in.read();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance the scanner one character in the input stream. This moves
+ * next_char2 to next_char and then reads a new next_char2.
+ */
+ protected static void advance() throws java.io.IOException
+ {
+ int old_char;
+
+ old_char = next_char;
+ next_char = next_char2;
+ if (next_char == EOF_CHAR)
+ next_char2 = EOF_CHAR;
+ else
+ next_char2 = System.in.read();
+
+ /* count this */
+ current_position++;
+ if (old_char == '\n')
+ {
+ current_line++;
+ current_position = 1;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit an error message. The message will be marked with both the
+ * current line number and the position in the line. Error messages
+ * are printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_error(String message)
+ {
+ System.err.println("Error at " + current_line + "(" + current_position +
+ "): " + message);
+ error_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a warning message. The message will be marked with both the
+ * current line number and the position in the line. Messages are
+ * printed on standard error (System.err).
+ * @param message the message to print.
+ */
+ public static void emit_warn(String message)
+ {
+ System.err.println("Warning at " + current_line + "(" + current_position +
+ "): " + message);
+ warning_count++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok to start an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_start_char(int ch)
+ {
+ return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch == '_');
+
+ // later need to deal with non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character is ok for the middle of an id.
+ * @param ch the character in question.
+ */
+ protected static boolean id_char(int ch)
+ {
+ return id_start_char(ch) || (ch >= '0' && ch <= '9');
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Try to look up a single character symbol, returns -1 for not found.
+ * @param ch the character in question.
+ */
+ protected static int find_single_char(int ch)
+ {
+ Integer result;
+
+ result = (Integer)char_symbols.get(new Integer((char)ch));
+ if (result == null)
+ return -1;
+ else
+ return result.intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Handle swallowing up a comment. Both old style C and new style C++
+ * comments are handled.
+ */
+ protected static void swallow_comment() throws java.io.IOException
+ {
+ /* next_char == '/' at this point */
+
+ /* is it a traditional comment */
+ if (next_char2 == '*')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow the comment until end of comment or EOF */
+ for (;;)
+ {
+ /* if its EOF we have an error */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a comment");
+ return;
+ }
+
+ /* if we can see the closer we are done */
+ if (next_char == '*' && next_char2 == '/')
+ {
+ advance();
+ advance();
+ return;
+ }
+
+ /* otherwise swallow char and move on */
+ advance();
+ }
+ }
+
+ /* is its a new style comment */
+ if (next_char2 == '/')
+ {
+ /* swallow the opener */
+ advance(); advance();
+
+ /* swallow to '\n', '\f', or EOF */
+ while (next_char != '\n' && next_char != '\f' && next_char!=EOF_CHAR)
+ advance();
+
+ return;
+
+ }
+
+ /* shouldn't get here, but... if we get here we have an error */
+ emit_error("Malformed comment in specification -- ignored");
+ advance();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Swallow up a code string. Code strings begin with "{:" and include
+ all characters up to the first occurrence of ":}" (there is no way to
+ include ":}" inside a code string). The routine returns an str_token
+ object suitable for return by the scanner.
+ */
+ protected static token do_code_string() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+
+ /* at this point we have lookahead of "{:" -- swallow that */
+ advance(); advance();
+
+ /* save chars until we see ":}" */
+ while (!(next_char == ':' && next_char2 == '}'))
+ {
+ /* if we have run off the end issue a message and break out of loop */
+ if (next_char == EOF_CHAR)
+ {
+ emit_error("Specification file ends inside a code string");
+ break;
+ }
+
+ /* otherwise record the char and move on */
+ result.append(new Character((char)next_char));
+ advance();
+ }
+
+ /* advance past the closer and build a return token */
+ advance(); advance();
+ return new str_token(sym.CODE_STRING, result.toString());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Process an identifier. Identifiers begin with a letter, underscore,
+ * or dollar sign, which is followed by zero or more letters, numbers,
+ * underscores or dollar signs. This routine returns an str_token suitable
+ * for return by the scanner.
+ */
+ protected static token do_id() throws java.io.IOException
+ {
+ StringBuffer result = new StringBuffer();
+ String result_str;
+ Integer keyword_num;
+ char buffer[] = new char[1];
+
+ /* next_char holds first character of id */
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+
+ /* collect up characters while they fit in id */
+ while(id_char(next_char))
+ {
+ buffer[0] = (char)next_char;
+ result.append(buffer,0,1);
+ advance();
+ }
+
+ /* extract a string and try to look it up as a keyword */
+ result_str = result.toString();
+ keyword_num = (Integer)keywords.get(result_str);
+
+ /* if we found something, return that keyword */
+ if (keyword_num != null)
+ return new token(keyword_num.intValue());
+
+ /* otherwise build and return an id token with an attached string */
+ return new str_token(sym.ID, result_str);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return one token. This is the main external interface to the scanner.
+ * It consumes sufficient characters to determine the next input token
+ * and returns it. To help with debugging, this routine actually calls
+ * real_next_token() which does the work. If you need to debug the
+ * parser, this can be changed to call debug_next_token() which prints
+ * a debugging message before returning the token.
+ */
+ public static token next_token() throws java.io.IOException
+ {
+ return real_next_token();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Debugging version of next_token(). This routine calls the real scanning
+ * routine, prints a message on System.out indicating what the token is,
+ * then returns it.
+ */
+ public static token debug_next_token() throws java.io.IOException
+ {
+ token result = real_next_token();
+ System.out.println("# next_token() => " + result.sym);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The actual routine to return one token. This is normally called from
+ * next_token(), but for debugging purposes can be called indirectly from
+ * debug_next_token().
+ */
+ protected static token real_next_token() throws java.io.IOException
+ {
+ int sym_num;
+
+ for (;;)
+ {
+ /* look for white space */
+ if (next_char == ' ' || next_char == '\t' || next_char == '\n' ||
+ next_char == '\f' || next_char == '\r')
+ {
+ /* advance past it and try the next character */
+ advance();
+ continue;
+ }
+
+ /* look for a single character symbol */
+ sym_num = find_single_char(next_char);
+ if (sym_num != -1)
+ {
+ /* found one -- advance past it and return a token for it */
+ advance();
+ return new token(sym_num);
+ }
+
+ /* look for : or ::= */
+ if (next_char == ':')
+ {
+ /* if we don't have a second ':' return COLON */
+ if (next_char2 != ':')
+ {
+ advance();
+ return new token(sym.COLON);
+ }
+
+ /* move forward and look for the '=' */
+ advance();
+ if (next_char2 == '=')
+ {
+ advance(); advance();
+ return new token(sym.COLON_COLON_EQUALS);
+ }
+ else
+ {
+ /* return just the colon (already consumed) */
+ return new token(sym.COLON);
+ }
+ }
+
+ /* look for a comment */
+ if (next_char == '/' && (next_char2 == '*' || next_char2 == '/'))
+ {
+ /* swallow then continue the scan */
+ swallow_comment();
+ continue;
+ }
+
+ /* look for start of code string */
+ if (next_char == '{' && next_char2 == ':')
+ return do_code_string();
+
+ /* look for an id or keyword */
+ if (id_start_char(next_char)) return do_id();
+
+ /* look for EOF */
+ if (next_char == EOF_CHAR) return new token(sym.EOF);
+
+ /* if we get here, we have an unrecognized character */
+ emit_warn("Unrecognized character '" +
+ new Character((char)next_char) + "'(" + next_char +
+ ") -- ignored");
+
+ /* advance past it */
+ advance();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+};
+
diff --git a/tools/dasm/src/java_cup/lr_item_core.java b/tools/dasm/src/java_cup/lr_item_core.java
new file mode 100644
index 0000000..164bf4e
--- /dev/null
+++ b/tools/dasm/src/java_cup/lr_item_core.java
@@ -0,0 +1,270 @@
+
+package java_cup;
+
+/** The "core" of an LR item. This includes a production and the position
+ * of a marker (the "dot") within the production. Typically item cores
+ * are written using a production with an embedded "dot" to indicate their
+ * position. For example: <pre>
+ * A ::= B * C d E
+ * </pre>
+ * This represents a point in a parse where the parser is trying to match
+ * the given production, and has succeeded in matching everything before the
+ * "dot" (and hence is expecting to see the symbols after the dot next). See
+ * lalr_item, lalr_item_set, and lalr_start for full details on the meaning
+ * and use of items.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+*/
+
+public class lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod production this item uses.
+ * @param pos position of the "dot" within the item.
+ */
+ public lr_item_core(production prod, int pos) throws internal_error
+ {
+ symbol after_dot = null;
+ production_part part;
+
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a null production");
+
+ _the_production = prod;
+
+ if (pos < 0 || pos > _the_production.rhs_length())
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a bad dot position");
+
+ _dot_pos = pos;
+
+ /* compute and cache hash code now */
+ _core_hash_cache = 13*_the_production.hashCode() + pos;
+
+ /* cache the symbol after the dot */
+ if (_dot_pos < _the_production.rhs_length())
+ {
+ part = _the_production.rhs(_dot_pos);
+ if (!part.is_action())
+ _symbol_after_dot = ((symbol_part)part).the_symbol();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for dot at start of right hand side.
+ * @param prod production this item uses.
+ */
+ public lr_item_core(production prod) throws internal_error
+ {
+ this(prod,0);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production for the item. */
+ protected production _the_production;
+
+ /** The production for the item. */
+ public production the_production() {return _the_production;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ protected int _dot_pos;
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ public int dot_pos() {return _dot_pos;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of the hash code. */
+ protected int _core_hash_cache;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of symbol after the dot. */
+ protected symbol _symbol_after_dot = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the dot at the end of the production? */
+ public boolean dot_at_end()
+ {
+ return _dot_pos >= _the_production.rhs_length();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the symbol after the dot. If there is no symbol after the dot
+ * we return null. */
+ public symbol symbol_after_dot()
+ {
+ /* use the cached symbol */
+ return _symbol_after_dot;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we have a dot before a non terminal, and if so which one
+ * (return null or the non terminal).
+ */
+ public non_terminal dot_before_nt()
+ {
+ symbol sym;
+
+ /* get the symbol after the dot */
+ sym = symbol_after_dot();
+
+ /* if it exists and is a non terminal, return it */
+ if (sym != null && sym.is_non_term())
+ return (non_terminal)sym;
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a new lr_item_core that results from shifting the dot one
+ * position to the right.
+ */
+ public lr_item_core shift_core() throws internal_error
+ {
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to shift past end of an lr_item_core");
+
+ return new lr_item_core(_the_production, _dot_pos+1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for the core only. This is separate out because we
+ * need separate access in a super class.
+ */
+ public boolean core_equals(lr_item_core other)
+ {
+ return other != null &&
+ _the_production.equals(other._the_production) &&
+ _dot_pos == other._dot_pos;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lr_item_core other) {return core_equals(other);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lr_item_core))
+ return false;
+ else
+ return equals((lr_item_core)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the core (separated so we keep non overridden version). */
+ public int core_hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the item. */
+ public int hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string (separated out from toString() so we can call it
+ * from subclass that overrides toString()).
+ */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+ production_part part;
+
+ if (_the_production.lhs() != null &&
+ _the_production.lhs().the_symbol() != null &&
+ _the_production.lhs().the_symbol().name() != null)
+ result = _the_production.lhs().the_symbol().name();
+ else
+ result = "$$NULL$$";
+
+ result += " ::= ";
+
+ for (int i = 0; i<_the_production.rhs_length(); i++)
+ {
+ /* do we need the dot before this one? */
+ if (i == _dot_pos)
+ result += "(*) ";
+
+ /* print the name of the part */
+ if (_the_production.rhs(i) == null)
+ {
+ result += "$$NULL$$ ";
+ }
+ else
+ {
+ part = _the_production.rhs(i);
+ if (part == null)
+ result += "$$NULL$$ ";
+ else if (part.is_action())
+ result += "{ACTION} ";
+ else if (((symbol_part)part).the_symbol() != null &&
+ ((symbol_part)part).the_symbol().name() != null)
+ result += ((symbol_part)part).the_symbol().name() + " ";
+ else
+ result += "$$NULL$$ ";
+ }
+ }
+
+ /* put the dot after if needed */
+ if (_dot_pos == _the_production.rhs_length())
+ result += "(*) ";
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string */
+ public String toString()
+ {
+ /* can't throw here since super class doesn't, so we crash instead */
+ try {
+ return to_simple_string();
+ } catch(internal_error e) {
+ e.crash();
+ return null;
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
diff --git a/tools/dasm/src/java_cup/non_terminal.java b/tools/dasm/src/java_cup/non_terminal.java
new file mode 100644
index 0000000..db7fff0
--- /dev/null
+++ b/tools/dasm/src/java_cup/non_terminal.java
@@ -0,0 +1,280 @@
+package java_cup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/** This class represents a non-terminal symbol in the grammar. Each
+ * non terminal has a textual name, an index, and a string which indicates
+ * the type of object it will be implemented with at runtime (i.e. the class
+ * of object that will be pushed on the parse stack to represent it).
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class non_terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the non terminal.
+ * @param tp the type string for the non terminal.
+ */
+ public non_terminal(String nm, String tp)
+ {
+ /* super class does most of the work */
+ super(nm, tp);
+
+ /* add to set of all non terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an exception here because these are used in static
+ // initializers, so we crash instead
+ // was:
+ // throw new internal_error("Duplicate non-terminal ("+nm+") created");
+ (new internal_error("Duplicate non-terminal ("+nm+") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the non terminal.
+ */
+ public non_terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all non-terminals -- elements are stored using name strings
+ * as the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all non-terminals. */
+ public static Enumeration all() {return _all.elements();};
+
+ /** lookup a non terminal by name string */
+ public static non_terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (non_terminal)_all.get(with_name);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of non-terminals. */
+ public static int number() {return _all.size();};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique indexes. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter for creating unique non-terminal names */
+ static protected int next_nt = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special non-terminal for start symbol */
+ public static final non_terminal START_nt = new non_terminal("$START");
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Method for creating a new uniquely named hidden non-terminal using
+ * the given string as a base for the name (or "NT$" if null is passed).
+ * @param prefix base name to construct unique name from.
+ */
+ static non_terminal create_new(String prefix) throws internal_error
+ {
+ if (prefix == null) prefix = "NT$";
+ return new non_terminal(prefix + next_nt++);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** static routine for creating a new uniquely named hidden non-terminal */
+ static non_terminal create_new() throws internal_error
+ {
+ return create_new(null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute nullability of all non-terminals. */
+ public static void compute_nullability() throws internal_error
+ {
+ boolean change = true;
+ non_terminal nt;
+ Enumeration e;
+ production prod;
+
+ /* repeat this process until there is no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (e=all(); e.hasMoreElements(); )
+ {
+ nt = (non_terminal)e.nextElement();
+
+ /* only look at things that aren't already marked nullable */
+ if (!nt.nullable())
+ {
+ if (nt.looks_nullable())
+ {
+ nt._nullable = true;
+ change = true;
+ }
+ }
+ }
+ }
+
+ /* do one last pass over the productions to finalize all of them */
+ for (e=production.all(); e.hasMoreElements(); )
+ {
+ prod = (production)e.nextElement();
+ prod.set_nullable(prod.check_nullable());
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute first sets for all non-terminals. This assumes nullability has
+ * already computed.
+ */
+ public static void compute_first_sets() throws internal_error
+ {
+ boolean change = true;
+ Enumeration n;
+ Enumeration p;
+ non_terminal nt;
+ production prod;
+ terminal_set prod_first;
+
+ /* repeat this process until we have no change */
+ while (change)
+ {
+ /* look for a new change */
+ change = false;
+
+ /* consider each non-terminal */
+ for (n = all(); n.hasMoreElements(); )
+ {
+ nt = (non_terminal)n.nextElement();
+
+ /* consider every production of that non terminal */
+ for (p = nt.productions(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* get the updated first of that production */
+ prod_first = prod.check_first_set();
+
+ /* if this going to add anything, add it */
+ if (!prod_first.is_subset_of(nt._first_set))
+ {
+ change = true;
+ nt._first_set.add(prod_first);
+ }
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all productions with this non terminal on the LHS. */
+ protected Hashtable _productions = new Hashtable(11);
+
+ /** Access to productions with this non terminal on the LHS. */
+ public Enumeration productions() {return _productions.elements();};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions with this non terminal on the LHS. */
+ public int num_productions() {return _productions.size();};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a production to our set of productions. */
+ public void add_production(production prod) throws internal_error
+ {
+ /* catch improper productions */
+ if (prod == null || prod.lhs() == null || prod.lhs().the_symbol() != this)
+ throw new internal_error(
+ "Attempt to add invalid production to non terminal production table");
+
+ /* add it to the table, keyed with itself */
+ _productions.put(prod,prod);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of this non terminal. */
+ protected boolean _nullable;
+
+ /** Nullability of this non terminal. */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set for this non-terminal. */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set for this non-terminal. */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate that this symbol is a non-terminal. */
+ public boolean is_non_term()
+ {
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Test to see if this non terminal currently looks nullable. */
+ protected boolean looks_nullable() throws internal_error
+ {
+ /* look and see if any of the productions now look nullable */
+ for (Enumeration e = productions(); e.hasMoreElements(); )
+ /* if the production can go to empty, we are nullable */
+ if (((production)e.nextElement()).check_nullable())
+ return true;
+
+ /* none of the productions can go to empty, so we are not nullable */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** convert to string */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]" + (nullable() ? "*" : "");
+ }
+
+ /*-----------------------------------------------------------*/
+};
diff --git a/tools/dasm/src/java_cup/parse_action.java b/tools/dasm/src/java_cup/parse_action.java
new file mode 100644
index 0000000..1adc92b
--- /dev/null
+++ b/tools/dasm/src/java_cup/parse_action.java
@@ -0,0 +1,87 @@
+
+package java_cup;
+
+/** This class serves as the base class for entries in a parse action table.
+ * Full entries will either be SHIFT(state_num), REDUCE(production), or ERROR.
+ * Objects of this base class will default to ERROR, while the other two
+ * types will be represented by subclasses.
+ *
+ * @see java_cup.reduce_action
+ * @see java_cup.shift_action
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public parse_action()
+ {
+ /* nothing to do in the base class */
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for action type -- error action. */
+ public static final int ERROR = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constant for action type -- shift action. */
+ public static final int SHIFT = 1;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int REDUCE = 2;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to the type -- base class defaults to error. */
+ public int kind() {return ERROR;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ /* we match all error actions */
+ return other != null && other.kind() == ERROR;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof parse_action)
+ return equals((parse_action)other);
+ else
+ return false;
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* all objects of this class hash together */
+ return 0xCafe123;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString() {return "ERROR";}
+
+ /*-----------------------------------------------------------*/
+};
+
diff --git a/tools/dasm/src/java_cup/parse_action_row.java b/tools/dasm/src/java_cup/parse_action_row.java
new file mode 100644
index 0000000..d12b0af
--- /dev/null
+++ b/tools/dasm/src/java_cup/parse_action_row.java
@@ -0,0 +1,106 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * parse action table.
+ */
+public class parse_action_row {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number of
+ * terminals in the grammar has been established.
+ */
+ public parse_action_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = terminal.number();
+
+ /* allocate the array */
+ under_term = new parse_action[size()];
+
+ /* set each element to an error action */
+ for (int i=0; i<_size; i++)
+ under_term[i] = new parse_action();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of reduction counts (reused by compute_default()). */
+ protected static int reduction_count[] = null;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual action entries for the row. */
+ public parse_action under_term[];
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Default (reduce) action for this row. -1 will represent default
+ * of error.
+ */
+ public int default_reduce;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Compute the default (reduce) action for this row and store it in
+ * default_reduce. In the case of non-zero default we will have the
+ * effect of replacing all errors by that reduction. This may cause
+ * us to do erroneous reduces, but will never cause us to shift past
+ * the point of the error and never cause an incorrect parse. -1 will
+ * be used to encode the fact that no reduction can be used as a
+ * default (in which case error will be used).
+ */
+ public void compute_default()
+ {
+ int i, prod, max_prod, max_red;
+
+ /* if we haven't allocated the count table, do so now */
+ if (reduction_count == null)
+ reduction_count = new int[production.number()];
+
+ /* clear the reduction count table and maximums */
+ for (i = 0; i < production.number(); i++)
+ reduction_count[i] = 0;
+ max_prod = -1;
+ max_red = 0;
+
+ /* walk down the row and look at the reduces */
+ for (i = 0; i < size(); i++)
+ if (under_term[i].kind() == parse_action.REDUCE)
+ {
+ /* count the reduce in the proper production slot and keep the
+ max up to date */
+ prod = ((reduce_action)under_term[i]).reduce_with().index();
+ reduction_count[prod]++;
+ if (reduction_count[prod] > max_red)
+ {
+ max_red = reduction_count[prod];
+ max_prod = prod;
+ }
+ }
+
+ /* record the max as the default (or -1 for not found) */
+ default_reduce = max_prod;
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
diff --git a/tools/dasm/src/java_cup/parse_action_table.java b/tools/dasm/src/java_cup/parse_action_table.java
new file mode 100644
index 0000000..002b1d8
--- /dev/null
+++ b/tools/dasm/src/java_cup/parse_action_table.java
@@ -0,0 +1,143 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** This class represents the complete "action" table of the parser.
+ * It has one row for each state in the parse machine, and a column for
+ * each terminal symbol. Each entry in the table represents a shift,
+ * reduce, or an error.
+ *
+ * @see java_cup.parse_action
+ * @see java_cup.parse_action_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_action_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. All terminals, non-terminals, and productions must
+ * already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_action_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_action_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_action_row();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states are in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states are in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state. */
+ public parse_action_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Check the table to ensure that all productions have been reduced.
+ * Issue a warning message (to System.err) for each production that
+ * is never reduced.
+ */
+ public void check_reductions()
+ throws internal_error
+ {
+ parse_action act;
+ production prod;
+
+ /* tabulate reductions -- look at every table entry */
+ for (int row = 0; row < num_states(); row++)
+ {
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* look at the action entry to see if its a reduce */
+ act = under_state[row].under_term[col];
+ if (act != null && act.kind() == parse_action.REDUCE)
+ {
+ /* tell production that we used it */
+ ((reduce_action)act).reduce_with().note_reduction_use();
+ }
+ }
+ }
+
+ /* now go across every production and make sure we hit it */
+ for (Enumeration p = production.all(); p.hasMoreElements(); )
+ {
+ prod = (production)p.nextElement();
+
+ /* if we didn't hit it give a warning */
+ if (prod.num_reductions() == 0)
+ {
+ /* count it *
+ emit.not_reduced++;
+
+ /* give a warning if they haven't been turned off */
+ if (!emit.nowarn)
+ {
+ System.err.println("*** Production \"" +
+ prod.to_simple_string() + "\" never reduced");
+ lexer.warning_count++;
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ int cnt;
+
+ result = "-------- ACTION_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* if the action is not an error print it */
+ if (under_state[row].under_term[col].kind() != parse_action.ERROR)
+ {
+ result += col + ":" + under_state[row].under_term[col] + " ";
+
+ /* end the line after the 3rd one */
+ cnt++;
+ if (cnt == 3)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "------------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
diff --git a/tools/dasm/src/java_cup/parse_reduce_row.java b/tools/dasm/src/java_cup/parse_reduce_row.java
new file mode 100644
index 0000000..d9adf68
--- /dev/null
+++ b/tools/dasm/src/java_cup/parse_reduce_row.java
@@ -0,0 +1,41 @@
+
+package java_cup;
+
+/** This class represents one row (corresponding to one machine state) of the
+ * reduce-goto parse table.
+ */
+public class parse_reduce_row {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: this should not be used until the number
+ * of terminals in the grammar has been established.
+ */
+ public parse_reduce_row()
+ {
+ /* make sure the size is set */
+ if (_size <= 0 ) _size = non_terminal.number();
+
+ /* allocate the array */
+ under_non_term = new lalr_state[size()];
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Number of columns (non terminals) in every row. */
+ protected static int _size = 0;
+
+ /** Number of columns (non terminals) in every row. */
+ public static int size() {return _size;}
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Actual entries for the row. */
+ public lalr_state under_non_term[];
+};
+
diff --git a/tools/dasm/src/java_cup/parse_reduce_table.java b/tools/dasm/src/java_cup/parse_reduce_table.java
new file mode 100644
index 0000000..4f27eb5
--- /dev/null
+++ b/tools/dasm/src/java_cup/parse_reduce_table.java
@@ -0,0 +1,98 @@
+
+package java_cup;
+
+
+/** This class represents the complete "reduce-goto" table of the parser.
+ * It has one row for each state in the parse machines, and a column for
+ * each terminal symbol. Each entry contains a state number to shift to
+ * as the last step of a reduce.
+ *
+ * @see java_cup.parse_reduce_row
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class parse_reduce_table {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. Note: all terminals, non-terminals, and productions
+ * must already have been entered, and the viable prefix recognizer should
+ * have been constructed before this is called.
+ */
+ public parse_reduce_table()
+ {
+ /* determine how many states we are working with */
+ _num_states = lalr_state.number();
+
+ /* allocate the array and fill it in with empty rows */
+ under_state = new parse_reduce_row[_num_states];
+ for (int i=0; i<_num_states; i++)
+ under_state[i] = new parse_reduce_row();
+ }
+
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** How many rows/states in the machine/table. */
+ protected int _num_states;
+
+ /** How many rows/states in the machine/table. */
+ public int num_states() {return _num_states;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Actual array of rows, one per state */
+ public parse_reduce_row[] under_state;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ lalr_state goto_st;
+ int cnt;
+
+ result = "-------- REDUCE_TABLE --------\n";
+ for (int row = 0; row < num_states(); row++)
+ {
+ result += "From state #" + row + "\n";
+ cnt = 0;
+ for (int col = 0; col < under_state[row].size(); col++)
+ {
+ /* pull out the table entry */
+ goto_st = under_state[row].under_non_term[col];
+
+ /* if it has action in it, print it */
+ if (goto_st != null)
+ {
+ result += col + ":";
+ result += goto_st.index();
+
+ /* end the line after the 3rd one */
+ cnt++;
+ if (cnt == 3)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "-----------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
diff --git a/tools/dasm/src/java_cup/parser.cup b/tools/dasm/src/java_cup/parser.cup
new file mode 100644
index 0000000..a64584e
--- /dev/null
+++ b/tools/dasm/src/java_cup/parser.cup
@@ -0,0 +1,620 @@
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+
+ This JavaCup specification is used to implement JavaCup itself.
+ It specifies the parser for the JavaCup specification language.
+ (It also serves as a reasonable example of what a typical JavaCup
+ spec looks like).
+
+ The specification has the following parts:
+ Package and import declarations
+ These serve the same purpose as in a normal Java source file
+ (and will appear in the generated code for the parser). In this
+ case we are part of the java_cup package and we import both the
+ java_cup runtime system and Hashtable from the standard Java
+ utilities package.
+
+ Action code
+ This section provides code that is included with the class encapsulating
+ the various pieces of user code embedded in the grammar (i.e., the
+ semantic actions). This provides a series of helper routines and
+ data structures that the semantic actions use.
+
+ Parser code
+ This section provides code included in the parser class itself. In
+ this case we override the default error reporting routines.
+
+ Init with and scan with
+ These sections provide small bits of code that initialize, then
+ indicate how to invoke the scanner.
+
+ Symbols and grammar
+ These sections declare all the terminal and non terminal symbols
+ and the types of objects that they will be represented by at runtime,
+ then indicate the start symbol of the grammar (), and finally provide
+ the grammar itself (with embedded actions).
+
+ Operation of the parser
+ The parser acts primarily by accumulating data structures representing
+ various parts of the specification. Various small parts (e.g., single
+ code strings) are stored as static variables of the emit class and
+ in a few cases as variables declared in the action code section.
+ Terminals, non terminals, and productions, are maintained as collection
+ accessible via static methods of those classes. In addition, two
+ symbol tables are kept:
+ symbols maintains the name to object mapping for all symbols
+ non_terms maintains a separate mapping containing only the non terms
+
+ Several intermediate working structures are also declared in the action
+ code section. These include: rhs_parts, rhs_pos, and lhs_nt which
+ build up parts of the current production while it is being parsed.
+
+ Author(s)
+ Scott Hudson, GVU Center, Georgia Tech.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+*/
+/*================================================================*/
+
+package java_cup;
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/*----------------------------------------------------------------*/
+
+action code {:
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser code {:
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+:};
+
+/*----------------------------------------------------------------*/
+
+init with {: lexer.init(); :};
+scan with {: return lexer.next_token(); :};
+
+/*----------------------------------------------------------------*/
+
+terminal java_cup.runtime.token
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR,
+ DEBUG;
+
+terminal java_cup.runtime.str_token ID, CODE_STRING;
+
+non terminal java_cup.runtime.symbol
+ spec, package_spec, import_list, code_part, action_code_part,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ debug_grammar,
+ type_id, term_name_list, non_term_name_list, production, prod_part_list,
+ prod_part, new_term_id, new_non_term_id, rhs_list, rhs, empty;
+
+non terminal java_cup.runtime.str_token nt_id, symbol_id, label_id, opt_label;
+
+/*----------------------------------------------------------------*/
+
+start with spec;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+spec ::=
+ {:
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+ :}
+ package_spec
+ import_list
+ code_part
+ debug_grammar
+ init_code
+ scan_code
+ symbol_list
+ start_spec
+ production_list
+ |
+ /* error recovery assuming something went wrong before symbols
+ and we have TERMINAL or NON TERMINAL to sync on. if we get
+ an error after that, we recover inside symbol_list or
+ production_list
+ */
+ error
+ symbol_list
+ start_spec
+ production_list
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+package_spec ::=
+ PACKAGE
+ multipart_id
+ {:
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_list ::=
+ import_list
+ import_spec
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_spec ::=
+ IMPORT
+ import_id
+ {:
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+code_part ::= action_code_part parser_code_part ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code SEMI
+ {:
+ /* save the user included code string */
+ emit.action_code = user_code.str_val;
+ :}
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code SEMI
+ {:
+ /* save the user included code string */
+ emit.parser_code = user_code.str_val;
+ :}
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code SEMI
+ {:
+ /* save the user code */
+ emit.init_code = user_code.str_val;
+ :}
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code SEMI
+ {:
+ /* save the user code */
+ emit.scan_code = user_code.str_val;
+ :}
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+debug_grammar ::=
+ DEBUG WITH multipart_id SEMI
+ {:
+ /* save the procedure name */
+ emit.debug_grammar = multipart_name;
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ NON
+ TERMINAL
+ type_id
+ non_term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+
+ /* error recovery productions -- sync on semicolon */
+
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ NON
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_name_list ::= term_name_list COMMA new_term_id | new_term_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_term_name_list ::=
+ non_term_name_list
+ COMMA
+ new_non_term_id
+ |
+ new_non_term_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+start_spec ::=
+ START WITH nt_id:start_name
+ {:
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name.str_val);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name.str_val +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(new symbol_part(start_nt));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production_list ::= production_list production | production;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production ::=
+ nt_id:lhs_id
+ {:
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id.str_val);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id.str_val +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+ :}
+ COLON_COLON_EQUALS
+ rhs_list
+ SEMI
+ |
+ error
+ {: lexer.emit_error("Syntax Error"); :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs_list ::= rhs_list BAR rhs | rhs;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs ::=
+ prod_part_list
+ {:
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(new symbol_part(start_nt));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part_list ::= prod_part_list prod_part | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part ::=
+ symbol_id:symid opt_label:labid
+ {:
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid.str_val);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("Symbol \"" + symid.str_val +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid.str_val));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str.str_val));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT.str_val = labid.str_val; :}
+ |
+ empty
+ {: RESULT.str_val = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT ID:another_id
+ {: append_multipart(another_id.str_val); :}
+ |
+ ID:an_id
+ {: append_multipart(an_id.str_val); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id.str_val) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("Symbol \"" + term_id.str_val +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* build a production_part and put it in the table */
+ symbols.put(term_id.str_val,
+ new symbol_part(new terminal(term_id.str_val, multipart_name)));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_non_term_id ::=
+ ID:non_term_id
+ {:
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id.str_val) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "Symbol \"" + non_term_id.str_val +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id.str_val, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id.str_val, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id.str_val, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT.str_val = the_id.str_val; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT.str_val = the_id.str_val; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ ID:the_id
+ {: RESULT.str_val = the_id.str_val; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
diff --git a/tools/dasm/src/java_cup/parser.java b/tools/dasm/src/java_cup/parser.java
new file mode 100644
index 0000000..3230281
--- /dev/null
+++ b/tools/dasm/src/java_cup/parser.java
@@ -0,0 +1,1130 @@
+
+//----------------------------------------------------
+// The following code was generated by Java(tm) CUP v0.9d
+// Thu Aug 10 03:51:39 MSD 2006
+//----------------------------------------------------
+
+package java_cup;
+
+import java.util.Hashtable;
+
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** constructor */
+ public parser() {super();}
+
+ /** production table */
+ protected static final short _production_table[][] = {
+ {0, 2}, {32, 0}, {1, 10}, {1, 4}, {33, 0},
+ {2, 4}, {2, 1}, {3, 2}, {3, 1}, {34, 0},
+ {11, 4}, {4, 2}, {5, 4}, {5, 1}, {6, 4},
+ {6, 1}, {13, 4}, {13, 1}, {14, 4}, {14, 1},
+ {16, 4}, {16, 1}, {7, 2}, {7, 1}, {35, 0},
+ {15, 5}, {36, 0}, {15, 6}, {37, 0}, {15, 4},
+ {38, 0}, {15, 5}, {18, 3}, {18, 1}, {19, 3},
+ {19, 1}, {39, 0}, {8, 5}, {8, 1}, {9, 2},
+ {9, 1}, {40, 0}, {20, 5}, {41, 0}, {20, 3},
+ {25, 3}, {25, 1}, {26, 1}, {21, 2}, {21, 1},
+ {22, 2}, {22, 1}, {31, 2}, {31, 1}, {10, 3},
+ {10, 1}, {12, 3}, {12, 1}, {17, 1}, {23, 1},
+ {24, 1}, {28, 1}, {29, 1}, {30, 1}, {27, 0}
+ };
+
+ /** access to production table */
+ public short[][] production_table() {return _production_table;}
+
+ /** parse action table */
+ protected static final short[][] _action_table = {
+ /*0*/{1,3,2,-2,3,-2,5,-2,6,-2,7,-2,8,-2,9,-2,10,-2,20,-2,-1,0},
+ /*1*/{0,120,-1,0},
+ /*2*/{7,34,8,36,-1,0},
+ /*3*/{2,7,3,-65,5,-65,6,-65,7,-65,8,-65,9,-65,10,-65,20,-65,-1,0},
+ /*4*/{3,-65,5,-65,6,-65,7,-65,8,-65,9,-65,10,-65,20,-65,-1,0},
+ /*5*/{3,-7,5,-7,6,-7,7,-7,8,-7,9,-7,10,-7,20,-7,-1,0},
+ /*6*/{21,8,-1,0},
+ /*7*/{13,-56,16,-56,21,-56,-1,0},
+ /*8*/{13,-5,16,11,-1,0},
+ /*9*/{13,13,-1,0},
+ /*10*/{21,12,-1,0},
+ /*11*/{13,-55,16,-55,21,-55,-1,0},
+ /*12*/{3,-6,5,-6,6,-6,7,-6,8,-6,9,-6,10,-6,20,-6,-1,0},
+ /*13*/{3,17,5,18,6,-65,7,-65,8,-65,9,-65,10,-65,20,-65,-1,0},
+ /*14*/{3,-9,5,-9,6,-9,7,-9,8,-9,9,-9,10,-9,20,-9,-1,0},
+ /*15*/{3,-8,5,-8,6,-8,7,-8,8,-8,9,-8,10,-8,20,-8,-1,0},
+ /*16*/{21,8,-1,0},
+ /*17*/{4,108,-1,0},
+ /*18*/{6,103,7,-65,8,-65,9,-65,10,-65,20,-65,-1,0},
+ /*19*/{6,-14,7,-14,8,-14,9,-14,10,-14,20,-14,-1,0},
+ /*20*/{7,-65,8,-65,9,-65,10,-65,20,22,-1,0},
+ /*21*/{11,99,-1,0},
+ /*22*/{7,-22,8,-22,9,-22,10,-22,-1,0},
+ /*23*/{7,-65,8,-65,9,25,10,-65,-1,0},
+ /*24*/{11,96,-1,0},
+ /*25*/{7,-65,8,-65,10,29,-1,0},
+ /*26*/{7,-18,8,-18,10,-18,-1,0},
+ /*27*/{7,34,8,36,-1,0},
+ /*28*/{11,31,-1,0},
+ /*29*/{7,-20,8,-20,-1,0},
+ /*30*/{22,32,-1,0},
+ /*31*/{13,33,-1,0},
+ /*32*/{7,-19,8,-19,-1,0},
+ /*33*/{1,85,21,8,-1,0},
+ /*34*/{1,-24,7,-24,8,-24,12,-24,21,-24,-1,0},
+ /*35*/{7,72,-1,0},
+ /*36*/{1,-65,7,34,8,36,12,41,21,-65,-1,0},
+ /*37*/{1,47,21,43,-1,0},
+ /*38*/{1,-39,21,-39,-1,0},
+ /*39*/{1,-23,7,-23,8,-23,12,-23,21,-23,-1,0},
+ /*40*/{11,42,-1,0},
+ /*41*/{21,43,-1,0},
+ /*42*/{13,-62,18,-62,-1,0},
+ /*43*/{13,-37,-1,0},
+ /*44*/{13,46,-1,0},
+ /*45*/{1,-38,21,-38,-1,0},
+ /*46*/{13,-44,-1,0},
+ /*47*/{18,-42,-1,0},
+ /*48*/{0,-3,1,47,21,43,-1,0},
+ /*49*/{0,-41,1,-41,21,-41,-1,0},
+ /*50*/{0,-40,1,-40,21,-40,-1,0},
+ /*51*/{18,53,-1,0},
+ /*52*/{13,-65,19,-65,21,-65,22,-65,-1,0},
+ /*53*/{13,68,19,67,-1,0},
+ /*54*/{13,-50,19,-50,21,-50,22,-50,-1,0},
+ /*55*/{13,-48,19,-48,21,59,22,58,-1,0},
+ /*56*/{13,-47,19,-47,-1,0},
+ /*57*/{13,-52,19,-52,21,-52,22,-52,-1,0},
+ /*58*/{13,-63,17,-63,19,-63,21,-63,22,-63,-1,0},
+ /*59*/{13,-65,17,62,19,-65,21,-65,22,-65,-1,0},
+ /*60*/{13,-49,19,-49,21,-49,22,-49,-1,0},
+ /*61*/{21,65,-1,0},
+ /*62*/{13,-54,19,-54,21,-54,22,-54,-1,0},
+ /*63*/{13,-51,19,-51,21,-51,22,-51,-1,0},
+ /*64*/{13,-64,21,-64,22,-64,-1,0},
+ /*65*/{13,-53,21,-53,22,-53,-1,0},
+ /*66*/{13,-65,19,-65,21,-65,22,-65,-1,0},
+ /*67*/{0,-43,1,-43,21,-43,-1,0},
+ /*68*/{13,-46,19,-46,-1,0},
+ /*69*/{13,71,-1,0},
+ /*70*/{0,-45,1,-45,21,-45,-1,0},
+ /*71*/{1,73,21,8,-1,0},
+ /*72*/{13,-31,-1,0},
+ /*73*/{16,11,21,-59,-1,0},
+ /*74*/{21,76,-1,0},
+ /*75*/{13,-61,14,-61,-1,0},
+ /*76*/{13,-27,14,79,-1,0},
+ /*77*/{13,-36,14,-36,-1,0},
+ /*78*/{21,76,-1,0},
+ /*79*/{13,81,-1,0},
+ /*80*/{1,-28,7,-28,8,-28,12,-28,21,-28,-1,0},
+ /*81*/{13,-35,14,-35,-1,0},
+ /*82*/{13,84,-1,0},
+ /*83*/{1,-32,7,-32,8,-32,12,-32,21,-32,-1,0},
+ /*84*/{13,-29,-1,0},
+ /*85*/{21,87,-1,0},
+ /*86*/{13,-60,14,-60,-1,0},
+ /*87*/{13,-34,14,-34,-1,0},
+ /*88*/{13,-25,14,91,-1,0},
+ /*89*/{13,93,-1,0},
+ /*90*/{21,87,-1,0},
+ /*91*/{13,-33,14,-33,-1,0},
+ /*92*/{1,-26,7,-26,8,-26,12,-26,21,-26,-1,0},
+ /*93*/{13,95,-1,0},
+ /*94*/{1,-30,7,-30,8,-30,12,-30,21,-30,-1,0},
+ /*95*/{22,97,-1,0},
+ /*96*/{13,98,-1,0},
+ /*97*/{7,-17,8,-17,10,-17,-1,0},
+ /*98*/{21,8,-1,0},
+ /*99*/{13,101,16,11,-1,0},
+ /*100*/{7,-21,8,-21,9,-21,10,-21,-1,0},
+ /*101*/{7,-16,8,-16,9,-16,10,-16,20,-16,-1,0},
+ /*102*/{4,105,-1,0},
+ /*103*/{7,-12,8,-12,9,-12,10,-12,20,-12,-1,0},
+ /*104*/{22,106,-1,0},
+ /*105*/{13,107,-1,0},
+ /*106*/{7,-15,8,-15,9,-15,10,-15,20,-15,-1,0},
+ /*107*/{22,109,-1,0},
+ /*108*/{13,110,-1,0},
+ /*109*/{6,-13,7,-13,8,-13,9,-13,10,-13,20,-13,-1,0},
+ /*110*/{13,-58,16,115,-1,0},
+ /*111*/{13,-10,-1,0},
+ /*112*/{13,114,-1,0},
+ /*113*/{3,-11,5,-11,6,-11,7,-11,8,-11,9,-11,10,-11,20,-11,-1,0},
+ /*114*/{15,116,21,12,-1,0},
+ /*115*/{13,-57,-1,0},
+ /*116*/{1,-65,7,34,8,36,12,41,21,-65,-1,0},
+ /*117*/{1,47,21,43,-1,0},
+ /*118*/{0,-4,1,47,21,43,-1,0},
+ /*119*/{0,-1,-1,0},
+ };
+
+ /** access to parse action table */
+ public short[][] action_table() {return _action_table;}
+
+ /** reduce_goto table */
+ protected static final short[][] _reduce_table = {
+ /*0*/{1,1,32,3,-1,-1},
+ /*1*/{-1,-1},
+ /*2*/{7,116,15,34,-1,-1},
+ /*3*/{2,4,27,5,-1,-1},
+ /*4*/{3,13,27,14,-1,-1},
+ /*5*/{-1,-1},
+ /*6*/{10,8,-1,-1},
+ /*7*/{-1,-1},
+ /*8*/{33,9,-1,-1},
+ /*9*/{-1,-1},
+ /*10*/{-1,-1},
+ /*11*/{-1,-1},
+ /*12*/{-1,-1},
+ /*13*/{4,20,5,18,11,15,27,19,-1,-1},
+ /*14*/{-1,-1},
+ /*15*/{-1,-1},
+ /*16*/{10,110,12,111,-1,-1},
+ /*17*/{-1,-1},
+ /*18*/{6,103,27,101,-1,-1},
+ /*19*/{-1,-1},
+ /*20*/{16,23,27,22,-1,-1},
+ /*21*/{-1,-1},
+ /*22*/{-1,-1},
+ /*23*/{13,25,27,26,-1,-1},
+ /*24*/{-1,-1},
+ /*25*/{14,27,27,29,-1,-1},
+ /*26*/{-1,-1},
+ /*27*/{7,36,15,34,-1,-1},
+ /*28*/{-1,-1},
+ /*29*/{-1,-1},
+ /*30*/{-1,-1},
+ /*31*/{-1,-1},
+ /*32*/{-1,-1},
+ /*33*/{10,73,17,85,-1,-1},
+ /*34*/{-1,-1},
+ /*35*/{-1,-1},
+ /*36*/{8,37,15,39,27,38,-1,-1},
+ /*37*/{9,48,20,49,28,47,-1,-1},
+ /*38*/{-1,-1},
+ /*39*/{-1,-1},
+ /*40*/{-1,-1},
+ /*41*/{28,43,-1,-1},
+ /*42*/{-1,-1},
+ /*43*/{39,44,-1,-1},
+ /*44*/{-1,-1},
+ /*45*/{-1,-1},
+ /*46*/{41,69,-1,-1},
+ /*47*/{40,51,-1,-1},
+ /*48*/{20,50,28,47,-1,-1},
+ /*49*/{-1,-1},
+ /*50*/{-1,-1},
+ /*51*/{-1,-1},
+ /*52*/{21,55,25,53,26,56,27,54,-1,-1},
+ /*53*/{-1,-1},
+ /*54*/{-1,-1},
+ /*55*/{22,60,29,59,-1,-1},
+ /*56*/{-1,-1},
+ /*57*/{-1,-1},
+ /*58*/{-1,-1},
+ /*59*/{27,62,31,63,-1,-1},
+ /*60*/{-1,-1},
+ /*61*/{30,65,-1,-1},
+ /*62*/{-1,-1},
+ /*63*/{-1,-1},
+ /*64*/{-1,-1},
+ /*65*/{-1,-1},
+ /*66*/{21,55,26,68,27,54,-1,-1},
+ /*67*/{-1,-1},
+ /*68*/{-1,-1},
+ /*69*/{-1,-1},
+ /*70*/{-1,-1},
+ /*71*/{10,73,17,74,-1,-1},
+ /*72*/{38,82,-1,-1},
+ /*73*/{-1,-1},
+ /*74*/{19,76,24,77,-1,-1},
+ /*75*/{-1,-1},
+ /*76*/{36,79,-1,-1},
+ /*77*/{-1,-1},
+ /*78*/{24,81,-1,-1},
+ /*79*/{-1,-1},
+ /*80*/{-1,-1},
+ /*81*/{-1,-1},
+ /*82*/{-1,-1},
+ /*83*/{-1,-1},
+ /*84*/{37,93,-1,-1},
+ /*85*/{18,88,23,87,-1,-1},
+ /*86*/{-1,-1},
+ /*87*/{-1,-1},
+ /*88*/{35,89,-1,-1},
+ /*89*/{-1,-1},
+ /*90*/{23,91,-1,-1},
+ /*91*/{-1,-1},
+ /*92*/{-1,-1},
+ /*93*/{-1,-1},
+ /*94*/{-1,-1},
+ /*95*/{-1,-1},
+ /*96*/{-1,-1},
+ /*97*/{-1,-1},
+ /*98*/{10,99,-1,-1},
+ /*99*/{-1,-1},
+ /*100*/{-1,-1},
+ /*101*/{-1,-1},
+ /*102*/{-1,-1},
+ /*103*/{-1,-1},
+ /*104*/{-1,-1},
+ /*105*/{-1,-1},
+ /*106*/{-1,-1},
+ /*107*/{-1,-1},
+ /*108*/{-1,-1},
+ /*109*/{-1,-1},
+ /*110*/{-1,-1},
+ /*111*/{34,112,-1,-1},
+ /*112*/{-1,-1},
+ /*113*/{-1,-1},
+ /*114*/{-1,-1},
+ /*115*/{-1,-1},
+ /*116*/{8,117,15,39,27,38,-1,-1},
+ /*117*/{9,118,20,49,28,47,-1,-1},
+ /*118*/{20,50,28,47,-1,-1},
+ /*119*/{-1,-1},
+ };
+
+ /** access to reduce_goto table */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** instance of action encapsulation class */
+ protected CUP$actions action_obj;
+
+ /** action encapsulation object initializer */
+ protected void init_actions()
+ {
+ action_obj = new CUP$actions();
+ }
+
+ /** invoke a user supplied parse action */
+ public java_cup.runtime.symbol do_action(
+ int act_num,
+ java_cup.runtime.lr_parser parser,
+ java.util.Stack stack,
+ int top)
+ throws java.lang.Exception
+ {
+ /* call code in generated class */
+ return action_obj.CUP$do_action(act_num, parser, stack, top);
+ }
+
+ /** start state */
+ public int start_state() {return 0;}
+ /** start production */
+ public int start_production() {return 0;}
+
+ /** EOF symbol index */
+ public int EOF_sym() {return 0;}
+
+ /** error symbol index */
+ public int error_sym() {return 1;}
+
+
+ /** user initialization */
+ public void user_init() throws java.lang.Exception
+ {
+ lexer.init();
+ }
+
+ /** scan to get the next token */
+ public java_cup.runtime.token scan()
+ throws java.lang.Exception
+ {
+ return lexer.next_token();
+ }
+
+
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+
+};
+
+/** JavaCup generated class to encapsulate user supplied action code.*/
+class CUP$actions {
+
+
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+
+
+ /** Constructor */
+ CUP$actions() { }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.symbol CUP$do_action(
+ int CUP$act_num,
+ java_cup.runtime.lr_parser CUP$parser,
+ java.util.Stack CUP$stack,
+ int CUP$top)
+ throws java.lang.Exception
+ {
+ /* object for return from actions */
+ java_cup.runtime.symbol CUP$result;
+
+ /* select the action based on the action number */
+ switch (CUP$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 64: // empty ::=
+ {
+ CUP$result = new java_cup.runtime.symbol(/*empty*/27);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 63: // label_id ::= ID
+ {
+ CUP$result = new java_cup.runtime.str_token(/*label_id*/30);
+ ((java_cup.runtime.str_token)CUP$result).str_val = (/*the_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val;
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 62: // symbol_id ::= ID
+ {
+ CUP$result = new java_cup.runtime.str_token(/*symbol_id*/29);
+ ((java_cup.runtime.str_token)CUP$result).str_val = (/*the_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val;
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 61: // nt_id ::= ID
+ {
+ CUP$result = new java_cup.runtime.str_token(/*nt_id*/28);
+ ((java_cup.runtime.str_token)CUP$result).str_val = (/*the_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val;
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 60: // new_non_term_id ::= ID
+ {
+ CUP$result = new java_cup.runtime.symbol(/*new_non_term_id*/24);
+
+ /* see if this non terminal has been declared before */
+ if (symbols.get((/*non_term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "Symbol \"" + (/*non_term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal((/*non_term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put((/*non_term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put((/*non_term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val, new symbol_part(this_nt));
+ }
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 59: // new_term_id ::= ID
+ {
+ CUP$result = new java_cup.runtime.symbol(/*new_term_id*/23);
+
+ /* see if this terminal has been declared before */
+ if (symbols.get((/*term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("Symbol \"" + (/*term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* build a production_part and put it in the table */
+ symbols.put((/*term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val,
+ new symbol_part(new terminal((/*term_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val, multipart_name)));
+ }
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 58: // type_id ::= multipart_id
+ {
+ CUP$result = new java_cup.runtime.symbol(/*type_id*/17);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 57: // import_id ::= multipart_id
+ {
+ CUP$result = new java_cup.runtime.symbol(/*import_id*/12);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 56: // import_id ::= multipart_id DOT STAR
+ {
+ CUP$result = new java_cup.runtime.symbol(/*import_id*/12);
+ append_multipart("*");
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 55: // multipart_id ::= ID
+ {
+ CUP$result = new java_cup.runtime.symbol(/*multipart_id*/10);
+ append_multipart((/*an_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val);
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 54: // multipart_id ::= multipart_id DOT ID
+ {
+ CUP$result = new java_cup.runtime.symbol(/*multipart_id*/10);
+ append_multipart((/*another_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val);
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 53: // opt_label ::= empty
+ {
+ CUP$result = new java_cup.runtime.str_token(/*opt_label*/31);
+ ((java_cup.runtime.str_token)CUP$result).str_val = null;
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 52: // opt_label ::= COLON label_id
+ {
+ CUP$result = new java_cup.runtime.str_token(/*opt_label*/31);
+ ((java_cup.runtime.str_token)CUP$result).str_val = (/*labid*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val;
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 51: // prod_part ::= CODE_STRING
+ {
+ CUP$result = new java_cup.runtime.symbol(/*prod_part*/22);
+
+ /* add a new production part */
+ add_rhs_part(new action_part((/*code_str*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val));
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 50: // prod_part ::= symbol_id opt_label
+ {
+ CUP$result = new java_cup.runtime.symbol(/*prod_part*/22);
+
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get((/*symid*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-1)).str_val);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("Symbol \"" + (/*symid*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-1)).str_val +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, (/*labid*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val));
+ }
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 49: // prod_part_list ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*prod_part_list*/21);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 48: // prod_part_list ::= prod_part_list prod_part
+ {
+ CUP$result = new java_cup.runtime.symbol(/*prod_part_list*/21);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 47: // rhs ::= prod_part_list
+ {
+ CUP$result = new java_cup.runtime.symbol(/*rhs*/26);
+
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(new symbol_part(start_nt));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 46: // rhs_list ::= rhs
+ {
+ CUP$result = new java_cup.runtime.symbol(/*rhs_list*/25);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 45: // rhs_list ::= rhs_list BAR rhs
+ {
+ CUP$result = new java_cup.runtime.symbol(/*rhs_list*/25);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 44: // production ::= error NT$9 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*production*/20);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 43: // NT$9 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$9*/41);
+ lexer.emit_error("Syntax Error");
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 42: // production ::= nt_id NT$8 COLON_COLON_EQUALS rhs_list SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*production*/20);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 41: // NT$8 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$8*/40);
+
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get((/*lhs_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + (/*lhs_id*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 40: // production_list ::= production
+ {
+ CUP$result = new java_cup.runtime.symbol(/*production_list*/9);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 39: // production_list ::= production_list production
+ {
+ CUP$result = new java_cup.runtime.symbol(/*production_list*/9);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 38: // start_spec ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*start_spec*/8);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 37: // start_spec ::= START WITH nt_id NT$7 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*start_spec*/8);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 36: // NT$7 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$7*/39);
+
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get((/*start_name*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + (/*start_name*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-0)).str_val +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(new symbol_part(start_nt));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 35: // non_term_name_list ::= new_non_term_id
+ {
+ CUP$result = new java_cup.runtime.symbol(/*non_term_name_list*/19);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 34: // non_term_name_list ::= non_term_name_list COMMA new_non_term_id
+ {
+ CUP$result = new java_cup.runtime.symbol(/*non_term_name_list*/19);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 33: // term_name_list ::= new_term_id
+ {
+ CUP$result = new java_cup.runtime.symbol(/*term_name_list*/18);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 32: // term_name_list ::= term_name_list COMMA new_term_id
+ {
+ CUP$result = new java_cup.runtime.symbol(/*term_name_list*/18);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 31: // symbol ::= NON TERMINAL error NT$6 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*symbol*/15);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 30: // NT$6 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$6*/38);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 29: // symbol ::= TERMINAL error NT$5 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*symbol*/15);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 28: // NT$5 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$5*/37);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 27: // symbol ::= NON TERMINAL type_id non_term_name_list NT$4 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*symbol*/15);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 26: // NT$4 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$4*/36);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 25: // symbol ::= TERMINAL type_id term_name_list NT$3 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*symbol*/15);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 24: // NT$3 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$3*/35);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 23: // symbol_list ::= symbol
+ {
+ CUP$result = new java_cup.runtime.symbol(/*symbol_list*/7);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 22: // symbol_list ::= symbol_list symbol
+ {
+ CUP$result = new java_cup.runtime.symbol(/*symbol_list*/7);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 21: // debug_grammar ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*debug_grammar*/16);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 20: // debug_grammar ::= DEBUG WITH multipart_id SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*debug_grammar*/16);
+
+ /* save the procedure name */
+ emit.debug_grammar = multipart_name;
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 19: // scan_code ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*scan_code*/14);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 18: // scan_code ::= SCAN WITH CODE_STRING SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*scan_code*/14);
+
+ /* save the user code */
+ emit.scan_code = (/*user_code*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-1)).str_val;
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 17: // init_code ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*init_code*/13);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 16: // init_code ::= INIT WITH CODE_STRING SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*init_code*/13);
+
+ /* save the user code */
+ emit.init_code = (/*user_code*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-1)).str_val;
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 15: // parser_code_part ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*parser_code_part*/6);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 14: // parser_code_part ::= PARSER CODE CODE_STRING SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*parser_code_part*/6);
+
+ /* save the user included code string */
+ emit.parser_code = (/*user_code*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-1)).str_val;
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 13: // action_code_part ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*action_code_part*/5);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // action_code_part ::= ACTION CODE CODE_STRING SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*action_code_part*/5);
+
+ /* save the user included code string */
+ emit.action_code = (/*user_code*/(java_cup.runtime.str_token)CUP$stack.elementAt(CUP$top-1)).str_val;
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // code_part ::= action_code_part parser_code_part
+ {
+ CUP$result = new java_cup.runtime.symbol(/*code_part*/4);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // import_spec ::= IMPORT import_id NT$2 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*import_spec*/11);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // NT$2 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$2*/34);
+
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // import_list ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*import_list*/3);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // import_list ::= import_list import_spec
+ {
+ CUP$result = new java_cup.runtime.symbol(/*import_list*/3);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // package_spec ::= empty
+ {
+ CUP$result = new java_cup.runtime.symbol(/*package_spec*/2);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // package_spec ::= PACKAGE multipart_id NT$1 SEMI
+ {
+ CUP$result = new java_cup.runtime.symbol(/*package_spec*/2);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // NT$1 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$1*/33);
+
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // spec ::= error symbol_list start_spec production_list
+ {
+ CUP$result = new java_cup.runtime.symbol(/*spec*/1);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // spec ::= NT$0 package_spec import_list code_part debug_grammar init_code scan_code symbol_list start_spec production_list
+ {
+ CUP$result = new java_cup.runtime.symbol(/*spec*/1);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // NT$0 ::=
+ {
+ CUP$result = new java_cup.runtime.token(/*NT$0*/32);
+
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+
+ }
+ return CUP$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // $START ::= spec EOF
+ {
+ CUP$result = new java_cup.runtime.token(/*$START*/0);
+
+ }
+ /* ACCEPT */
+ CUP$parser.done_parsing();
+ return CUP$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+};
+
diff --git a/tools/dasm/src/java_cup/production.java b/tools/dasm/src/java_cup/production.java
new file mode 100644
index 0000000..9c1d634
--- /dev/null
+++ b/tools/dasm/src/java_cup/production.java
@@ -0,0 +1,782 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/** This class represents a production in the grammar. It contains
+ * a LHS non terminal, and an array of RHS symbols. As various
+ * transformations are done on the RHS of the production, it may shrink.
+ * As a result a separate length is always maintained to indicate how much
+ * of the RHS array is still valid.<p>
+ *
+ * I addition to construction and manipulation operations, productions provide
+ * methods for factoring out actions (see remove_embedded_actions()), for
+ * computing the nullability of the production (i.e., can it derive the empty
+ * string, see check_nullable()), and operations for computing its first
+ * set (i.e., the set of terminals that could appear at the beginning of some
+ * string derived from the production, see check_first_set()).
+ *
+ * @see java_cup.production_part
+ * @see java_cup.symbol_part
+ * @see java_cup.action_part
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class production {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor. This constructor accepts a LHS non terminal,
+ * an array of RHS parts (including terminals, non terminals, and
+ * actions), and a string for a final reduce action. It does several
+ * manipulations in the process of creating a production object.
+ * After some validity checking it translates labels that appear in
+ * actions into code for accessing objects on the runtime parse stack.
+ * It them merges adjacent actions if they appear and moves any trailing
+ * action into the final reduce actions string. Next it removes any
+ * embedded actions by factoring them out with new action productions.
+ * Finally it assigns a unique index to the production.<p>
+ *
+ * Factoring out of actions is accomplished by creating new "hidden"
+ * non terminals. For example if the production was originally: <pre>
+ * A ::= B {action} C D
+ * </pre>
+ * then it is factored into two productions:<pre>
+ * A ::= B X C D
+ * X ::= {action}
+ * </pre>
+ * (where X is a unique new non terminal). This has the effect of placing
+ * all actions at the end where they can be handled as part of a reduce by
+ * the parser.
+ */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str)
+ throws internal_error
+ {
+ int i;
+ action_part tail_action;
+
+ /* remember the length */
+ if (rhs_l >= 0)
+ _rhs_length = rhs_l;
+ else if (rhs_parts != null)
+ _rhs_length = rhs_parts.length;
+ else
+ _rhs_length = 0;
+
+ /* make sure we have a valid left-hand-side */
+ if (lhs_sym == null)
+ throw new internal_error(
+ "Attempt to construct a production with a null LHS");
+
+ /* translate labels appearing in action strings */
+ action_str = translate_labels(
+ rhs_parts, rhs_l, action_str, lhs_sym.stack_type());
+
+ /* count use of lhs */
+ lhs_sym.note_use();
+
+ /* create the part for left-hand-side */
+ _lhs = new symbol_part(lhs_sym);
+
+ /* merge adjacent actions (if any) */
+ _rhs_length = merge_adjacent_actions(rhs_parts, _rhs_length);
+
+ /* strip off any trailing action */
+ tail_action = strip_trailing_action(rhs_parts, _rhs_length);
+ if (tail_action != null) _rhs_length--;
+
+ /* allocate and copy over the right-hand-side */
+ _rhs = new production_part[_rhs_length];
+ for (i=0; i<_rhs_length; i++)
+ _rhs[i] = rhs_parts[i];
+
+ /* count use of each rhs symbol */
+ for (i=0; i<_rhs_length; i++)
+ if (!_rhs[i].is_action())
+ ((symbol_part)_rhs[i]).the_symbol().note_use();
+
+ /* merge any trailing action with action string parameter */
+ if (action_str == null) action_str = "";
+ if (tail_action != null && tail_action.code_string() != null)
+ action_str = tail_action.code_string() + action_str;
+
+ /* stash the action */
+ _action = new action_part(action_str);
+
+ /* rewrite production to remove any embedded actions */
+ remove_embedded_actions();
+
+ /* assign an index */
+ _index = next_index++;
+
+ /* put us in the global collection of productions */
+ _all.put(new Integer(_index),this);
+
+ /* put us in the production list of the lhs non terminal */
+ lhs_sym.add_production(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no action string. */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all productions. Elements are stored using their index as
+ * the key.
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all productions. */
+ public static Enumeration all() {return _all.elements();};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of productions. */
+ public static int number() {return _all.size();};
+
+ /** Static counter for assigning unique index numbers. */
+ protected static int next_index;
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The left hand side non-terminal. */
+ protected symbol_part _lhs;
+
+ /** The left hand side non-terminal. */
+ public symbol_part lhs() {return _lhs;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** A collection of parts for the right hand side. */
+ protected production_part _rhs[];
+
+ /** Access to the collection of parts for the right hand side. */
+ public production_part rhs(int indx) throws internal_error
+ {
+ if (indx >= 0 && indx < _rhs_length)
+ return _rhs[indx];
+ else
+ throw new internal_error(
+ "Index out of range for right hand side of production");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** How much of the right hand side array we are presently using. */
+ protected int _rhs_length;
+
+ /** How much of the right hand side array we are presently using. */
+ public int rhs_length() {return _rhs_length;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ protected action_part _action;
+
+ /** An action_part containing code for the action to be performed when we
+ * reduce with this production.
+ */
+ public action_part action() {return _action;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index number of the production. */
+ protected int _index;
+
+ /** Index number of the production. */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of number of reductions using this production. */
+ protected int _num_reductions = 0;
+
+ /** Count of number of reductions using this production. */
+ public int num_reductions() {return _num_reductions;}
+
+ /** Increment the count of reductions with this non-terminal */
+ public void note_reduction_use() {_num_reductions++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the nullability of the production known or unknown? */
+ protected boolean _nullable_known = false;
+
+ /** Is the nullability of the production known or unknown? */
+ public boolean nullable_known() {return _nullable_known;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Nullability of the production (can it derive the empty string). */
+ protected boolean _nullable = false;
+
+ /** Nullability of the production (can it derive the empty string). */
+ public boolean nullable() {return _nullable;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ protected terminal_set _first_set = new terminal_set();
+
+ /** First set of the production. This is the set of terminals that
+ * could appear at the front of some string derived from this production.
+ */
+ public terminal_set first_set() {return _first_set;}
+
+ /*-----------------------------------------------------------*/
+ /*--- Static Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Determine if a given character can be a label id starter.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_start(char c)
+ {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
+
+ //later need to handle non-8-bit chars here
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if a character can be in a label id.
+ * @param c the character in question.
+ */
+ protected static boolean is_id_char(char c)
+ {
+ return is_id_start(c) || (c >= '0' && c <= '9');
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Determine the translation for one label id found within a code_string.
+ * Symbols appearing in the RHS correspond to objects found on the parse
+ * stack at runtime. The code to access them, becomes code to access an
+ * object at the appropriate offset from the top of the stack, and then
+ * cast that to the proper type.
+ *
+ * @param id_str the name of the id to be translated.
+ * @param act_pos the original position of the action it appears in.
+ * @param label_map a hash table mapping labels to positions in the RHS.
+ * @param type_map a hash table mapping labels to declared symbol types.
+ */
+ protected String label_translate(
+ String id_str, /* the id string we are (possibly) translating */
+ int act_pos, /* position of the action */
+ Hashtable label_map, /* map from labels to positions in the RHS */
+ Hashtable label_types)/* map from labels to stack types */
+ {
+ Integer label_pos;
+ String label_type;
+ int offset;
+
+ /* look up the id */
+ label_pos = (Integer)label_map.get(id_str);
+
+ /* if we don't find it, just return the id */
+ if (label_pos == null) return id_str;
+
+ /* extract the type of the labeled symbol */
+ label_type = (String)label_types.get(id_str);
+
+ /* is this for the LHS? */
+ if (label_pos.intValue() == -1)
+ {
+ /* return the result object cast properly */
+ return "((" + label_type + ")" + emit.pre("result") + ")";
+ }
+
+ /* its a RHS label */
+
+ /* if the label appears after the action, we have an error */
+ if (label_pos.intValue() > act_pos)
+ {
+ /* emit an error message */
+ System.err.println("*** Label \"" + id_str +
+ "\" appears in action before it appears in production");
+ lexer.error_count++;
+
+ // later need to print the production this is in
+
+ /* just return the id unchanged */
+ return id_str;
+ }
+
+ /* calculate the stack offset as the difference in position from
+ label to action minus one */
+ offset = (act_pos - label_pos.intValue())-1;
+
+ /* translation is properly cast element at that offset from TOS */
+ return "(/*"+id_str+"*/("+label_type+")" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +"-"+ offset + "))";
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Translate all the label names within an action string to appropriate code.
+ * @param act_string the string to be translated
+ * @param act_pos the position that the action originally held in the
+ * production.
+ * @param label_map a hash table mapping labels to positions in the RHS.
+ * @param type_map a hash table mapping labels to declared symbol types.
+ */
+ protected String action_translate(
+ String act_string, /* the action string */
+ int act_pos, /* the position of the action on the RHS */
+ Hashtable label_map, /* map from labels to RHS positions */
+ Hashtable label_types) /* map from labels to symbol stack types */
+ {
+ int id_start;
+ int pos;
+ int len;
+ String id_str;
+ boolean in_id;
+ StringBuffer result;
+ char buffer[];
+
+ /* if we have no string we are done */
+ if (act_string == null || act_string.length()== 0) return act_string;
+
+ len = act_string.length();
+
+ /* set up a place to put the result */
+ result = new StringBuffer(len + 50);
+
+ /* extract string into array */
+ buffer = new char[len + 1];
+ act_string.getChars(0, len, buffer, 0);
+
+ /* put terminator in buffer so we can look one past the end */
+ buffer[len] = '\0';
+
+ /* walk down the input buffer looking for identifiers */
+ in_id = false;
+ for (pos = id_start = 0; pos <= len; pos++)
+ {
+ /* are we currently working on an id? */
+ if (in_id)
+ {
+ /* does this end the id? */
+ if (!is_id_char(buffer[pos]))
+ {
+ /* extract the id string and translate it */
+ id_str = new String(buffer, id_start, pos - id_start);
+ result.append(
+ label_translate(id_str, act_pos, label_map,label_types));
+
+ /* copy over the ending character */
+ if (buffer[pos] != '\0')
+ result.append(buffer, pos, 1);
+
+ /* and we are done with this id */
+ in_id = false;
+ }
+ else
+ {
+ /* we are still in the id, so just keep going */
+ }
+ }
+ else /* we are not inside an id */
+ {
+ /* start a new id? */
+ if (is_id_start(buffer[pos]))
+ {
+ /* start keeping these chars as an id */
+ in_id = true;
+ id_start = pos;
+ }
+ else
+ {
+ /* just copy over the char */
+ if (buffer[pos] != '\0')
+ result.append(buffer, pos, 1);
+ }
+ }
+ }
+
+ /* return the accumulated result */
+ return result.toString();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Translate label names to appropriate code within all action strings.
+ * @param rhs array of RHS parts.
+ * @param rhs_len how much of rhs to consider valid.
+ * @param final_action the final action string of the production.
+ * @param lhs_type the object type associated with the LHS symbol.
+ */
+ protected String translate_labels(
+ production_part rhs[],
+ int rhs_len,
+ String final_action,
+ String lhs_type)
+ {
+ Hashtable label_map = new Hashtable(11);
+ Hashtable label_types = new Hashtable(11);
+ symbol_part part;
+ action_part act_part;
+ int pos;
+
+ /* walk down the parts and extract the labels */
+ for (pos = 0; pos < rhs_len; pos++)
+ {
+ if (!rhs[pos].is_action())
+ {
+ part = (symbol_part)rhs[pos];
+
+ /* if it has a label enter it in the tables */
+ if (part.label() != null)
+ {
+ label_map.put(part.label(), new Integer(pos));
+ label_types.put(part.label(), part.the_symbol().stack_type());
+ }
+ }
+ }
+
+ /* add a label for the LHS */
+ label_map.put("RESULT", new Integer(-1));
+ label_types.put("RESULT", lhs_type);
+
+ /* now walk across and do each action string */
+ for (pos = 0; pos < rhs_len; pos++)
+ {
+ if (rhs[pos].is_action())
+ {
+ act_part = (action_part)rhs[pos];
+ act_part.set_code_string(
+ action_translate(
+ act_part.code_string(), pos, label_map, label_types));
+ }
+ }
+
+ /* now do the final action string at the position after the last */
+ return action_translate(final_action, rhs_len, label_map, label_types);
+
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to merge adjacent actions in a set of RHS parts
+ * @param rhs_parts array of RHS parts.
+ * @param len amount of that array that is valid.
+ * @return remaining valid length.
+ */
+ protected int merge_adjacent_actions(production_part rhs_parts[], int len)
+ {
+ int from_loc, to_loc, merge_cnt;
+
+ /* bail out early if we have no work to do */
+ if (rhs_parts == null || len == 0) return 0;
+
+ merge_cnt = 0;
+ to_loc = -1;
+ for (from_loc=0; from_loc<len; from_loc++)
+ {
+ /* do we go in the current position or one further */
+ if (to_loc < 0 || !rhs_parts[to_loc].is_action()
+ || !rhs_parts[from_loc].is_action())
+ {
+ /* next one */
+ to_loc++;
+
+ /* clear the way for it */
+ if (to_loc != from_loc) rhs_parts[to_loc] = null;
+ }
+
+ /* if this is not trivial? */
+ if (to_loc != from_loc)
+ {
+ /* do we merge or copy? */
+ if (rhs_parts[to_loc] != null && rhs_parts[to_loc].is_action() &&
+ rhs_parts[from_loc].is_action())
+ {
+ /* merge */
+ rhs_parts[to_loc] = new action_part(
+ ((action_part)rhs_parts[to_loc]).code_string() +
+ ((action_part)rhs_parts[from_loc]).code_string());
+ merge_cnt++;
+ }
+ else
+ {
+ /* copy */
+ rhs_parts[to_loc] = rhs_parts[from_loc];
+ }
+ }
+ }
+
+ /* return the used length */
+ return len - merge_cnt;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to strip a trailing action off rhs and return it
+ * @param rhs_parts array of RHS parts.
+ * @param len how many of those are valid.
+ * @return the removed action part.
+ */
+ protected action_part strip_trailing_action(
+ production_part rhs_parts[],
+ int len)
+ {
+ action_part result;
+
+ /* bail out early if we have nothing to do */
+ if (rhs_parts == null || len == 0) return null;
+
+ /* see if we have a trailing action */
+ if (rhs_parts[len-1].is_action())
+ {
+ /* snip it out and return it */
+ result = (action_part)rhs_parts[len-1];
+ rhs_parts[len-1] = null;
+ return result;
+ }
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove all embedded actions from a production by factoring them
+ * out into individual action production using new non terminals.
+ * if the original production was: <pre>
+ * A ::= B {action1} C {action2} D
+ * </pre>
+ * then it will be factored into: <pre>
+ * A ::= B NT$1 C NT$2 D
+ * NT$1 ::= {action1}
+ * NT$2 ::= {action2}
+ * </pre>
+ * where NT$1 and NT$2 are new system created non terminals.
+ */
+ protected void remove_embedded_actions() throws internal_error
+ {
+ non_terminal new_nt;
+ production new_prod;
+
+ /* walk over the production and process each action */
+ for (int act_loc = 0; act_loc < rhs_length(); act_loc++)
+ if (rhs(act_loc).is_action())
+ {
+ /* create a new non terminal for the action production */
+ new_nt = non_terminal.create_new();
+
+ /* create a new production with just the action */
+ new_prod = new action_production(this, new_nt, null, 0,
+ ((action_part)rhs(act_loc)).code_string());
+
+ /* replace the action with the generated non terminal */
+ _rhs[act_loc] = new symbol_part(new_nt);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Check to see if the production (now) appears to be nullable.
+ * A production is nullable if its RHS could derive the empty string.
+ * This results when the RHS is empty or contains only non terminals
+ * which themselves are nullable.
+ */
+ public boolean check_nullable() throws internal_error
+ {
+ production_part part;
+ symbol sym;
+ int pos;
+
+ /* if we already know bail out early */
+ if (nullable_known()) return nullable();
+
+ /* if we have a zero size RHS we are directly nullable */
+ if (rhs_length() == 0)
+ {
+ /* stash and return the result */
+ return set_nullable(true);
+ }
+
+ /* otherwise we need to test all of our parts */
+ for (pos=0; pos<rhs_length(); pos++)
+ {
+ part = rhs(pos);
+
+ /* only look at non-actions */
+ if (!part.is_action())
+ {
+ sym = ((symbol_part)part).the_symbol();
+
+ /* if its a terminal we are definitely not nullable */
+ if (!sym.is_non_term())
+ return set_nullable(false);
+ /* its a non-term, is it marked nullable */
+ else if (!((non_terminal)sym).nullable())
+ /* this one not (yet) nullable, so we aren't */
+ return false;
+ }
+ }
+
+ /* if we make it here all parts are nullable */
+ return set_nullable(true);
+ }
+
+ /** set (and return) nullability */
+ boolean set_nullable(boolean v)
+ {
+ _nullable_known = true;
+ _nullable = v;
+ return v;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Update (and return) the first set based on current NT firsts.
+ * This assumes that nullability has already been computed for all non
+ * terminals and productions.
+ */
+ public terminal_set check_first_set() throws internal_error
+ {
+ int part;
+ symbol sym;
+
+ /* walk down the right hand side till we get past all nullables */
+ for (part=0; part<rhs_length(); part++)
+ {
+ /* only look at non-actions */
+ if (!rhs(part).is_action())
+ {
+ sym = ((symbol_part)rhs(part)).the_symbol();
+
+ /* is it a non-terminal?*/
+ if (sym.is_non_term())
+ {
+ /* add in current firsts from that NT */
+ _first_set.add(((non_terminal)sym).first_set());
+
+ /* if its not nullable, we are done */
+ if (!((non_terminal)sym).nullable())
+ break;
+ }
+ else
+ {
+ /* its a terminal -- add that to the set */
+ _first_set.add((terminal)sym);
+
+ /* we are done */
+ break;
+ }
+ }
+ }
+
+ /* return our updated first set */
+ return first_set();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production other)
+ {
+ if (other == null) return false;
+ return other._index == _index;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production))
+ return false;
+ else
+ return equals((production)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ /* just use a simple function of the index */
+ return _index*13;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+
+ /* catch any internal errors */
+ try {
+ result = "production [" + index() + "]: ";
+ result += ((lhs() != null) ? lhs().toString() : "$$NULL-LHS$$");
+ result += " :: = ";
+ for (int i = 0; i<rhs_length(); i++)
+ result += rhs(i) + " ";
+ result += ";";
+ if (action() != null && action().code_string() != null)
+ result += " {" + action().code_string() + "}";
+
+ if (nullable_known())
+ if (nullable())
+ result += "[NULLABLE]";
+ else
+ result += "[NOT NULLABLE]";
+ } catch (internal_error e) {
+ /* crash on internal error since we can't throw it from here (because
+ superclass does not throw anything. */
+ e.crash();
+ result = null;
+ }
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a simpler string. */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+
+ result = ((lhs() != null) ? lhs().the_symbol().name() : "NULL_LHS");
+ result += " ::= ";
+ for (int i = 0; i < rhs_length(); i++)
+ if (!rhs(i).is_action())
+ result += ((symbol_part)rhs(i)).the_symbol().name() + " ";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/production_part.java b/tools/dasm/src/java_cup/production_part.java
new file mode 100644
index 0000000..cdb92f7
--- /dev/null
+++ b/tools/dasm/src/java_cup/production_part.java
@@ -0,0 +1,94 @@
+package java_cup;
+
+/** This class represents one part (either a symbol or an action) of a
+ * production. In this base class it contains only an optional label
+ * string that the user can use to refer to the part within actions.<p>
+ *
+ * This is an abstract class.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public abstract class production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public production_part(String lab)
+ {
+ _label = lab;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ protected String _label;
+
+ /** Optional label for referring to the part within an action (null for
+ * no label).
+ */
+ public String label() {return _label;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Indicate if this is an action (rather than a symbol). Here in the
+ * base class, we don't this know yet, so its an abstract method.
+ */
+ public abstract boolean is_action();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(production_part other)
+ {
+ if (other == null) return false;
+
+ /* compare the labels */
+ if (label() != null)
+ return label().equals(other.label());
+ else
+ return other.label() == null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof production_part))
+ return false;
+ else
+ return equals((production_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return label()==null ? 0 : label().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (label() != null)
+ return label() + ":";
+ else
+ return " ";
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/reduce_action.java b/tools/dasm/src/java_cup/reduce_action.java
new file mode 100644
index 0000000..646fe0c
--- /dev/null
+++ b/tools/dasm/src/java_cup/reduce_action.java
@@ -0,0 +1,84 @@
+
+package java_cup;
+
+/** This class represents a reduce action within the parse table.
+ * The action simply stores the production that it reduces with and
+ * responds to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class reduce_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param prod the production this action reduces with.
+ */
+ public reduce_action(production prod ) throws internal_error
+ {
+ /* sanity check */
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create a reduce_action with a null production");
+
+ _reduce_with = prod;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production we reduce with. */
+ protected production _reduce_with;
+
+ /** The production we reduce with. */
+ public production reduce_with() {return _reduce_with;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return REDUCE;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(reduce_action other)
+ {
+ return other != null && other.reduce_with() == reduce_with();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof reduce_action)
+ return equals((reduce_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the production we are reducing with */
+ return reduce_with().hashCode();
+ }
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "REDUCE(" + reduce_with().index() + ")";
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/runtime/char_token.java b/tools/dasm/src/java_cup/runtime/char_token.java
new file mode 100644
index 0000000..0b4502b
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/char_token.java
@@ -0,0 +1,32 @@
+
+package java_cup.runtime;
+
+/** This subclass of token represents symbols that need to maintain one
+ * char value as an attribute. It maintains that value in the public
+ * field int_val.
+ *
+ * @see java_cup.runtime.str_token
+ * @version last updated: 1/7/96
+ * @author Scott Hudson
+ */
+
+public class char_token extends token {
+
+ /** Full constructor. */
+ public char_token(int term_num, char v)
+ {
+ /* super class does most of the work */
+ super(term_num);
+
+ char_val = v;
+ }
+
+ /** Constructor with default value of 0 */
+ public char_token(int term_num)
+ {
+ this(term_num, '\0');
+ }
+
+ /** The stored char value. */
+ public char char_val;
+};
diff --git a/tools/dasm/src/java_cup/runtime/double_token.java b/tools/dasm/src/java_cup/runtime/double_token.java
new file mode 100644
index 0000000..df95822
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/double_token.java
@@ -0,0 +1,32 @@
+
+package java_cup.runtime;
+
+/** This subclass of token represents symbols that need to maintain one
+ * double value as an attribute. It maintains that value in the public
+ * field int_val.
+ *
+ * @see java_cup.runtime.str_token
+ * @version last updated: 1/7/96
+ * @author Scott Hudson
+ */
+
+public class double_token extends token {
+
+ /** Full constructor. */
+ public double_token(int term_num, double v)
+ {
+ /* super class does most of the work */
+ super(term_num);
+
+ double_val = v;
+ }
+
+ /** Constructor with default value of 0.0. */
+ public double_token(int term_num)
+ {
+ this(term_num,0.0f);
+ }
+
+ /** The stored double value. */
+ public double double_val;
+};
diff --git a/tools/dasm/src/java_cup/runtime/float_token.java b/tools/dasm/src/java_cup/runtime/float_token.java
new file mode 100644
index 0000000..d1b56da
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/float_token.java
@@ -0,0 +1,32 @@
+
+package java_cup.runtime;
+
+/** This subclass of token represents symbols that need to maintain one
+ * float value as an attribute. It maintains that value in the public
+ * field int_val.
+ *
+ * @see java_cup.runtime.str_token
+ * @version last updated: 1/7/96
+ * @author Scott Hudson
+ */
+
+public class float_token extends token {
+
+ /** Full constructor. */
+ public float_token(int term_num, float v)
+ {
+ /* super class does most of the work */
+ super(term_num);
+
+ float_val = v;
+ }
+
+ /** Constructor with default value of 0.0. */
+ public float_token(int term_num)
+ {
+ this(term_num,0.0f);
+ }
+
+ /** The stored float value. */
+ public float float_val;
+};
diff --git a/tools/dasm/src/java_cup/runtime/int_token.java b/tools/dasm/src/java_cup/runtime/int_token.java
new file mode 100644
index 0000000..b78df69
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/int_token.java
@@ -0,0 +1,32 @@
+
+package java_cup.runtime;
+
+/** This subclass of token represents symbols that need to maintain one
+ * int value as an attribute. It maintains that value in the public
+ * field int_val.
+ *
+ * @see java_cup.runtime.str_token
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class int_token extends token {
+
+ /** Full constructor. */
+ public int_token(int term_num, int iv)
+ {
+ /* super class does most of the work */
+ super(term_num);
+
+ int_val = iv;
+ }
+
+ /** Constructor with default value of 0. */
+ public int_token(int term_num)
+ {
+ this(term_num,0);
+ }
+
+ /** The stored int value. */
+ public int int_val;
+};
diff --git a/tools/dasm/src/java_cup/runtime/long_token.java b/tools/dasm/src/java_cup/runtime/long_token.java
new file mode 100644
index 0000000..170a69b
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/long_token.java
@@ -0,0 +1,32 @@
+
+package java_cup.runtime;
+
+/** This subclass of token represents symbols that need to maintain one
+ * long value as an attribute. It maintains that value in the public
+ * field int_val.
+ *
+ * @see java_cup.runtime.str_token
+ * @version last updated: 1/7/96
+ * @author Scott Hudson
+ */
+
+public class long_token extends token {
+
+ /** Full constructor. */
+ public long_token(int term_num, long lv)
+ {
+ /* super class does most of the work */
+ super(term_num);
+
+ long_val = lv;
+ }
+
+ /** Constructor with default value of 0. */
+ public long_token(int term_num)
+ {
+ this(term_num,0);
+ }
+
+ /** The stored long value. */
+ public long long_val;
+};
diff --git a/tools/dasm/src/java_cup/runtime/lr_parser.java b/tools/dasm/src/java_cup/runtime/lr_parser.java
new file mode 100644
index 0000000..b814390
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/lr_parser.java
@@ -0,0 +1,1121 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a skeleton table driven LR parser. In general,
+ * LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce
+ * parsers act by shifting input onto a parse stack until the symbols
+ * matching the right hand side of a production appear on the top of the
+ * stack. Once this occurs, a reduce is performed. This involves removing
+ * the symbols corresponding to the right hand side of the production
+ * (the so called "handle") and replacing them with the non-terminal from
+ * the left hand side of the production. <p>
+ *
+ * To control the decision of whether to shift or reduce at any given point,
+ * the parser uses a state machine (the "viable prefix recognition machine"
+ * built by the parser generator). The current state of the machine is placed
+ * on top of the parse stack (stored as part of a symbol object representing
+ * a terminal or non terminal). The parse action table is consulted
+ * (using the current state and the current lookahead token as indexes) to
+ * determine whether to shift or to reduce. When the parser shifts, it
+ * changes to a new state by pushing a new symbol (containing a new state)
+ * onto the stack. When the parser reduces, it pops the handle (right hand
+ * side of a production) off the stack. This leaves the parser in the state
+ * it was in before any of those symbols were matched. Next the reduce-goto
+ * table is consulted (using the new state and current lookahead token as
+ * indexes) to determine a new state to go to. The parser then shifts to
+ * this goto state by pushing the left hand side symbol of the production
+ * (also containing the new state) onto the stack.<p>
+ *
+ * This class actually provides four LR parsers. The methods parse() and
+ * debug_parse() provide two versions of the main parser (the only difference
+ * being that debug_parse() emits debugging trace messages as it parses).
+ * In addition to these main parsers, the error recovery mechanism uses two
+ * more. One of these is used to simulate "parsing ahead" in the input
+ * without carrying out actions (to verify that a potential error recovery
+ * has worked), and the other is used to parse through buffered "parse ahead"
+ * input in order to execute all actions and re-synchronize the actual parser
+ * configuration.<p>
+ *
+ * This is an abstract class which is normally filled out by a subclass
+ * generated by the JavaCup parser generator. In addition to supplying
+ * the actual parse tables, generated code also supplies methods which
+ * invoke various pieces of user supplied code, provide access to certain
+ * special symbols (e.g., EOF and error), etc. Specifically, the following
+ * abstract methods are normally supplied by generated code:
+ * <dl compact>
+ * <dt> short[][] production_table()
+ * <dd> Provides a reference to the production table (indicating the index of
+ * the left hand side non terminal and the length of the right hand side
+ * for each production in the grammar).
+ * <dt> short[][] action_table()
+ * <dd> Provides a reference to the parse action table.
+ * <dt> short[][] reduce_table()
+ * <dd> Provides a reference to the reduce-goto table.
+ * <dt> int start_state()
+ * <dd> Indicates the index of the start state.
+ * <dt> int start_production()
+ * <dd> Indicates the index of the starting production.
+ * <dt> int EOF_sym()
+ * <dd> Indicates the index of the EOF symbol.
+ * <dt> int error_sym()
+ * <dd> Indicates the index of the error symbol.
+ * <dt> symbol do_action()
+ * <dd> Executes a piece of user supplied action code. This always comes at
+ * the point of a reduce in the parse, so this code also allocates and
+ * fills in the left hand side non terminal symbol object that is to be
+ * pushed onto the stack for the reduce.
+ * <dt> void init_actions()
+ * <dd> Code to initialize a special object that encapsulates user supplied
+ * actions (this object is used by do_action() to actually carry out the
+ * actions).
+ * <dt> token scan()
+ * <dd> Used to get the next input token from the scanner.
+ * </dl>
+ *
+ * In addition to these routines that <i>must</i> be supplied by the
+ * generated subclass there are also a series of routines that <i>may</i>
+ * be supplied. These include:
+ * <dl>
+ * <dt> int error_sync_size()
+ * <dd> This determines how many tokens past the point of an error
+ * must be parsed without error in order to consider a recovery to
+ * be valid. This defaults to 3. Values less than 2 are not
+ * recommended.
+ * <dt> void report_error(String message, Object info)
+ * <dd> This method is called to report an error. The default implementation
+ * simply prints a message to System.err and ignores its second parameter.
+ * This method is often replaced in order to provide a more sophisticated
+ * error reporting mechanism.
+ * <dt> void report_fatal_error(String message, Object info)
+ * <dd> This method is called when a fatal error that cannot be recovered from
+ * is encountered. In the default implementation, it calls
+ * report_error() to emit a message, then throws an exception.
+ * <dt> void syntax_error(token cur_token)
+ * <dd> This method is called as soon as syntax error is detected (but
+ * before recovery is attempted). In the default implementation it
+ * invokes: report_error("Syntax error", null);
+ * <dt> void unrecovered_syntax_error(token cur_token)
+ * <dd> This method is called if syntax error recovery fails. In the default
+ * implementation it invokes:<br>
+ * report_fatal_error("Couldn't repair and continue parse", null);
+ * </dl>
+ *
+ * @see java_cup.runtime.symbol
+ * @see java_cup.runtime.token
+ * @see java_cup.runtime.virtual_parse_stack
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public abstract class lr_parser {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor. */
+ public lr_parser()
+ {
+ /* nothing to do here */
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The default number of tokens after an error we much match to consider
+ * it recovered from.
+ */
+ protected final static int _error_sync_size = 3;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The number of tokens after an error we much match to consider it
+ * recovered from.
+ */
+ protected int error_sync_size() {return _error_sync_size; }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of production information (supplied by generated subclass).
+ * This table contains one entry per production and is indexed by
+ * the negative-encoded values (reduce actions) in the action_table.
+ * Each entry has two parts, the index of the non-terminal on the
+ * left hand side of the production, and the number of symbols
+ * on the right hand side.
+ */
+ public abstract short[][] production_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The action table (supplied by generated subclass). This table is
+ * indexed by state and terminal number indicating what action is to
+ * be taken when the parser is in the given state (i.e., the given state
+ * is on top of the stack) and the given terminal is next on the input.
+ * States are indexed using the first dimension, however, the entries for
+ * a given state are compacted and stored in adjacent index, value pairs
+ * which are searched for rather than accessed directly (see get_action()).
+ * The actions stored in the table will be either shifts, reduces, or
+ * errors. Shifts are encoded as positive values (one greater than the
+ * state shifted to). Reduces are encoded as negative values (one less
+ * than the production reduced by). Error entries are denoted by zero.
+ *
+ * @see java_cup.runtime.lr_parser#get_action
+ */
+ public abstract short[][] action_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The reduce-goto table (supplied by generated subclass). This
+ * table is indexed by state and non-terminal number and contains
+ * state numbers. States are indexed using the first dimension, however,
+ * the entries for a given state are compacted and stored in adjacent
+ * index, value pairs which are searched for rather than accessed
+ * directly (see get_reduce()). When a reduce occurs, the handle
+ * (corresponding to the RHS of the matched production) is popped off
+ * the stack. The new top of stack indicates a state. This table is
+ * then indexed by that state and the LHS of the reducing production to
+ * indicate where to "shift" to.
+ *
+ * @see java_cup.runtime.lr_parser#get_reduce
+ */
+ public abstract short[][] reduce_table();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start state (supplied by generated subclass). */
+ public abstract int start_state();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the start production (supplied by generated subclass). */
+ public abstract int start_production();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the end of file terminal symbol (supplied by generated
+ * subclass).
+ */
+ public abstract int EOF_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The index of the special error symbol (supplied by generated subclass). */
+ public abstract int error_sym();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Internal flag to indicate when parser should quit. */
+ protected boolean _done_parsing = false;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called to indicate that the parser should quit. This is
+ * normally called by an accept action, but can be used to cancel parsing
+ * early in other circumstances if desired.
+ */
+ public void done_parsing()
+ {
+ _done_parsing = true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Global parse state shared by parse(), error recovery, and
+ * debugging routines */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indication of the index for top of stack (for use by actions). */
+ protected int tos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The current lookahead token. */
+ protected token cur_token;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse stack itself. */
+ protected Stack stack = new Stack();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the production table. */
+ protected short[][] production_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the action table. */
+ protected short[][] action_tab;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Direct reference to the reduce-goto table. */
+ protected short[][] reduce_tab;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Perform a bit of user supplied action code (supplied by generated
+ * subclass). Actions are indexed by an internal action number assigned
+ * at parser generation time.
+ *
+ * @param act_num the internal index of the action to be performed.
+ * @param parser the parser object we are acting for.
+ * @param stack the parse stack of that object.
+ * @param top the index of the top element of the parse stack.
+ */
+ public abstract symbol do_action(
+ int act_num,
+ lr_parser parser,
+ Stack stack,
+ int top)
+ throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** User code for initialization inside the parser. Typically this
+ * initializes the scanner. This is called before the parser requests
+ * the first token. Here this is just a placeholder for subclasses that
+ * might need this and we perform no action. This method is normally
+ * overridden by the generated code using this contents of the "init with"
+ * clause as its body.
+ */
+ public void user_init() throws java.lang.Exception { }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Initialize the action object. This is called before the parser does
+ * any parse actions. This is filled in by generated code to create
+ * an object that encapsulates all action code.
+ */
+ protected abstract void init_actions() throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Get the next token from the input (supplied by generated subclass).
+ * Once end of file has been reached, all subsequent calls to scan
+ * should return an EOF token (which is symbol number 0). This method
+ * is supplied by the generator using using the code declared in the
+ * "scan with" clause.
+ */
+ public abstract token scan() throws java.lang.Exception;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a fatal error. This method takes a message string and an
+ * additional object (to be used by specializations implemented in
+ * subclasses). Here in the base class a very simple implementation
+ * is provided which reports the error then throws an exception.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_fatal_error(
+ String message,
+ Object info)
+ throws java.lang.Exception
+ {
+ /* stop parsing (not really necessary since we throw an exception, but) */
+ done_parsing();
+
+ /* use the normal error message reporting to put out the message */
+ report_error(message, info);
+
+ /* throw an exception */
+ throw new Exception("Can't recover from previous error(s)");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Report a non fatal error (or warning). This method takes a message
+ * string and an additional object (to be used by specializations
+ * implemented in subclasses). Here in the base class a very simple
+ * implementation is provided which simply prints the message to
+ * System.err.
+ *
+ * @param message an error message.
+ * @param info an extra object reserved for use by specialized subclasses.
+ */
+ public void report_error(String message, Object info)
+ {
+ System.err.println(message);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called when a syntax error has been detected and recovery
+ * is about to be invoked. Here in the base class we just emit a
+ * "Syntax error" error message.
+ *
+ * @param cur_token the current lookahead token.
+ */
+ public void syntax_error(token cur_token)
+ {
+ report_error("Syntax error", null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method is called if it is determined that syntax error recovery
+ * has been unsuccessful. Here in the base class we report a fatal error.
+ *
+ * @param cur_token the current lookahead token.
+ */
+ public void unrecovered_syntax_error(token cur_token)
+ throws java.lang.Exception
+ {
+ report_fatal_error("Couldn't repair and continue parse", null);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch an action from the action table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a symbol index of -1). To find the proper entry in a row
+ * we do a linear or binary search (depending on the size of the row).
+ *
+ * @param state the state index of the action being accessed.
+ * @param sym the symbol index of the action being accessed.
+ */
+ protected final short get_action(int state, int sym)
+ {
+ short tag;
+ int first, last, probe;
+ short[] row = action_tab[state];
+
+ /* linear search if we are < 10 entries */
+ if (row.length < 20)
+ for (probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* otherwise binary search */
+ else
+ {
+ first = 0;
+ last = (row.length-1)/2 - 1; /* leave out trailing default entry */
+ while (first <= last)
+ {
+ probe = (first+last)/2;
+ if (sym == row[probe*2])
+ return row[probe*2+1];
+ else if (sym > row[probe*2])
+ first = probe+1;
+ else
+ last = probe-1;
+ }
+
+ /* not found, use the default at the end */
+ return row[row.length-1];
+ }
+
+ /* shouldn't happened, but if we run off the end we return the
+ default (error == 0) */
+ return 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Fetch a state from the reduce-goto table. The table is broken up into
+ * rows, one per state (rows are indexed directly by state number).
+ * Within each row, a list of index, value pairs are given (as sequential
+ * entries in the table), and the list is terminated by a default entry
+ * (denoted with a symbol index of -1). To find the proper entry in a row
+ * we do a linear search.
+ *
+ * @param state the state index of the entry being accessed.
+ * @param sym the symbol index of the entry being accessed.
+ */
+ protected final short get_reduce(int state, int sym)
+ {
+ short tag;
+ short[] row = reduce_tab[state];
+
+ /* if we have a null row we go with the default */
+ if (row == null)
+ return -1;
+
+ for (int probe = 0; probe < row.length; probe++)
+ {
+ /* is this entry labeled with our symbol or the default? */
+ tag = row[probe++];
+ if (tag == sym || tag == -1)
+ {
+ /* return the next entry */
+ return row[probe];
+ }
+ }
+ /* if we run off the end we return the default (error == -1) */
+ return -1;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** This method provides the main parsing routine. It returns only when
+ * done_parsing() has been called (typically because the parser has
+ * accepted, or a fatal error has been reported). See the header
+ * documentation for the class regarding how shift/reduce parsers operate
+ * and how the various tables are used.
+ */
+ public void parse() throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the symbol/stack element returned by a reduce */
+ symbol lhs_sym;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* get the first token */
+ cur_token = scan();
+
+ /* push dummy symbol with start state to get us underway */
+ stack.push(new symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next token */
+ cur_token = scan();
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ stack.push(lhs_sym);
+ tos++;
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(false))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Write a debugging message to System.err for the debugging version
+ * of the parser.
+ *
+ * @param mess the text of the debugging message.
+ */
+ public void debug_message(String mess)
+ {
+ System.err.println(mess);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Dump the parse stack for debugging purposes. */
+ public void dump_stack()
+ {
+ if (stack == null)
+ {
+ debug_message("# Stack dump requested, but stack is null");
+ return;
+ }
+
+ debug_message("============ Parse Stack Dump ============");
+
+ /* dump the stack */
+ for (int i=0; i<stack.size(); i++)
+ {
+ debug_message("Symbol: " + ((symbol)stack.elementAt(i)).sym +
+ " State: " + ((symbol)stack.elementAt(i)).parse_state);
+ }
+ debug_message("==========================================");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for a reduce.
+ *
+ * @param prod_num the production we are reducing with.
+ * @param nt_num the index of the LHS non terminal.
+ * @param rhs_size the size of the RHS.
+ */
+ public void debug_reduce(int prod_num, int nt_num, int rhs_size)
+ {
+ debug_message("# Reduce with prod #" + prod_num + " [NT=" + nt_num +
+ ", " + "SZ=" + rhs_size + "]");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do debug output for shift.
+ *
+ * @param shift_tkn the token being shifted onto the stack.
+ */
+ public void debug_shift(token shift_tkn)
+ {
+ debug_message("# Shift under term #" + shift_tkn.sym +
+ " to state #" + shift_tkn.parse_state);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Perform a parse with debugging output. This does exactly the
+ * same things as parse(), except that it calls debug_shift() and
+ * debug_reduce() when shift and reduce moves are taken by the parser
+ * and produces various other debugging messages.
+ */
+ public void debug_parse()
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the symbol/stack element returned by a reduce */
+ symbol lhs_sym;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* set up direct reference to tables to drive the parser */
+ production_tab = production_table();
+ action_tab = action_table();
+ reduce_tab = reduce_table();
+
+ debug_message("# Initializing parser");
+
+ /* initialize the action encapsulation object */
+ init_actions();
+
+ /* do user initialization */
+ user_init();
+
+ /* the current token */
+ cur_token = scan();
+
+ debug_message("# Current token is #" + cur_token.sym);
+
+ /* push dummy symbol with start state to get us underway */
+ stack.push(new symbol(0, start_state()));
+ tos = 0;
+
+ /* continue until we are told to stop */
+ for (_done_parsing = false; !_done_parsing; )
+ {
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act = get_action(((symbol)stack.peek()).parse_state, cur_token.sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_token.parse_state = act-1;
+ debug_shift(cur_token);
+ stack.push(cur_token);
+ tos++;
+
+ /* advance to the next token */
+ cur_token = scan();
+ debug_message("# Current token is #" + cur_token.sym);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ stack.push(lhs_sym);
+ tos++;
+
+ debug_message("# Goto state #" + act);
+ }
+ /* finally if the entry is zero, we have an error */
+ else if (act == 0)
+ {
+ /* call user syntax error reporting routine */
+ syntax_error(cur_token);
+
+ /* try to error recover */
+ if (!error_recovery(true))
+ {
+ /* if that fails give up with a fatal syntax error */
+ unrecovered_syntax_error(cur_token);
+
+ /* just in case that wasn't fatal enough, end parse */
+ done_parsing();
+ }
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+ /* Error recovery code */
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Attempt to recover from a syntax error. This returns false if recovery
+ * fails, true if it succeeds. Recovery happens in 4 steps. First we
+ * pop the parse stack down to a point at which we have a shift out
+ * of the top-most state on the error symbol. This represents the
+ * initial error recovery configuration. If no such configuration is
+ * found, then we fail. Next a small number of "lookahead" or "parse
+ * ahead" tokens are read into a buffer. The size of this buffer is
+ * determined by error_sync_size() and determines how many tokens beyond
+ * the error must be matched to consider the recovery a success. Next,
+ * we begin to discard tokens in attempt to get past the point of error
+ * to a point where we can continue parsing. After each token, we attempt
+ * to "parse ahead" though the buffered lookahead tokens. The "parse ahead"
+ * process simulates that actual parse, but does not modify the real
+ * parser's configuration, nor execute any actions. If we can parse all
+ * the stored tokens without error, then the recovery is considered a
+ * success. Once a successful recovery point is determined, we do an
+ * actual parse over the stored input -- modifying the real parse
+ * configuration and executing all actions. Finally, we return the the
+ * normal parser to continue with the overall parse.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean error_recovery(boolean debug)
+ throws java.lang.Exception
+ {
+ if (debug) debug_message("# Attempting error recovery");
+
+ /* first pop the stack back into a state that can shift on error and
+ do that shift (if that fails, we fail) */
+ if (!find_recovery_config(debug))
+ {
+ if (debug) debug_message("# Error recovery fails");
+ return false;
+ }
+
+ /* read ahead to create lookahead we can parse multiple times */
+ read_lookahead();
+
+ /* repeatedly try to parse forward until we make it the required dist */
+ for (;;)
+ {
+ /* try to parse forward, if it makes it, bail out of loop */
+ if (debug) debug_message("# Trying to parse ahead");
+ if (try_parse_ahead(debug))
+ {
+ break;
+ }
+
+ /* if we are now at EOF, we have failed */
+ if (lookahead[0].sym == EOF_sym())
+ {
+ if (debug) debug_message("# Error recovery fails at EOF");
+ return false;
+ }
+
+ /* otherwise, we consume another token and try again */
+ if (debug)
+ debug_message("# Consuming token #" + cur_err_token().sym);
+ restart_lookahead();
+ }
+
+ /* we have consumed to a point where we can parse forward */
+ if (debug) debug_message("# Parse-ahead ok, going back to normal parse");
+
+ /* do the real parse (including actions) across the lookahead */
+ parse_lookahead(debug);
+
+ /* we have success */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we can shift under the special error symbol out of the
+ * state currently on the top of the (real) parse stack.
+ */
+ protected boolean shift_under_error()
+ {
+ /* is there a shift under error symbol */
+ return get_action(((symbol)stack.peek()).parse_state, error_sym()) > 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Put the (real) parse stack into error recovery configuration by
+ * popping the stack down to a state that can shift on the special
+ * error symbol, then doing the shift. If no suitable state exists on
+ * the stack we return false
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean find_recovery_config(boolean debug)
+ {
+ token error_token;
+ int act;
+
+ if (debug) debug_message("# Finding recovery state on stack");
+
+ /* pop down until we can shift under error token */
+ while (!shift_under_error())
+ {
+ /* pop the stack */
+ if (debug)
+ debug_message("# Pop stack by one, state was # " +
+ ((symbol)stack.peek()).parse_state);
+ stack.pop();
+ tos--;
+
+ /* if we have hit bottom, we fail */
+ if (stack.empty())
+ {
+ if (debug) debug_message("# No recovery state found on stack");
+ return false;
+ }
+ }
+
+ /* state on top of the stack can shift under error, find the shift */
+ act = get_action(((symbol)stack.peek()).parse_state, error_sym());
+ if (debug)
+ {
+ debug_message("# Recover state found (#" +
+ ((symbol)stack.peek()).parse_state + ")");
+ debug_message("# Shifting on error to state #" + (act-1));
+ }
+
+ /* build and shift a special error token */
+ error_token = new token(error_sym());
+ error_token.parse_state = act-1;
+ stack.push(error_token);
+ tos++;
+
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Lookahead tokens used for attempting error recovery "parse aheads". */
+ protected token lookahead[];
+
+ /** Position in lookahead input buffer used for "parse ahead". */
+ protected int lookahead_pos;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Read from input to establish our buffer of "parse ahead" lookahead
+ * symbols.
+ */
+ protected void read_lookahead() throws java.lang.Exception
+ {
+ /* create the lookahead array */
+ lookahead = new token[error_sync_size()];
+
+ /* fill in the array */
+ for (int i = 0; i < error_sync_size(); i++)
+ {
+ lookahead[i] = cur_token;
+ cur_token = scan();
+ }
+
+ /* start at the beginning */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the current lookahead in our error "parse ahead" buffer. */
+ protected token cur_err_token() { return lookahead[lookahead_pos]; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Advance to next "parse ahead" input symbol. Return true if we have
+ * input to advance to, false otherwise.
+ */
+ protected boolean advance_lookahead()
+ {
+ /* advance the input location */
+ lookahead_pos++;
+
+ /* return true if we didn't go off the end */
+ return lookahead_pos < error_sync_size();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Reset the parse ahead input to one token past where we started error
+ * recovery (this consumes one new token from the real input).
+ */
+ protected void restart_lookahead() throws java.lang.Exception
+ {
+ /* move all the existing input over */
+ for (int i = 1; i < error_sync_size(); i++)
+ lookahead[i-1] = lookahead[i];
+
+ /* read a new token into the last spot */
+ cur_token = scan();
+ lookahead[error_sync_size()-1] = cur_token;
+
+ /* reset our internal position marker */
+ lookahead_pos = 0;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Do a simulated parse forward (a "parse ahead") from the current
+ * stack configuration using stored lookahead input and a virtual parse
+ * stack. Return true if we make it all the way through the stored
+ * lookahead input without error. This basically simulates the action of
+ * parse() using only our saved "parse ahead" input, and not executing any
+ * actions.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected boolean try_parse_ahead(boolean debug)
+ throws java.lang.Exception
+ {
+ int act;
+ short lhs, rhs_size;
+
+ /* create a virtual stack from the real parse stack */
+ virtual_parse_stack vstack = new virtual_parse_stack(stack);
+
+ /* parse until we fail or get past the lookahead input */
+ for (;;)
+ {
+ /* look up the action from the current state (on top of stack) */
+ act = get_action(vstack.top(), cur_err_token().sym);
+
+ /* if its an error, we fail */
+ if (act == 0) return false;
+
+ /* > 0 encodes a shift */
+ if (act > 0)
+ {
+ /* push the new state on the stack */
+ vstack.push(act-1);
+
+ if (debug) debug_message("# Parse-ahead shifts token #" +
+ cur_err_token().sym + " into state #" + (act-1));
+
+ /* advance simulated input, if we run off the end, we are done */
+ if (!advance_lookahead()) return true;
+ }
+ /* < 0 encodes a reduce */
+ else
+ {
+ /* if this is a reduce with the start production we are done */
+ if ((-act)-1 == start_production())
+ {
+ if (debug) debug_message("# Parse-ahead accepts");
+ return true;
+ }
+
+ /* get the lhs symbol and the rhs size */
+ lhs = production_tab[(-act)-1][0];
+ rhs_size = production_tab[(-act)-1][1];
+
+ /* pop handle off the stack */
+ for (int i = 0; i < rhs_size; i++)
+ vstack.pop();
+
+ if (debug)
+ debug_message("# Parse-ahead reduces: handle size = " +
+ rhs_size + " lhs = #" + lhs + " from state #" + vstack.top());
+
+ /* look up goto and push it onto the stack */
+ vstack.push(get_reduce(vstack.top(), lhs));
+ if (debug)
+ debug_message("# Goto state #" + vstack.top());
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse forward using stored lookahead symbols. In this case we have
+ * already verified that parsing will make it through the stored lookahead
+ * symbols and we are now getting back to the point at which we can hand
+ * control back to the normal parser. Consequently, this version of the
+ * parser performs all actions and modifies the real parse configuration.
+ * This returns once we have consumed all the stored input or we accept.
+ *
+ * @param debug should we produce debugging messages as we parse.
+ */
+ protected void parse_lookahead(boolean debug)
+ throws java.lang.Exception
+ {
+ /* the current action code */
+ int act;
+
+ /* the symbol/stack element returned by a reduce */
+ symbol lhs_sym;
+
+ /* information about production being reduced with */
+ short handle_size, lhs_sym_num;
+
+ /* restart the saved input at the beginning */
+ lookahead_pos = 0;
+
+ if (debug)
+ {
+ debug_message("# Reparsing saved input with actions");
+ debug_message("# Current token is #" + cur_err_token().sym);
+ debug_message("# Current state is #" +
+ ((symbol)stack.peek()).parse_state);
+ }
+
+ /* continue until we accept or have read all lookahead input */
+ while(!_done_parsing)
+ {
+ /* current state is always on the top of the stack */
+
+ /* look up action out of the current state with the current input */
+ act =
+ get_action(((symbol)stack.peek()).parse_state, cur_err_token().sym);
+
+ /* decode the action -- > 0 encodes shift */
+ if (act > 0)
+ {
+ /* shift to the encoded state by pushing it on the stack */
+ cur_err_token().parse_state = act-1;
+ if (debug) debug_shift(cur_err_token());
+ stack.push(cur_err_token());
+ tos++;
+
+ /* advance to the next token, if there is none, we are done */
+ if (!advance_lookahead())
+ {
+ if (debug) debug_message("# Completed reparse");
+
+ /* scan next token so we can continue parse */
+ cur_token = scan();
+
+ /* go back to normal parser */
+ return;
+ }
+
+ if (debug)
+ debug_message("# Current token is #" + cur_err_token().sym);
+ }
+ /* if its less than zero, then it encodes a reduce action */
+ else if (act < 0)
+ {
+ /* perform the action for the reduce */
+ lhs_sym = do_action((-act)-1, this, stack, tos);
+
+ /* look up information about the production */
+ lhs_sym_num = production_tab[(-act)-1][0];
+ handle_size = production_tab[(-act)-1][1];
+
+ if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size);
+
+ /* pop the handle off the stack */
+ for (int i = 0; i < handle_size; i++)
+ {
+ stack.pop();
+ tos--;
+ }
+
+ /* look up the state to go to from the one popped back to */
+ act = get_reduce(((symbol)stack.peek()).parse_state, lhs_sym_num);
+
+ /* shift to that state */
+ lhs_sym.parse_state = act;
+ stack.push(lhs_sym);
+ tos++;
+
+ if (debug) debug_message("# Goto state #" + act);
+
+ }
+ /* finally if the entry is zero, we have an error
+ (shouldn't happen here, but...)*/
+ else if (act == 0)
+ {
+ report_fatal_error("Syntax error", null);
+ return;
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/runtime/str_token.java b/tools/dasm/src/java_cup/runtime/str_token.java
new file mode 100644
index 0000000..96e2c94
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/str_token.java
@@ -0,0 +1,32 @@
+
+package java_cup.runtime;
+
+/** This subclass of token represents symbols that need to maintain one
+ * String value as an attribute. It maintains that value in the public
+ * field str_val.
+ *
+ * @see java_cup.runtime.int_token
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class str_token extends token {
+ /** Full constructor. */
+ public str_token(int term_num, String v)
+ {
+ /* super class does most of the work */
+ super(term_num);
+
+ str_val = v;
+ }
+
+ /** Constructor for value defaulting to an empty string. */
+ public str_token(int term_num)
+ {
+ this(term_num, "");
+ }
+
+ /** The stored string value. */
+ public String str_val;
+
+};
diff --git a/tools/dasm/src/java_cup/runtime/symbol.java b/tools/dasm/src/java_cup/runtime/symbol.java
new file mode 100644
index 0000000..ac0fe5a
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/symbol.java
@@ -0,0 +1,50 @@
+
+package java_cup.runtime;
+
+/** This class represents a (terminal or non-terminal) symbol that, among
+ * other things can be placed on the parse stack. Symbols are used to
+ * keep track of state on the parse stack. The symbol currently on top
+ * of the stack contains the current state in the parse_state field.
+ * In addition to the parse_state field, symbols also maintain a record
+ * of the symbol number that they represent in the sym field. Finally,
+ * symbols are used contain to any attributes used by semantic action (this
+ * is done via fields added in subclasses -- see for example, int_token and
+ * str_token).
+ *
+ * @see java_cup.runtime.token
+ * @see java_cup.runtime.int_token
+ * @see java_cup.runtime.str_token
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class symbol {
+
+ /** Full constructor. */
+ public symbol(int sym_num, int state)
+ {
+ sym = sym_num;
+ parse_state = state;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor without a known state. */
+ public symbol(int sym_num)
+ {
+ this(sym_num, -1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The symbol number of the terminal or non terminal being represented */
+ public int sym;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The parse state to be recorded on the parse stack with this symbol.
+ * This field is for the convenience of the parser and shouldn't be
+ * modified except by the parser.
+ */
+ public int parse_state;
+};
diff --git a/tools/dasm/src/java_cup/runtime/token.java b/tools/dasm/src/java_cup/runtime/token.java
new file mode 100644
index 0000000..0df9b81
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/token.java
@@ -0,0 +1,21 @@
+
+package java_cup.runtime;
+
+/** This subclass of symbol represents (at least) terminal symbols returned
+ * by the scanner and placed on the parse stack. At present, this
+ * class does nothing more than its super class.
+ *
+ * @see java_cup.runtime.int_token
+ * @see java_cup.runtime.str_token
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class token extends symbol {
+
+ /* Simple constructor -- just delegates to the super class. */
+ public token(int term_num)
+ {
+ /* super class does all the work */
+ super(term_num);
+ }
+};
diff --git a/tools/dasm/src/java_cup/runtime/virtual_parse_stack.java b/tools/dasm/src/java_cup/runtime/virtual_parse_stack.java
new file mode 100644
index 0000000..507b755
--- /dev/null
+++ b/tools/dasm/src/java_cup/runtime/virtual_parse_stack.java
@@ -0,0 +1,145 @@
+
+package java_cup.runtime;
+
+import java.util.Stack;
+
+/** This class implements a temporary or "virtual" parse stack that
+ * replaces the top portion of the actual parse stack (the part that
+ * has been changed by some set of operations) while maintaining its
+ * original contents. This data structure is used when the parse needs
+ * to "parse ahead" to determine if a given error recovery attempt will
+ * allow the parse to continue far enough to consider it successful. Once
+ * success or failure of parse ahead is determined the system then
+ * reverts to the original parse stack (which has not actually been
+ * modified). Since parse ahead does not execute actions, only parse
+ * state is maintained on the virtual stack, not full symbol objects.
+ *
+ * @see java_cup.runtime.lr_parser
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+
+public class virtual_parse_stack {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor to build a virtual stack out of a real stack. */
+ public virtual_parse_stack(Stack shadowing_stack) throws java.lang.Exception
+ {
+ /* sanity check */
+ if (shadowing_stack == null)
+ throw new Exception(
+ "Internal parser error: attempt to create null virtual stack");
+
+ /* set up our internals */
+ real_stack = shadowing_stack;
+ vstack = new Stack();
+ real_next = 0;
+
+ /* get one element onto the virtual portion of the stack */
+ get_from_real();
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The real stack that we shadow. This is accessed when we move off
+ * the bottom of the virtual portion of the stack, but is always left
+ * unmodified.
+ */
+ protected Stack real_stack;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Top of stack indicator for where we leave off in the real stack.
+ * This is measured from top of stack, so 0 would indicate that no
+ * elements have been "moved" from the real to virtual stack.
+ */
+ protected int real_next;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The virtual top portion of the stack. This stack contains Integer
+ * objects with state numbers. This stack shadows the top portion
+ * of the real stack within the area that has been modified (via operations
+ * on the virtual stack). When this portion of the stack becomes empty we
+ * transfer elements from the underlying stack onto this stack.
+ */
+ protected Stack vstack;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Transfer an element from the real to the virtual stack. This assumes
+ * that the virtual stack is currently empty.
+ */
+ protected void get_from_real()
+ {
+ symbol stack_sym;
+
+ /* don't transfer if the real stack is empty */
+ if (real_next >= real_stack.size()) return;
+
+ /* get a copy of the first symbol we have not transfered */
+ stack_sym = (symbol)real_stack.elementAt(real_stack.size()-1-real_next);
+
+ /* record the transfer */
+ real_next++;
+
+ /* put the state number from the symbol onto the virtual stack */
+ vstack.push(new Integer(stack_sym.parse_state));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate whether the stack is empty. */
+ public boolean empty()
+ {
+ /* if vstack is empty then we were unable to transfer onto it and
+ the whole thing is empty. */
+ return vstack.empty();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return value on the top of the stack (without popping it). */
+ public int top() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: top() called on empty virtual stack");
+
+ return ((Integer)vstack.peek()).intValue();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Pop the stack. */
+ public void pop() throws java.lang.Exception
+ {
+ if (vstack.empty())
+ throw new Exception(
+ "Internal parser error: pop from empty virtual stack");
+
+ /* pop it */
+ vstack.pop();
+
+ /* if we are now empty transfer an element (if there is one) */
+ if (vstack.empty())
+ get_from_real();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Push a state number onto the stack. */
+ public void push(int state_num)
+ {
+ vstack.push(new Integer(state_num));
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/shift_action.java b/tools/dasm/src/java_cup/shift_action.java
new file mode 100644
index 0000000..f1513cd
--- /dev/null
+++ b/tools/dasm/src/java_cup/shift_action.java
@@ -0,0 +1,82 @@
+
+package java_cup;
+
+/** This class represents a shift action within the parse table.
+ * The action simply stores the state that it shifts to and responds
+ * to queries about its type.
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class shift_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ * @param shft_to the state that this action shifts to.
+ */
+ public shift_action(lalr_state shft_to) throws internal_error
+ {
+ /* sanity check */
+ if (shft_to == null)
+ throw new internal_error(
+ "Attempt to create a shift_action to a null state");
+
+ _shift_to = shft_to;
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The state we shift to. */
+ protected lalr_state _shift_to;
+
+ /** The state we shift to. */
+ public lalr_state shift_to() {return _shift_to;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return SHIFT;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(shift_action other)
+ {
+ return other != null && other.shift_to() == shift_to();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality test. */
+ public boolean equals(Object other)
+ {
+ if (other instanceof shift_action)
+ return equals((shift_action)other);
+ else
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ /* use the hash code of the state we are shifting to */
+ return shift_to().hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString() {return "SHIFT(" + shift_to().index() + ")";}
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/sym.java b/tools/dasm/src/java_cup/sym.java
new file mode 100644
index 0000000..3987e25
--- /dev/null
+++ b/tools/dasm/src/java_cup/sym.java
@@ -0,0 +1,36 @@
+
+//----------------------------------------------------
+// The following code was generated by Java(tm) CUP v0.9d
+// Thu Aug 10 03:51:39 MSD 2006
+//----------------------------------------------------
+
+package java_cup;
+
+/** JavaCup generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ static final int IMPORT = 3;
+ static final int INIT = 9;
+ static final int CODE_STRING = 22;
+ static final int DEBUG = 20;
+ static final int SEMI = 13;
+ static final int STAR = 15;
+ static final int CODE = 4;
+ static final int COLON = 17;
+ static final int NON = 8;
+ static final int ID = 21;
+ static final int WITH = 11;
+ static final int TERMINAL = 7;
+ static final int COLON_COLON_EQUALS = 18;
+ static final int COMMA = 14;
+ static final int EOF = 0;
+ static final int PARSER = 6;
+ static final int error = 1;
+ static final int DOT = 16;
+ static final int ACTION = 5;
+ static final int START = 12;
+ static final int PACKAGE = 2;
+ static final int BAR = 19;
+ static final int SCAN = 10;
+};
+
diff --git a/tools/dasm/src/java_cup/symbol.java b/tools/dasm/src/java_cup/symbol.java
new file mode 100644
index 0000000..1c99640
--- /dev/null
+++ b/tools/dasm/src/java_cup/symbol.java
@@ -0,0 +1,107 @@
+package java_cup;
+
+/** This abstract class serves as the base class for grammar symbols (i.e.,
+ * both terminals and non-terminals). Each symbol has a name string, and
+ * a string giving the type of object that the symbol will be represented by
+ * on the runtime parse stack. In addition, each symbol maintains a use count
+ * in order to detect symbols that are declared but never used, and an index
+ * number that indicates where it appears in parse tables (index numbers are
+ * unique within terminals or non terminals, but not across both).
+ *
+ * @see java_cup.terminal
+ * @see java_cup.non_terminal
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public abstract class symbol {
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the symbol.
+ * @param tp a string with the type name.
+ */
+ public symbol(String nm, String tp)
+ {
+ /* sanity check */
+ if (nm == null) nm = "";
+
+ /* apply default if no type given */
+ if (tp == null) tp = "java_cup.runtime.token";
+
+ _name = nm;
+ _stack_type = tp;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the symbol.
+ */
+ public symbol(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** String for the human readable name of the symbol. */
+ protected String _name;
+
+ /** String for the human readable name of the symbol. */
+ public String name() {return _name;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ protected String _stack_type;
+
+ /** String for the type of object used for the symbol on the parse stack. */
+ public String stack_type() {return _stack_type;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Count of how many times the symbol appears in productions. */
+ protected int _use_count = 0;
+
+ /** Count of how many times the symbol appears in productions. */
+ public int use_count() {return _use_count;}
+
+ /** Increment the use count. */
+ public void note_use() {_use_count++;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ protected int _index;
+
+ /** Index of this symbol (terminal or non terminal) in the parse tables.
+ * Note: indexes are unique among terminals and unique among non terminals,
+ * however, a terminal may have the same index as a non-terminal, etc.
+ */
+ public int index() {return _index;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Indicate if this is a non-terminal. Here in the base class we
+ * don't know, so this is abstract.
+ */
+ public abstract boolean is_non_term();
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return name();
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/symbol_part.java b/tools/dasm/src/java_cup/symbol_part.java
new file mode 100644
index 0000000..e923af6
--- /dev/null
+++ b/tools/dasm/src/java_cup/symbol_part.java
@@ -0,0 +1,100 @@
+package java_cup;
+
+/** This class represents a part of a production which is a symbol (terminal
+ * or non terminal). This simply maintains a reference to the symbol in
+ * question.
+ *
+ * @see java_cup.production
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_part extends production_part {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param sym the symbol that this part is made up of.
+ * @param lab an optional label string for the part.
+ */
+ public symbol_part(symbol sym, String lab) throws internal_error
+ {
+ super(lab);
+
+ if (sym == null)
+ throw new internal_error(
+ "Attempt to construct a symbol_part with a null symbol");
+ _the_symbol = sym;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with no label.
+ * @param sym the symbol that this part is made up of.
+ */
+ public symbol_part(symbol sym) throws internal_error
+ {
+ this(sym,null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The symbol that this part is made up of. */
+ protected symbol _the_symbol;
+
+ /** The symbol that this part is made up of. */
+ public symbol the_symbol() {return _the_symbol;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Respond that we are not an action part. */
+ public boolean is_action() { return false; }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_part other)
+ {
+ return other != null && super.equals(other) &&
+ the_symbol().equals(other.the_symbol());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_part))
+ return false;
+ else
+ return equals((symbol_part)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a hash code. */
+ public int hashCode()
+ {
+ return super.hashCode() ^
+ (the_symbol()==null ? 0 : the_symbol().hashCode());
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ if (the_symbol() != null)
+ return super.toString() + the_symbol();
+ else
+ return super.toString() + "$$MISSING-SYMBOL$$";
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/symbol_set.java b/tools/dasm/src/java_cup/symbol_set.java
new file mode 100644
index 0000000..ef478be
--- /dev/null
+++ b/tools/dasm/src/java_cup/symbol_set.java
@@ -0,0 +1,231 @@
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/** This class represents a set of symbols and provides a series of
+ * set operations to manipulate them.
+ *
+ * @see java_cup.symbol
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class symbol_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public symbol_set() { };
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public symbol_set(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ _all = (Hashtable)other._all.clone();
+ };
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** A hash table to hold the set. Symbols are keyed using their name string.
+ */
+ protected Hashtable _all = new Hashtable(11);
+
+ /** Access to all elements of the set. */
+ public Enumeration all() {return _all.elements();};
+
+ /** size of the set */
+ public int size() {return _all.size();};
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception
+ * if one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular symbol.
+ * @param sym the symbol we are looking for.
+ */
+ public boolean contains(symbol sym) {return _all.containsKey(sym.name());};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down our set and make sure every element is in the other */
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ if (!other.contains((symbol)e.nextElement()))
+ return false;
+
+ /* they were all there */
+ return true;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are are testing against.
+ */
+ public boolean is_superset_of(symbol_set other) throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single symbol to the set.
+ * @param sym the symbol we are adding.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol sym) throws internal_error
+ {
+ Object previous;
+
+ not_null(sym);
+
+ /* put the object in */
+ previous = _all.put(sym.name(),sym);
+
+ /* if we had a previous, this is no change */
+ return previous == null;
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a single symbol if it is in the set.
+ * @param sym the symbol we are removing.
+ */
+ public void remove(symbol sym) throws internal_error
+ {
+ not_null(sym);
+ _all.remove(sym.name());
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set we are adding in.
+ * @return true if this changes the set.
+ */
+ public boolean add(symbol_set other) throws internal_error
+ {
+ boolean result = false;
+
+ not_null(other);
+
+ /* walk down the other set and do the adds individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ result = add((symbol)e.nextElement()) || result;
+
+ return result;
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove (set subtract) a complete set.
+ * @param other the set we are removing.
+ */
+ public void remove(symbol_set other) throws internal_error
+ {
+ not_null(other);
+
+ /* walk down the other set and do the removes individually */
+ for (Enumeration e = other.all(); e.hasMoreElements(); )
+ remove((symbol)e.nextElement());
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(symbol_set other)
+ {
+ if (other == null || other.size() != size()) return false;
+
+ /* once we know they are the same size, then improper subset does test */
+ try {
+ return is_subset_of(other);
+ } catch (internal_error e) {
+ /* can't throw the error (because super class doesn't), so we crash */
+ e.crash();
+ return false;
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof symbol_set))
+ return false;
+ else
+ return equals((symbol_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Compute a hash code. */
+ public int hashCode()
+ {
+ int result = 0;
+ int cnt;
+ Enumeration e;
+
+ /* hash together codes from at most first 5 elements */
+ for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++)
+ result ^= ((symbol)e.nextElement()).hashCode();
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (Enumeration e = all(); e.hasMoreElements(); )
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += ((symbol)e.nextElement()).name();
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
+
diff --git a/tools/dasm/src/java_cup/terminal.java b/tools/dasm/src/java_cup/terminal.java
new file mode 100644
index 0000000..bb8dfdd
--- /dev/null
+++ b/tools/dasm/src/java_cup/terminal.java
@@ -0,0 +1,130 @@
+package java_cup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/** This class represents a terminal symbol in the grammar. Each terminal
+ * has a textual name, an index, and a string which indicates the type of
+ * object it will be implemented with at runtime (i.e. the class of object
+ * that will be returned by the scanner and pushed on the parse stack to
+ * represent it).
+ *
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class terminal extends symbol {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param nm the name of the terminal.
+ * @param tp the type of the terminal.
+ */
+ public terminal(String nm, String tp)
+ {
+ /* superclass does most of the work */
+ super(nm, tp);
+
+ /* add to set of all terminals and check for duplicates */
+ Object conflict = _all.put(nm,this);
+ if (conflict != null)
+ // can't throw an execption here because this is used in static
+ // initializers, so we do a crash instead
+ // was:
+ // throw new internal_error("Duplicate terminal (" + nm + ") created");
+ (new internal_error("Duplicate terminal (" + nm + ") created")).crash();
+
+ /* assign a unique index */
+ _index = next_index++;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the terminal.
+ */
+ public terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Table of all terminals. Elements are stored using name strings as
+ * the key
+ */
+ protected static Hashtable _all = new Hashtable();
+
+ /** Access to all terminals. */
+ public static Enumeration all() {return _all.elements();};
+
+ /** Lookup a terminal by name string. */
+ public static terminal find(String with_name)
+ {
+ if (with_name == null)
+ return null;
+ else
+ return (terminal)_all.get(with_name);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a terminal by index. */
+ public static terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Total number of terminals. */
+ public static int number() {return _all.size();};
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Static counter to assign unique index. */
+ protected static int next_index = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Special terminal for end of input. */
+ public static final terminal EOF = new terminal("EOF");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** special terminal used for error recovery */
+ public static final terminal error = new terminal("error");
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Report this symbol as not being a non-terminal. */
+ public boolean is_non_term()
+ {
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string. */
+ public String toString()
+ {
+ return super.toString() + "[" + index() + "]";
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
diff --git a/tools/dasm/src/java_cup/terminal_set.java b/tools/dasm/src/java_cup/terminal_set.java
new file mode 100644
index 0000000..591233b
--- /dev/null
+++ b/tools/dasm/src/java_cup/terminal_set.java
@@ -0,0 +1,253 @@
+
+package java_cup;
+
+import java.util.BitSet;
+
+/** A set of terminals implemented as a bitset.
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+ */
+public class terminal_set {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constructor for an empty set. */
+ public terminal_set()
+ {
+ /* allocate the bitset at what is probably the right size */
+ _elements = new BitSet(terminal.number());
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for cloning from another set.
+ * @param other the set we are cloning from.
+ */
+ public terminal_set(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ _elements = (BitSet)other._elements.clone();
+ };
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Static (Class) Variables ------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Constant for the empty set. */
+ public static final terminal_set EMPTY = new terminal_set();
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Bitset to implement the actual set. */
+ protected BitSet _elements;
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Helper function to test for a null object and throw an exception if
+ * one is found.
+ * @param obj the object we are testing.
+ */
+ protected void not_null(Object obj) throws internal_error
+ {
+ if (obj == null)
+ throw new internal_error("Null object used in set operation");
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set is empty. */
+ public boolean empty()
+ {
+ return equals(EMPTY);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if the set contains a particular terminal.
+ * @param sym the terminal symbol we are looking for.
+ */
+ public boolean contains(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ return _elements.get(sym.index());
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Given its index determine if the set contains a particular terminal.
+ * @param indx the index of the terminal in question.
+ */
+ public boolean contains(int indx)
+ {
+ return _elements.get(indx);
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) subset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_subset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy_other = (BitSet)other._elements.clone();
+
+ /* and or in */
+ copy_other.or(_elements);
+
+ /* if it hasn't changed, we were a subset */
+ return copy_other.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set is an (improper) superset of another.
+ * @param other the set we are testing against.
+ */
+ public boolean is_superset_of(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+ return other.is_subset_of(this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add a single terminal to the set.
+ * @param sym the terminal being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal sym)
+ throws internal_error
+ {
+ boolean result;
+
+ not_null(sym);
+
+ /* see if we already have this */
+ result = _elements.get(sym.index());
+
+ /* if not we add it */
+ if (!result)
+ _elements.set(sym.index());
+
+ return result;
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Remove a terminal if it is in the set.
+ * @param sym the terminal being removed.
+ */
+ public void remove(terminal sym)
+ throws internal_error
+ {
+ not_null(sym);
+ _elements.clear(sym.index());
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Add (union) in a complete set.
+ * @param other the set being added.
+ * @return true if this changes the set.
+ */
+ public boolean add(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy */
+ BitSet copy = (BitSet)_elements.clone();
+
+ /* or in the other set */
+ _elements.or(other._elements);
+
+ /* changed if we are not the same as the copy */
+ return !_elements.equals(copy);
+ };
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if this set intersects another.
+ * @param other the other set in question.
+ */
+ public boolean intersects(terminal_set other)
+ throws internal_error
+ {
+ not_null(other);
+
+ /* make a copy of the other set */
+ BitSet copy = (BitSet)other._elements.clone();
+
+ /* xor out our values */
+ copy.xor(this._elements);
+
+ /* see if its different */
+ return !copy.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(terminal_set other)
+ {
+ if (other == null)
+ return false;
+ else
+ return _elements.equals(other._elements);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof terminal_set))
+ return false;
+ else
+ return equals((terminal_set)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to string. */
+ public String toString()
+ {
+ String result;
+ boolean comma_flag;
+
+ result = "{";
+ comma_flag = false;
+ for (int t = 0; t < terminal.number(); t++)
+ {
+ if (_elements.get(t))
+ {
+ if (comma_flag)
+ result += ", ";
+ else
+ comma_flag = true;
+
+ result += terminal.find(t).name();
+ }
+ }
+ result += "}";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+};
+
diff --git a/tools/dasm/src/java_cup/version.java b/tools/dasm/src/java_cup/version.java
new file mode 100644
index 0000000..40a9581
--- /dev/null
+++ b/tools/dasm/src/java_cup/version.java
@@ -0,0 +1,54 @@
+
+package java_cup;
+
+/** This class contains version and authorship information.
+ * It contains only static data elements and basically just a central
+ * place to put this kind of information so it can be updated easily
+ * for each release.
+ *
+ * Version numbers used here are broken into 3 parts: major, minor, and
+ * update, and are written as v<major>.<minor><update> (e.g. v0.9a).
+ * Major numbers will change at the time of major reworking of some
+ * part of the system. Minor numbers for each public release or
+ * change big enough to cause incompatibilities. Finally update
+ * letter will be incremented for small bug fixes and changes that
+ * probably wouldn't be noticed by a user.
+ *
+ * @version last updated: 1/7/96
+ * @author Scott Hudson
+ */
+
+public class version {
+ /** String for the current version. */
+ public static final String version_str = "v0.9d";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The major version number. */
+ public static final int major = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The minor version number. */
+ public static final int minor = 9;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The update letter. */
+ public static final char update = 'd';
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Full title of the system */
+ public static final String title_str = "Java(tm) CUP " + version_str;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the author */
+ public static final String author_str = "Scott E. Hudson";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The command name normally used to invoke this program */
+ public static final String program_name = "java_cup";
+};