--- /dev/null
+Date: Fri, 05 Feb 1999 17:11:08 -0600
+From: jon miner <jon.miner@doit.wisc.edu>
+To: cananian@alumni.princeton.edu
+Subject: Makefile for NT/DOS
+
+I've made (hah) a Makefile for java_cup that will install and test java_cup
+on NT/9x/DOS with GNU Make...
+
+You (should) find it attached.
+
+thanks,
+
+jon
+
+-------------------------------------------------------------
+Date: Sun, 07 Feb 1999 17:30:33 -0600
+From: Jon Miner <jon.miner@doit.wisc.edu>
+To: C. Scott Ananian <cananian@lesser-magoo.lcs.mit.edu>
+Subject: Re: Makefile for NT/DOS
+
+The Makefile included is for Microsoft's (I think) Nmake... it doesn't
+jive with just plain old GNU make (At least not on my machine..) Also, the
+Makefile I wrote _should_ (I haven't tested it, though) work (with minor
+changes) on Un*x and WinTel machines...
+
+thanks,
+
+jon
+
+[The makefile has been included in this directory. -- CSA 24-Mar-1998 ]
--- /dev/null
+SIMPLEDIR=SIMPLE~1
+# SIMPLEDIR=simple_calc
+RM=del
+# RM=rm
+JAVA=java
+JAVAOPTS=
+JAVAC=javac
+JAVACOPTS=-verbose
+
+
+test: java_cup\\Main.class java_cup\\$(SIMPLEDIR)\\Main.class
+ echo "1*-2+2;" | $(JAVA) $(JAVAOPTS) java_cup.simple_calc.Main
+
+ echo 'If the line above says "= 0" everything is OK.'
+
+
+java_cup\\Main.class:
+ $(JAVAC) $(JAVACOPTS) java_cup\\Main.java
+
+java_cup\\$(SIMPLEDIR)\\Main.class:
+ cd java_cup
+ cd $(SIMPLEDIR)
+ echo $(RM) parser.java
+ echo $(RM) sym.java
+ $(JAVA) $(JAVAOPTS) java_cup.Main < parser.cup
+ $(JAVAC) $(JAVACOPTS) Main.java
--- /dev/null
+
+package java_cup;
+
+import java.util.Enumeration;
+import java.io.*;
+
+/** 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> -interface
+ * <dd> emit symbol constant <i>interface</i>, rather than class
+ * <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
+ * <dt> -nopositions
+ * <dd> don't generate the positions code
+ * <dt> -noscanner
+ * <dd> don't refer to java_cup.runtime.Scanner in the parser
+ * (for compatibility with old runtimes)
+ * <dt> -version
+ * <dd> print version information for JavaCUP and halt.
+ * </dl>
+ *
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+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 = true;
+ /** 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;
+
+ /* frankf added this 6/18/96 */
+ /** User option -- should generator generate code for left/right values? */
+ protected static boolean lr_values = true;
+
+ /** User option -- should symbols be put in a class or an interface? [CSA]*/
+ protected static boolean sym_interface = false;
+
+ /** User option -- should generator suppress references to
+ * java_cup.runtime.Scanner for compatibility with old runtimes? */
+ protected static boolean suppress_scanner = false;
+
+ /*----------------------------------------------------------------------*/
+ /* Timing data (not all of these time intervals are mutually exclusive) */
+ /*----------------------------------------------------------------------*/
+ /** Timing data -- when did we start */
+ protected static long start_time = 0;
+ /** Timing data -- when did we end preliminaries */
+ protected static long prelim_end = 0;
+ /** Timing data -- when did we end parsing */
+ protected static long parse_end = 0;
+ /** Timing data -- when did we end checking */
+ protected static long check_end = 0;
+ /** Timing data -- when did we end dumping */
+ protected static long dump_end = 0;
+ /** Timing data -- when did we end state and table building */
+ protected static long build_end = 0;
+ /** Timing data -- when did we end nullability calculation */
+ protected static long nullability_end = 0;
+ /** Timing data -- when did we end first set calculation */
+ protected static long first_end = 0;
+ /** Timing data -- when did we end state machine construction */
+ protected static long machine_end = 0;
+ /** Timing data -- when did we end table construction */
+ protected static long table_end = 0;
+ /** Timing data -- when did we end checking for non-reduced productions */
+ protected static long reduce_check_end = 0;
+ /** Timing data -- when did we finish emitting code */
+ protected static long emit_end = 0;
+ /** Timing data -- when were we completely done */
+ protected static long final_time = 0;
+
+ /* Additional timing information is also collected in emit */
+
+ /*-----------------------------------------------------------*/
+ /*--- Main Program ------------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The main driver for the system.
+ * @param argv an array of strings containing command line arguments.
+ */
+ public static void main(String argv[])
+ throws internal_error, java.io.IOException, java.lang.Exception
+ {
+ boolean did_output = false;
+
+ start_time = System.currentTimeMillis();
+
+ /* process user options and arguments */
+ parse_args(argv);
+
+ /* frankf 6/18/96
+ hackish, yes, but works */
+ emit.set_lr_values(lr_values);
+ /* open output files */
+ if (print_progress) System.err.println("Opening files...");
+ /* use a buffered version of standard input */
+ input_file = new BufferedInputStream(System.in);
+
+ prelim_end = System.currentTimeMillis();
+
+ /* parse spec into internal data structures */
+ if (print_progress)
+ System.err.println("Parsing specification from standard input...");
+ parse_grammar_spec();
+
+ parse_end = System.currentTimeMillis();
+
+ /* don't proceed unless we are error free */
+ if (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 # of conflicts permits */
+ if (lexer.error_count != 0) {
+ // conflicts! don't emit code, don't dump tables.
+ opt_dump_tables = false;
+ } else { // everything's okay, emit parser.
+ if (print_progress) System.err.println("Writing parser...");
+ open_files();
+ emit_parser();
+ did_output = true;
+ }
+ }
+ /* fix up the times to make the summary easier */
+ emit_end = System.currentTimeMillis();
+
+ /* do requested dumps */
+ if (opt_dump_grammar) dump_grammar();
+ if (opt_dump_states) dump_machine();
+ if (opt_dump_tables) dump_tables();
+
+ dump_end = System.currentTimeMillis();
+
+ /* close input/output files */
+ if (print_progress) System.err.println("Closing files...");
+ close_files();
+
+ /* produce a summary if desired */
+ if (!no_summary) emit_summary(did_output);
+
+ /* If there were errors during the run,
+ * exit with non-zero status (makefile-friendliness). --CSA */
+ if (lexer.error_count != 0)
+ System.exit(100);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Print a "usage message" that described possible command line options,
+ * then exit.
+ * @param message a specific error message to preface the usage message by.
+ */
+ protected static void usage(String message)
+ {
+ System.err.println();
+ System.err.println(message);
+ System.err.println();
+ System.err.println(
+"Usage: " + version.program_name + " [options] [filename]\n" +
+" and expects a specification file on standard input if no filename is given.\n" +
+" Legal options include:\n" +
+" -package name specify package generated classes go in [default none]\n" +
+" -parser name specify parser class name [default \"parser\"]\n" +
+" -symbols name specify name for symbol constant class [default \"sym\"]\n"+
+" -interface put symbols in an interface, rather than a class\n" +
+" -nonterms put non terminals in symbol constant class\n" +
+" -expect # number of conflicts expected/allowed [default 0]\n" +
+" -compact_red compact tables by defaulting to most frequent reduce\n" +
+" -nowarn don't warn about useless productions, etc.\n" +
+" -nosummary don't print the usual summary of parse states, etc.\n" +
+" -nopositions don't propagate the left and right token position values\n" +
+" -noscanner don't refer to java_cup.runtime.Scanner\n" +
+" -progress print messages to indicate progress of the system\n" +
+" -time print time usage summary\n" +
+" -dump_grammar produce a human readable dump of the symbols and grammar\n"+
+" -dump_states produce a dump of parse state machine\n"+
+" -dump_tables produce a dump of the parse tables\n"+
+" -dump produce a dump of all of the above\n"+
+" -version print the version information for CUP and exit\n"
+ );
+ System.exit(1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse command line options and arguments to set various user-option
+ * flags and variables.
+ * @param argv the command line arguments to be parsed.
+ */
+ protected static void parse_args(String argv[])
+ {
+ int len = argv.length;
+ int i;
+
+ /* parse the options */
+ for (i=0; i<len; i++)
+ {
+ /* try to get the various options */
+ if (argv[i].equals("-package"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-package must have a name argument");
+
+ /* record the name */
+ emit.package_name = argv[i];
+ }
+ else if (argv[i].equals("-parser"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-parser must have a name argument");
+
+ /* record the name */
+ emit.parser_class_name = argv[i];
+ }
+ else if (argv[i].equals("-symbols"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-symbols must have a name argument");
+
+ /* record the name */
+ emit.symbol_const_class_name = argv[i];
+ }
+ else if (argv[i].equals("-nonterms"))
+ {
+ include_non_terms = true;
+ }
+ else if (argv[i].equals("-expect"))
+ {
+ /* must have an arg */
+ if (++i >= len || argv[i].startsWith("-") ||
+ argv[i].endsWith(".cup"))
+ usage("-expect must have a name argument");
+
+ /* record the number */
+ try {
+ expect_conflicts = Integer.parseInt(argv[i]);
+ } catch (NumberFormatException e) {
+ usage("-expect must be followed by a decimal integer");
+ }
+ }
+ else if (argv[i].equals("-compact_red")) opt_compact_red = true;
+ else if (argv[i].equals("-nosummary")) no_summary = true;
+ else if (argv[i].equals("-nowarn")) emit.nowarn = true;
+ else if (argv[i].equals("-dump_states")) opt_dump_states = true;
+ else if (argv[i].equals("-dump_tables")) opt_dump_tables = true;
+ else if (argv[i].equals("-progress")) print_progress = true;
+ else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
+ else if (argv[i].equals("-dump"))
+ opt_dump_states = opt_dump_tables = opt_dump_grammar = true;
+ else if (argv[i].equals("-time")) opt_show_timing = true;
+ else if (argv[i].equals("-debug")) opt_do_debug = true;
+ /* frankf 6/18/96 */
+ else if (argv[i].equals("-nopositions")) lr_values = false;
+ /* CSA 12/21/97 */
+ else if (argv[i].equals("-interface")) sym_interface = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-noscanner")) suppress_scanner = true;
+ /* CSA 23-Jul-1999 */
+ else if (argv[i].equals("-version")) {
+ System.out.println(version.title_str);
+ System.exit(1);
+ }
+ /* CSA 24-Jul-1999; suggestion by Jean Vaucher */
+ else if (!argv[i].startsWith("-") && i==len-1) {
+ /* use input from file. */
+ try {
+ System.setIn(new FileInputStream(argv[i]));
+ } catch (java.io.FileNotFoundException e) {
+ usage("Unable to open \"" + argv[i] +"\" for input");
+ }
+ }
+ else
+ {
+ usage("Unrecognized option \"" + argv[i] + "\"");
+ }
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-------*/
+ /* Files */
+ /*-------*/
+
+ /** Input file. This is a buffered version of System.in. */
+ protected static BufferedInputStream input_file;
+
+ /** Output file for the parser class. */
+ protected static PrintWriter parser_class_file;
+
+ /** Output file for the symbol constant class. */
+ protected static PrintWriter symbol_class_file;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Open various files used by the system. */
+ protected static void open_files()
+ {
+ File fil;
+ String out_name;
+
+ /* open each of the output files */
+
+ /* parser class */
+ out_name = emit.parser_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ parser_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(3);
+ }
+
+ /* symbol constants class */
+ out_name = emit.symbol_const_class_name + ".java";
+ fil = new File(out_name);
+ try {
+ symbol_class_file = new PrintWriter(
+ new BufferedOutputStream(new FileOutputStream(fil), 4096));
+ } catch(Exception e) {
+ System.err.println("Can't open \"" + out_name + "\" for output");
+ System.exit(4);
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Close various files used by the system. */
+ protected static void close_files() throws java.io.IOException
+ {
+ if (input_file != null) input_file.close();
+ if (parser_class_file != null) parser_class_file.close();
+ if (symbol_class_file != null) symbol_class_file.close();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Parse the grammar specification from standard input. This produces
+ * sets of terminal, non-terminals, and productions which can be accessed
+ * via static variables of the respective classes, as well as the setting
+ * of various variables (mostly in the emit class) for small user supplied
+ * items such as the code to scan with.
+ */
+ protected static void parse_grammar_spec() throws java.lang.Exception
+ {
+ parser parser_obj;
+
+ /* create a parser and parse with it */
+ 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 lst = (lalr_state)st.nextElement();
+ lst.build_table_entries(
+ action_table, reduce_table);
+ }
+
+ table_end = System.currentTimeMillis();
+
+ /* check and warn for non-reduced productions */
+ if (opt_do_debug || print_progress)
+ System.err.println(" Checking for non-reduced productions...");
+ action_table.check_reductions();
+
+ reduce_check_end = System.currentTimeMillis();
+
+ /* if we have more conflicts than we expected issue a message and die */
+ if (emit.num_conflicts > expect_conflicts)
+ {
+ System.err.println("*** More conflicts encountered than expected " +
+ "-- parser generation aborted");
+ lexer.error_count++; // indicate the problem.
+ // we'll die on return, after clean up.
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Call the emit routines necessary to write out the generated parser. */
+ protected static void emit_parser() throws internal_error
+ {
+ emit.symbols(symbol_class_file, include_non_terms, sym_interface);
+ emit.parser(parser_class_file, action_table, reduce_table,
+ start_state.index(), emit.start_production, opt_compact_red,
+ suppress_scanner);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Helper routine to optionally return a plural or non-plural ending.
+ * @param val the numerical value determining plurality.
+ */
+ protected static String plural(int val)
+ {
+ if (val == 1)
+ return "";
+ else
+ return "s";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a long summary message to standard error (System.err) which
+ * summarizes what was found in the specification, how many states were
+ * produced, how many conflicts were found, etc. A detailed timing
+ * summary is also produced if it was requested by the user.
+ * @param output_produced did the system get far enough to generate code.
+ */
+ protected static void emit_summary(boolean output_produced)
+ {
+ final_time = System.currentTimeMillis();
+
+ if (no_summary) return;
+
+ System.err.println("------- " + version.title_str +
+ " Parser Generation Summary -------");
+
+ /* error and warning count */
+ System.err.println(" " + 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
+ {
+ System.err.println("===== Terminals =====");
+ for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
+ {
+ System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+ System.err.println("===== Non terminals =====");
+ for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
+ {
+ System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
+ if ((cnt+1) % 5 == 0) System.err.println();
+ }
+ System.err.println();
+ System.err.println();
+
+
+ System.err.println("===== Productions =====");
+ for (int pidx=0; pidx < production.number(); pidx++)
+ {
+ production prod = production.find(pidx);
+ System.err.print("["+pidx+"] "+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);
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
--- /dev/null
+
+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() + "}";
+ }
+
+ /*-----------------------------------------------------------*/
+}
--- /dev/null
+
+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;}
+}
--- /dev/null
+package java_cup;
+
+/* Defines integers that represent the associativity of terminals
+ * @version last updated: 7/3/96
+ * @author Frank Flannery
+ */
+
+public class assoc {
+
+ /* various associativities, no_prec being the default value */
+ public final static int left = 0;
+ public final static int right = 1;
+ public final static int nonassoc = 2;
+ public final static int no_prec = -1;
+
+}
\ No newline at end of file
--- /dev/null
+package java_cup;
+
+import java.io.PrintWriter;
+import java.util.Stack;
+import java.util.Enumeration;
+import java.util.Date;
+
+/**
+ * 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 Symbol.
+ 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 ------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** 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 Symbol. */
+ 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;
+
+ /* frankf 6/18/96 */
+ protected static boolean _lr_values;
+
+ /** whether or not to emit code for left and right values */
+ public static boolean lr_values() {return _lr_values;}
+ protected static void set_lr_values(boolean b) { _lr_values = b;}
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Build a string with the standard prefix.
+ * @param str string to prefix.
+ */
+ protected static String pre(String str) {
+ return prefix + parser_class_name + "$" + str;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit a package spec if the user wants one.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_package(PrintWriter out)
+ {
+ /* generate a package spec if we have a name for one */
+ if (package_name != null) {
+ out.println("package " + package_name + ";"); out.println();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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?
+ * @param sym_interface should we emit an interface, rather than a class?
+ */
+ public static void symbols(PrintWriter out,
+ boolean emit_non_terms, boolean sym_interface)
+ {
+ terminal term;
+ non_terminal nt;
+ String class_or_interface = (sym_interface)?"interface":"class";
+
+ 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("/** CUP generated " + class_or_interface +
+ " containing symbol constants. */");
+ out.println("public " + class_or_interface + " " +
+ 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(" public 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();
+ out.println(" /* 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("}");
+ out.println();
+
+ 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(PrintWriter out, production start_prod)
+ throws internal_error
+ {
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* class header */
+ out.println();
+ out.println(
+ "/** Cup 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);
+ }
+
+ /* field for parser object */
+ out.println(" private final "+parser_class_name+" parser;");
+
+ /* constructor */
+ out.println();
+ out.println(" /** Constructor */");
+ out.println(" " + pre("actions") + "("+parser_class_name+" parser) {");
+ out.println(" this.parser = parser;");
+ out.println(" }");
+
+ /* 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 */
+ /* New declaration!! now return Symbol
+ 6/13/96 frankf */
+ out.println(" /* Symbol 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(" {");
+
+ /* create the result symbol */
+ /*make the variable RESULT which will point to the new Symbol (see below)
+ and be changed by action code
+ 6/13/96 frankf */
+ out.println(" " + prod.lhs().the_symbol().stack_type() +
+ " RESULT = null;");
+
+ /* Add code to propagate RESULT assignments that occur in
+ * action code embedded in a production (ie, non-rightmost
+ * action code). 24-Mar-1998 CSA
+ */
+ for (int i=0; i<prod.rhs_length(); i++) {
+ // only interested in non-terminal symbols.
+ if (!(prod.rhs(i) instanceof symbol_part)) continue;
+ symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
+ if (!(s instanceof non_terminal)) continue;
+ // skip this non-terminal unless it corresponds to
+ // an embedded action production.
+ if (((non_terminal)s).is_embedded_action == false) continue;
+ // OK, it fits. Make a conditional assignment to RESULT.
+ int index = prod.rhs_length() - i - 1; // last rhs is on top.
+ out.println(" " + "// propagate RESULT from " +
+ s.name());
+ out.println(" " + "if ( " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value != null )");
+ out.println(" " + "RESULT = " +
+ "(" + prod.lhs().the_symbol().stack_type() + ") " +
+ "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
+ + emit.pre("top") + "-" + index + ")).value;");
+ }
+
+ /* 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());
+
+ /* here we have the left and right values being propagated.
+ must make this a command line option.
+ frankf 6/18/96 */
+
+ /* Create the code that assigns the left and right values of
+ the new Symbol that the production is reducing to */
+ if (emit.lr_values()) {
+ int loffset;
+ String leftstring, rightstring;
+ int roffset = 0;
+ rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + roffset + ")).right";
+ if (prod.rhs_length() == 0)
+ leftstring = rightstring;
+ else {
+ loffset = prod.rhs_length() - 1;
+ leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" +
+ emit.pre("top") + "-" + loffset + ")).left";
+ }
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", " + leftstring + ", " + rightstring + ", RESULT);");
+ } else {
+ out.println(" " + pre("result") + " = new java_cup.runtime.Symbol(" +
+ prod.lhs().the_symbol().index() + "/*" +
+ prod.lhs().the_symbol().name() + "*/" +
+ ", RESULT);");
+ }
+
+ /* 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("}");
+ out.println();
+
+ action_code_time = System.currentTimeMillis() - start_time;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Emit the production table.
+ * @param out stream to produce output on.
+ */
+ protected static void emit_production_table(PrintWriter out)
+ {
+ production all_prods[];
+ production prod;
+
+ long start_time = System.currentTimeMillis();
+
+ /* 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;
+ }
+
+ // make short[][]
+ short[][] prod_table = new short[production.number()][2];
+ for (int i = 0; i<production.number(); i++)
+ {
+ prod = all_prods[i];
+ // { lhs symbol , rhs size }
+ prod_table[i][0] = (short) prod.lhs().the_symbol().index();
+ prod_table[i][1] = (short) prod.rhs_length();
+ }
+ /* do the top of the table */
+ out.println();
+ out.println(" /** Production table. */");
+ out.println(" protected static final short _production_table[][] = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, prod_table);
+ 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(
+ PrintWriter 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();
+
+ /* collect values for the action table */
+ short[][] action_table = new short[act_tab.num_states()][];
+ /* 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;
+
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*row.size()];
+ int nentries = 0;
+
+ /* 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)
+ {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short)
+ (((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) {
+ /* make entry */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) (-(red+1));
+ }
+ } else if (act.kind() == parse_action.NONASSOC)
+ {
+ /* do nothing, since we just want a syntax error */
+ }
+ /* shouldn't be anything else */
+ else
+ throw new internal_error("Unrecognized action code " +
+ act.kind() + " found in parse table");
+ }
+ }
+
+ /* now we know how big to make the row */
+ action_table[i] = new short[nentries + 2];
+ System.arraycopy(temp_table, 0, action_table[i], 0, nentries);
+
+ /* finish off the row with a default entry */
+ action_table[i][nentries++] = -1;
+ if (row.default_reduce != -1)
+ action_table[i][nentries++] = (short) (-(row.default_reduce+1));
+ else
+ action_table[i][nentries++] = 0;
+ }
+
+ /* finish off the init of the table */
+ out.println();
+ out.println(" /** Parse-action table. */");
+ out.println(" protected static final short[][] _action_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, action_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(
+ PrintWriter out,
+ parse_reduce_table red_tab)
+ {
+ lalr_state goto_st;
+ parse_action act;
+
+ long start_time = System.currentTimeMillis();
+
+ /* collect values for reduce-goto table */
+ short[][] reduce_goto_table = new short[red_tab.num_states()][];
+ /* do each row of the reduce-goto table */
+ for (int i=0; i<red_tab.num_states(); i++)
+ {
+ /* make temporary table for the row. */
+ short[] temp_table = new short[2*red_tab.under_state[i].size()];
+ int nentries = 0;
+ /* 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 */
+ temp_table[nentries++] = (short) j;
+ temp_table[nentries++] = (short) goto_st.index();
+ }
+ }
+ /* now we know how big to make the row. */
+ reduce_goto_table[i] = new short[nentries+2];
+ System.arraycopy(temp_table, 0, reduce_goto_table[i], 0, nentries);
+
+ /* end row with default value */
+ reduce_goto_table[i][nentries++] = -1;
+ reduce_goto_table[i][nentries++] = -1;
+ }
+
+ /* emit the table. */
+ out.println();
+ out.println(" /** <code>reduce_goto</code> table. */");
+ out.println(" protected static final short[][] _reduce_table = ");
+ out.print (" unpackFromStrings(");
+ do_table_as_string(out, reduce_goto_table);
+ out.println(");");
+
+ /* do the public accessor method */
+ out.println();
+ out.println(" /** Access to <code>reduce_goto</code> table. */");
+ out.println(" public short[][] reduce_table() {return _reduce_table;}");
+ out.println();
+
+ goto_table_time = System.currentTimeMillis() - start_time;
+ }
+
+ // print a string array encoding the given short[][] array.
+ protected static void do_table_as_string(PrintWriter out, short[][] sa) {
+ out.println("new String[] {");
+ out.print(" \"");
+ int nchar=0, nbytes=0;
+ nbytes+=do_escaped(out, (char)(sa.length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa.length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int i=0; i<sa.length; i++) {
+ nbytes+=do_escaped(out, (char)(sa[i].length>>16));
+ nchar =do_newline(out, nchar, nbytes);
+ nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF));
+ nchar =do_newline(out, nchar, nbytes);
+ for (int j=0; j<sa[i].length; j++) {
+ // contents of string are (value+2) to allow for common -1, 0 cases
+ // (UTF-8 encoding is most efficient for 0<c<0x80)
+ nbytes+=do_escaped(out, (char)(2+sa[i][j]));
+ nchar =do_newline(out, nchar, nbytes);
+ }
+ }
+ out.print("\" }");
+ }
+ // split string if it is very long; start new line occasionally for neatness
+ protected static int do_newline(PrintWriter out, int nchar, int nbytes) {
+ if (nbytes > 65500) { out.println("\", "); out.print(" \""); }
+ else if (nchar > 11) { out.println("\" +"); out.print(" \""); }
+ else return nchar+1;
+ return 0;
+ }
+ // output an escape sequence for the given character code.
+ protected static int do_escaped(PrintWriter out, char c) {
+ StringBuffer escape = new StringBuffer();
+ if (c <= 0xFF) {
+ escape.append(Integer.toOctalString(c));
+ while(escape.length() < 3) escape.insert(0, '0');
+ } else {
+ escape.append(Integer.toHexString(c));
+ while(escape.length() < 4) escape.insert(0, '0');
+ escape.insert(0, 'u');
+ }
+ escape.insert(0, '\\');
+ out.print(escape.toString());
+
+ // return number of bytes this takes up in UTF-8 encoding.
+ if (c == 0) return 2;
+ if (c >= 0x01 && c <= 0x7F) return 1;
+ if (c >= 0x80 && c <= 0x7FF) return 2;
+ return 3;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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?
+ * @param suppress_scanner should scanner be suppressed for compatibility?
+ */
+ public static void parser(
+ PrintWriter out,
+ parse_action_table action_table,
+ parse_reduce_table reduce_table,
+ int start_st,
+ production start_prod,
+ boolean compact_reduces,
+ boolean suppress_scanner)
+ 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("/** "+version.title_str+" generated parser.");
+ out.println(" * @version " + new Date());
+ out.println(" */");
+ out.println("public class " + parser_class_name +
+ " extends java_cup.runtime.lr_parser {");
+
+ /* constructors [CSA/davidm, 24-jul-99] */
+ out.println();
+ out.println(" /** Default constructor. */");
+ out.println(" public " + parser_class_name + "() {super();}");
+ if (!suppress_scanner) {
+ out.println();
+ out.println(" /** Constructor which sets the default scanner. */");
+ out.println(" public " + parser_class_name +
+ "(java_cup.runtime.Scanner s) {super(s);}");
+ }
+
+ /* 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") + "(this);");
+ 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(" /** Indicates start state. */");
+ out.println(" public int start_state() {return " + start_st + ";}");
+
+ /* method to indicate start production */
+ out.println(" /** Indicates start production. */");
+ out.println(" public int start_production() {return " +
+ start_production.index() + ";}");
+ out.println();
+
+ /* methods to indicate EOF and error symbol indexes */
+ out.println(" /** <code>EOF</code> Symbol index. */");
+ out.println(" public int EOF_sym() {return " + terminal.EOF.index() +
+ ";}");
+ out.println();
+ out.println(" /** <code>error</code> 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 code. */");
+ 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 Symbol. */");
+ out.println(" public java_cup.runtime.Symbol 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;
+ }
+
+ /*-----------------------------------------------------------*/
+}
--- /dev/null
+
+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);
+ }
+ }
--- /dev/null
+package java_cup;
+
+import java.util.Stack;
+import java.util.Enumeration;
+
+/** 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 += "(" + obj_hash() + ")";
+ 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+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
+ //
+ // if (needs_propagation) result += " NP";
+
+ return result;
+ }
+ /*-----------------------------------------------------------*/
+}
--- /dev/null
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** 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: 3/6/96
+ * @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 terminal_set(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 */
+ // CSA fix! we'd *like* to hash just a few elements, but
+ // that means equal sets will have inequal hashcodes, which
+ // we're not allowed (by contract) to do. So hash them all.
+ 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();
+ }
+ /*-----------------------------------------------------------*/
+}
+
--- /dev/null
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+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 Symbol 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: 7/3/96
+ * @author Frank Flannery
+ *
+ */
+
+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;
+ terminal_set conflict_set = new terminal_set();
+
+ /* 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 */
+ terminal term = terminal.find(t);
+ other_act = our_act_row.under_term[t];
+
+ /* if the other act was not a shift */
+ if ((other_act.kind() != parse_action.SHIFT) &&
+ (other_act.kind() != parse_action.NONASSOC))
+ {
+ /* 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;
+ }
+ } else {
+ /* Check precedences,see if problem is correctable */
+ if(fix_with_precedence(itm.the_production(),
+ t, our_act_row, act)) {
+ term = null;
+ }
+ }
+ if(term!=null) {
+
+ conflict_set.add(term);
+ }
+ }
+ }
+ }
+ }
+
+ /* 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 */
+ production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with();
+
+ /* shift always wins */
+ if (!fix_with_precedence(p, sym.index(), our_act_row, act)) {
+ our_act_row.under_term[sym.index()] = act;
+ conflict_set.add(terminal.find(sym.index()));
+ }
+ }
+ }
+ 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 (!conflict_set.empty())
+ report_conflicts(conflict_set);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /** Procedure that attempts to fix a shift/reduce error by using
+ * precedences. --frankf 6/26/96
+ *
+ * if a production (also called rule) or the lookahead terminal
+ * has a precedence, then the table can be fixed. if the rule
+ * has greater precedence than the terminal, a reduce by that rule
+ * in inserted in the table. If the terminal has a higher precedence,
+ * it is shifted. if they have equal precedence, then the associativity
+ * of the precedence is used to determine what to put in the table:
+ * if the precedence is left associative, the action is to reduce.
+ * if the precedence is right associative, the action is to shift.
+ * if the precedence is non associative, then it is a syntax error.
+ *
+ * @param p the production
+ * @param term_index the index of the lokahead terminal
+ * @param parse_action_row a row of the action table
+ * @param act the rule in conflict with the table entry
+ */
+
+ protected boolean fix_with_precedence(
+ production p,
+ int term_index,
+ parse_action_row table_row,
+ parse_action act)
+
+ throws internal_error {
+
+ terminal term = terminal.find(term_index);
+
+ /* if the production has a precedence number, it can be fixed */
+ if (p.precedence_num() > assoc.no_prec) {
+
+ /* if production precedes terminal, put reduce in table */
+ if (p.precedence_num() > term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if terminal precedes rule, put shift in table */
+ else if (p.precedence_num() < term.precedence_num()) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+ else { /* they are == precedence */
+
+ /* equal precedences have equal sides, so only need to
+ look at one: if it is right, put shift in table */
+ if (term.precedence_side() == assoc.right) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is left, put reduce in table */
+ else if (term.precedence_side() == assoc.left) {
+ table_row.under_term[term_index] =
+ insert_reduce(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* if it is nonassoc, we're not allowed to have two nonassocs
+ of equal precedence in a row, so put in NONASSOC */
+ else if (term.precedence_side() == assoc.nonassoc) {
+ table_row.under_term[term_index] = new nonassoc_action();
+ return true;
+ } else {
+ /* something really went wrong */
+ throw new internal_error("Unable to resolve conflict correctly");
+ }
+ }
+ }
+ /* check if terminal has precedence, if so, shift, since
+ rule does not have precedence */
+ else if (term.precedence_num() > assoc.no_prec) {
+ table_row.under_term[term_index] =
+ insert_shift(table_row.under_term[term_index],act);
+ return true;
+ }
+
+ /* otherwise, neither the rule nor the terminal has a precedence,
+ so it can't be fixed. */
+ return false;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+
+ /* given two actions, and an action type, return the
+ action of that action type. give an error if they are of
+ the same action, because that should never have tried
+ to be fixed
+
+ */
+ protected parse_action insert_action(
+ parse_action a1,
+ parse_action a2,
+ int act_type)
+ throws internal_error
+ {
+ if ((a1.kind() == act_type) && (a2.kind() == act_type)) {
+ throw new internal_error("Conflict resolution of bogus actions");
+ } else if (a1.kind() == act_type) {
+ return a1;
+ } else if (a2.kind() == act_type) {
+ return a2;
+ } else {
+ throw new internal_error("Conflict resolution of bogus actions");
+ }
+ }
+
+ /* find the shift in the two actions */
+ protected parse_action insert_shift(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.SHIFT);
+ }
+
+ /* find the reduce in the two actions */
+ protected parse_action insert_reduce(
+ parse_action a1,
+ parse_action a2)
+ throws internal_error
+ {
+ return insert_action(a1, a2, parse_action.REDUCE);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce warning messages for all conflicts found in this state. */
+ protected void report_conflicts(terminal_set conflict_set)
+ throws internal_error
+ {
+ lalr_item itm, compare;
+ symbol shift_sym;
+
+ 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 */
+
+ /* 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);
+ }
+ }
+ }
+ /* 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;
+ }
+
+ /*-----------------------------------------------------------*/
+}
--- /dev/null
+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;
+ }
+
+ /*-----------------------------------------------------------*/
+}
--- /dev/null
+package java_cup;
+
+import java_cup.runtime.Symbol;
+import java.util.Hashtable;
+
+/** 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 Symbol. Once end of input is reached the EOF Symbol is
+ * returned on every subsequent call.<p>
+ * Symbols 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 "precedence" PRECEDENCE
+ * "left" LEFT "right" RIGHT
+ * "nonassoc" NONASSOC "%prec PRECENT_PREC
+ * [ LBRACK ] RBRACK
+ * ; SEMI
+ * , COMMA * STAR
+ * . DOT : COLON
+ * ::= COLON_COLON_EQUALS | BAR
+ * identifier ID {:...:} CODE_STRING
+ * "nonterminal" NONTERMINAL
+ * </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 Symbol) 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: 7/3/96
+ * @author Frank Flannery
+ */
+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;
+
+ /** Second character of lookahead. */
+ protected static int next_char3;
+
+ /** Second character of lookahead. */
+ protected static int next_char4;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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 Symbols 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;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Character position in current line. */
+ protected static int absolute_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("nonterminal",new Integer(sym.NONTERMINAL));// [CSA]
+ 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("precedence", new Integer(sym.PRECEDENCE));
+ keywords.put("left", new Integer(sym.LEFT));
+ keywords.put("right", new Integer(sym.RIGHT));
+ keywords.put("nonassoc", new Integer(sym.NONASSOC));
+
+ /* 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));
+ char_symbols.put(new Integer('['), new Integer(sym.LBRACK));
+ char_symbols.put(new Integer(']'), new Integer(sym.RBRACK));
+
+ /* read two characters of lookahead */
+ next_char = System.in.read();
+ if (next_char == EOF_CHAR) {
+ next_char2 = EOF_CHAR;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = System.in.read();
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = System.in.read();
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = 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;
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char2 = next_char3;
+ if (next_char2 == EOF_CHAR) {
+ next_char3 = EOF_CHAR;
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char3 = next_char4;
+ if (next_char3 == EOF_CHAR) {
+ next_char4 = EOF_CHAR;
+ } else {
+ next_char4 = System.in.read();
+ }
+ }
+ }
+
+ /* count this */
+ absolute_position++;
+ current_position++;
+ if (old_char == '\n' || (old_char == '\r' && next_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)
+ {
+ /* allow for % in identifiers. a hack to allow my
+ %prec in. Should eventually make lex spec for this
+ frankf */
+ 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', '\r', '\f', or EOF */
+ while (next_char != '\n' && next_char != '\r' &&
+ 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 a String
+ object suitable for return by the scanner.
+ */
+ protected static Symbol 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 Symbol */
+ advance(); advance();
+ return new Symbol(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 a String suitable
+ * for return by the scanner.
+ */
+ protected static Symbol 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 Symbol(keyword_num.intValue());
+
+ /* otherwise build and return an id Symbol with an attached string */
+ return new Symbol(sym.ID, result_str);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return one Symbol. This is the main external interface to the scanner.
+ * It consumes sufficient characters to determine the next input Symbol
+ * 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 Symbol.
+ */
+ public static Symbol 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 Symbol is,
+ * then returns it.
+ */
+ public static Symbol debug_next_token() throws java.io.IOException
+ {
+ Symbol result = real_next_token();
+ System.out.println("# next_Symbol() => " + result.sym);
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The actual routine to return one Symbol. This is normally called from
+ * next_token(), but for debugging purposes can be called indirectly from
+ * debug_next_token().
+ */
+ protected static Symbol 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 Symbol for it */
+ advance();
+ return new Symbol(sym_num);
+ }
+
+ /* look for : or ::= */
+ if (next_char == ':')
+ {
+ /* if we don't have a second ':' return COLON */
+ if (next_char2 != ':')
+ {
+ advance();
+ return new Symbol(sym.COLON);
+ }
+
+ /* move forward and look for the '=' */
+ advance();
+ if (next_char2 == '=')
+ {
+ advance(); advance();
+ return new Symbol(sym.COLON_COLON_EQUALS);
+ }
+ else
+ {
+ /* return just the colon (already consumed) */
+ return new Symbol(sym.COLON);
+ }
+ }
+
+ /* find a "%prec" string and return it. otherwise, a '%' was found,
+ which has no right being in the specification otherwise */
+ if (next_char == '%') {
+ advance();
+ if ((next_char == 'p') && (next_char2 == 'r') && (next_char3 == 'e') &&
+ (next_char4 == 'c')) {
+ advance();
+ advance();
+ advance();
+ advance();
+ return new Symbol(sym.PERCENT_PREC);
+ } else {
+ emit_error("Found extraneous percent sign");
+ }
+ }
+
+ /* 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 Symbol(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();
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+}
+
--- /dev/null
+
+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;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the hash code that object would have provided for us so we have
+ * a (nearly) unique id for debugging.
+ */
+ protected int obj_hash()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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;
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
--- /dev/null
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** 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++;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Table of all non terminals indexed by their index number. */
+ protected static Hashtable _all_by_index = new Hashtable();
+
+ /** Lookup a non terminal by index. */
+ public static non_terminal find(int indx)
+ {
+ Integer the_indx = new Integer(indx);
+
+ return (non_terminal)_all_by_index.get(the_indx);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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");
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** flag non-terminals created to embed action productions */
+ public boolean is_embedded_action = false; /* added 24-Mar-1998, CSA */
+
+ /*-----------------------------------------------------------*/
+ /*--- 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() ? "*" : "");
+ }
+
+ /*-----------------------------------------------------------*/
+}
--- /dev/null
+
+package java_cup;
+
+/** This class represents a shift/reduce nonassociative error within the
+ * parse table. If action_table element is assign to type
+ * nonassoc_action, it cannot be changed, and signifies that there
+ * is a conflict between shifting and reducing a production and a
+ * terminal that shouldn't be next to each other.
+ *
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+public class nonassoc_action extends parse_action {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Simple constructor.
+ */
+ public nonassoc_action() throws internal_error
+ {
+ /* don't need to set anything, since it signifies error */
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- General Methods ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Quick access to type of action. */
+ public int kind() {return NONASSOC;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality test. */
+ public boolean equals(parse_action other)
+ {
+ return other != null && other.kind() == NONASSOC;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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 0xCafe321;
+ }
+
+
+
+ /** Convert to string. */
+ public String toString()
+ {
+ return "NONASSOC";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+
+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), NONASSOC,
+ * or ERROR. Objects of this base class will default to ERROR, while
+ * the other three types will be represented by subclasses.
+ *
+ * @see java_cup.reduce_action
+ * @see java_cup.shift_action
+ * @version last updated: 7/2/96
+ * @author Frank Flannery
+ */
+
+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;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constants for action type -- reduce action. */
+ public static final int NONASSOC = 3;
+
+ /*-----------------------------------------------------------*/
+ /*--- 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";}
+
+ /*-----------------------------------------------------------*/
+}
+
--- /dev/null
+
+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;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
--- /dev/null
+
+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 += " [term " + col + ":" + under_state[row].under_term[col] + "]";
+
+ /* end the line after the 2nd one */
+ cnt++;
+ if (cnt == 2)
+ {
+ result += "\n";
+ cnt = 0;
+ }
+ }
+ }
+ /* finish the line if we haven't just done that */
+ if (cnt != 0) result += "\n";
+ }
+ result += "------------------------------";
+
+ return result;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
--- /dev/null
+
+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[];
+}
+
--- /dev/null
+
+package java_cup;
+
+import java.util.Enumeration;
+
+/** 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 += " [non term " + col + "->";
+ result += "state " + 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;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
--- /dev/null
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+ and Frank Flannery, Department of Computer Science, Princeton Univ,
+ July 1996
+ Bug Fixes: C. Scott Ananian, Dept of Electrical Engineering, Princeton
+ University, October 1996. [later Massachusetts Institute of Technology]
+
+
+ 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.
+ Frank Flannery, Department of Computer Science, Princeton Univ.
+ C. Scott Ananian, Department of Electrical Engineering, Princeton Univ.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+ v0.10a Made many improvements/changes. now offers:
+ return value
+ left/right positions and propagations
+ cleaner label references
+ precedence and associativity for terminals
+ contextual precedence for productions
+ [FF] 7/3/96
+ v0.10b Fixed %prec directive so it works like it's supposed to.
+ [CSA] 10/10/96
+ v0.10g Added support for array types on symbols.
+ [CSA] 03/23/98
+ v0.10i Broaden set of IDs allowed in multipart_id and label_id so
+ that only java reserved words (and not CUP reserved words like
+ 'parser' and 'start') are prohibited. Allow reordering of
+ action code, parser code, init code, and scan with sections,
+ and made closing semicolon optional for these sections.
+ Added 'nonterminal' as a terminal symbol, finally fixing a
+ spelling mistake that's been around since the beginning.
+ For backwards compatibility, you can still misspell the
+ word if you like.
+*/
+/*================================================================*/
+
+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;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+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
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR, PRECEDENCE,
+ LEFT, RIGHT, NONASSOC, PERCENT_PREC, LBRACK, RBRACK, NONTERMINAL;
+
+terminal String ID, CODE_STRING;
+
+non terminal
+ spec, package_spec, import_list, action_code_part,
+ code_parts, code_part, opt_semi, non_terminal,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ 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,
+ precedence_list, preced, terminal_list, precedence_l, declares_term,
+ declares_non_term;
+
+non terminal String nt_id, symbol_id, label_id, opt_label, terminal_id,
+ term_id, robust_id;
+
+/*----------------------------------------------------------------*/
+
+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_parts
+ symbol_list
+ precedence_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
+ precedence_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
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+// allow any order; all parts are optional. [CSA, 23-Jul-1999]
+// (we check in the part action to make sure we don't have 2 of any part)
+code_part ::=
+ action_code_part | parser_code_part | init_code | scan_code ;
+code_parts ::=
+ | code_parts code_part;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ declares_term
+ |
+ TERMINAL
+ declares_term
+ |
+ non_terminal
+ type_id
+ declares_non_term
+ |
+ non_terminal
+ declares_non_term
+ |
+ /* 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
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_term ::=
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_non_term ::=
+ non_term_name_list
+ {:
+ /* 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
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+precedence_list ::= precedence_l | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+precedence_l ::= precedence_l preced | preced;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+preced ::=
+ PRECEDENCE LEFT
+ {:
+ update_precedence(assoc.left);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE RIGHT
+ {:
+ update_precedence(assoc.right);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE NONASSOC
+ {:
+ update_precedence(assoc.nonassoc);
+ :}
+ terminal_list SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_list ::= terminal_list COMMA terminal_id
+ |
+ terminal_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_id ::= term_id:sym
+ {:
+ add_precedence(sym);
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_id ::= symbol_id:sym
+ {:
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+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);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ 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);
+
+ /* 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 +
+ "\" 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 PERCENT_PREC term_id:term_name
+ {:
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ 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(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ 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
+ {:
+ 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(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ 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);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT = labid; :}
+ |
+ empty
+ {: RESULT = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT robust_id:another_id
+ {: append_multipart(another_id); :}
+ |
+ robust_id:an_id
+ {: append_multipart(an_id); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id
+ | type_id LBRACK RBRACK
+ {: multipart_name = multipart_name.concat("[]"); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, 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) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ robust_id:the_id
+ {: RESULT = the_id; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+robust_id ::= /* all ids that aren't reserved words in Java */
+ ID:the_id {: RESULT = the_id; :}
+ /* package is reserved. */
+ /* import is reserved. */
+ | CODE {: RESULT = "code"; :}
+ | ACTION {: RESULT = "action"; :}
+ | PARSER {: RESULT = "parser"; :}
+ | TERMINAL {: RESULT = "terminal"; :}
+ | NON {: RESULT = "non"; :}
+ | NONTERMINAL {: RESULT = "nonterminal"; :}
+ | INIT {: RESULT = "init"; :}
+ | SCAN {: RESULT = "scan"; :}
+ | WITH {: RESULT = "with"; :}
+ | START {: RESULT = "start"; :}
+ | PRECEDENCE {: RESULT = "precedence"; :}
+ | LEFT {: RESULT = "left"; :}
+ | RIGHT {: RESULT = "right"; :}
+ | NONASSOC {: RESULT = "nonassoc"; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_terminal ::= NON TERMINAL | NONTERMINAL;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_semi ::= /* nothing */
+ | SEMI;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
--- /dev/null
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/** CUP v0.10k generated parser.
+ * @version Sun Jul 25 13:35:26 EDT 1999
+ */
+public class parser extends java_cup.runtime.lr_parser {
+
+ /** Default constructor. */
+ public parser() {super();}
+
+ /** Constructor which sets the default scanner. */
+ public parser(java_cup.runtime.Scanner s) {super(s);}
+
+ /** Production table. */
+ protected static final short _production_table[][] =
+ unpackFromStrings(new String[] {
+ "\000\153\000\002\002\004\000\002\055\002\000\002\003" +
+ "\012\000\002\003\007\000\002\056\002\000\002\004\006" +
+ "\000\002\004\003\000\002\005\004\000\002\005\003\000" +
+ "\002\057\002\000\002\020\006\000\002\010\003\000\002" +
+ "\010\003\000\002\010\003\000\002\010\003\000\002\007" +
+ "\002\000\002\007\004\000\002\006\006\000\002\013\006" +
+ "\000\002\022\006\000\002\023\006\000\002\014\004\000" +
+ "\002\014\003\000\002\024\005\000\002\024\004\000\002" +
+ "\024\005\000\002\024\004\000\002\060\002\000\002\024" +
+ "\006\000\002\061\002\000\002\024\006\000\002\062\002" +
+ "\000\002\044\005\000\002\063\002\000\002\045\005\000" +
+ "\002\026\005\000\002\026\003\000\002\027\005\000\002" +
+ "\027\003\000\002\040\003\000\002\040\003\000\002\043" +
+ "\004\000\002\043\003\000\002\064\002\000\002\041\007" +
+ "\000\002\065\002\000\002\041\007\000\002\066\002\000" +
+ "\002\041\007\000\002\042\005\000\002\042\003\000\002" +
+ "\052\003\000\002\053\003\000\002\067\002\000\002\015" +
+ "\007\000\002\015\003\000\002\016\004\000\002\016\003" +
+ "\000\002\070\002\000\002\071\002\000\002\030\010\000" +
+ "\002\072\002\000\002\030\005\000\002\035\005\000\002" +
+ "\035\003\000\002\036\005\000\002\036\003\000\002\031" +
+ "\004\000\002\031\003\000\002\032\004\000\002\032\003" +
+ "\000\002\051\004\000\002\051\003\000\002\017\005\000" +
+ "\002\017\003\000\002\021\005\000\002\021\003\000\002" +
+ "\025\003\000\002\025\005\000\002\033\003\000\002\034" +
+ "\003\000\002\046\003\000\002\046\003\000\002\047\003" +
+ "\000\002\047\003\000\002\050\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\054\003\000\002" +
+ "\054\003\000\002\054\003\000\002\054\003\000\002\054" +
+ "\003\000\002\054\003\000\002\054\003\000\002\054\003" +
+ "\000\002\054\003\000\002\054\003\000\002\054\003\000" +
+ "\002\054\003\000\002\054\003\000\002\012\004\000\002" +
+ "\012\003\000\002\011\002\000\002\011\003\000\002\037" +
+ "\002" });
+
+ /** Access to production table. */
+ public short[][] production_table() {return _production_table;}
+
+ /** Parse-action table. */
+ protected static final short[][] _action_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\026\003\006\004\000\005\000\007\000\010" +
+ "\000\011\000\012\000\013\000\014\000\035\000\001\002" +
+ "\000\004\002\251\001\002\000\024\004\200\005\uff97\007" +
+ "\uff97\010\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97" +
+ "\001\002\000\010\011\007\012\012\035\014\001\002\000" +
+ "\042\003\163\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\160\001\002\000\020\003\uffeb" +
+ "\011\uffeb\012\uffeb\016\uffeb\026\uffeb\035\uffeb\036\uffeb\001" +
+ "\002\000\020\003\uff97\011\007\012\012\016\uff97\026\065" +
+ "\035\014\036\uff97\001\002\000\004\011\061\001\002\000" +
+ "\042\003\034\006\026\007\027\010\040\011\036\012\022" +
+ "\013\042\014\030\015\017\016\015\026\033\027\023\030" +
+ "\035\031\041\035\025\036\016\001\002\000\042\003\uff9a" +
+ "\006\uff9a\007\uff9a\010\uff9a\011\uff9a\012\uff9a\013\uff9a\014" +
+ "\uff9a\015\uff9a\016\uff9a\026\uff9a\027\uff9a\030\uff9a\031\uff9a" +
+ "\035\uff9a\036\uff9a\001\002\000\022\003\uffa1\017\uffa1\022" +
+ "\uffa1\025\uffa1\032\uffa1\033\uffa1\036\uffa1\037\uffa1\001\002" +
+ "\000\014\017\uffb1\020\uffb1\022\uffab\033\uffab\036\uffab\001" +
+ "\002\000\022\003\uffa2\017\uffa2\022\uffa2\025\uffa2\032\uffa2" +
+ "\033\uffa2\036\uffa2\037\uffa2\001\002\000\006\017\uffe0\020" +
+ "\055\001\002\000\010\022\051\033\uffb4\036\uffb4\001\002" +
+ "\000\022\003\uffa6\017\uffa6\022\uffa6\025\uffa6\032\uffa6\033" +
+ "\uffa6\036\uffa6\037\uffa6\001\002\000\022\003\uff9f\017\uff9f" +
+ "\022\uff9f\025\uff9f\032\uff9f\033\uff9f\036\uff9f\037\uff9f\001" +
+ "\002\000\006\033\047\036\045\001\002\000\022\003\uffa5" +
+ "\017\uffa5\022\uffa5\025\uffa5\032\uffa5\033\uffa5\036\uffa5\037" +
+ "\uffa5\001\002\000\022\003\uffaa\017\uffaa\022\uffaa\025\uffaa" +
+ "\032\uffaa\033\uffaa\036\uffaa\037\uffaa\001\002\000\022\003" +
+ "\uffa9\017\uffa9\022\uffa9\025\uffa9\032\uffa9\033\uffa9\036\uffa9" +
+ "\037\uffa9\001\002\000\022\003\uffa3\017\uffa3\022\uffa3\025" +
+ "\uffa3\032\uffa3\033\uffa3\036\uffa3\037\uffa3\001\002\000\012" +
+ "\017\uffb7\022\uffb7\033\uffb7\036\uffb7\001\002\000\020\003" +
+ "\uffe7\011\uffe7\012\uffe7\016\uffe7\026\uffe7\035\uffe7\036\uffe7" +
+ "\001\002\000\022\003\uffa0\017\uffa0\022\uffa0\025\uffa0\032" +
+ "\uffa0\033\uffa0\036\uffa0\037\uffa0\001\002\000\012\017\uffe4" +
+ "\022\uff9c\033\uff9c\036\uff9c\001\002\000\022\003\uff9e\017" +
+ "\uff9e\022\uff9e\025\uff9e\032\uff9e\033\uff9e\036\uff9e\037\uff9e" +
+ "\001\002\000\022\003\uffa7\017\uffa7\022\uffa7\025\uffa7\032" +
+ "\uffa7\033\uffa7\036\uffa7\037\uffa7\001\002\000\006\017\uffdb" +
+ "\020\uffdb\001\002\000\022\003\uffa8\017\uffa8\022\uffa8\025" +
+ "\uffa8\032\uffa8\033\uffa8\036\uffa8\037\uffa8\001\002\000\022" +
+ "\003\uff9d\017\uff9d\022\uff9d\025\uff9d\032\uff9d\033\uff9d\036" +
+ "\uff9d\037\uff9d\001\002\000\022\003\uffa4\017\uffa4\022\uffa4" +
+ "\025\uffa4\032\uffa4\033\uffa4\036\uffa4\037\uffa4\001\002\000" +
+ "\004\017\044\001\002\000\020\003\uffe3\011\uffe3\012\uffe3" +
+ "\016\uffe3\026\uffe3\035\uffe3\036\uffe3\001\002\000\006\017" +
+ "\uffb1\020\uffb1\001\002\000\020\003\uffe8\011\uffe8\012\uffe8" +
+ "\016\uffe8\026\uffe8\035\uffe8\036\uffe8\001\002\000\004\034" +
+ "\050\001\002\000\006\033\uffb3\036\uffb3\001\002\000\042" +
+ "\003\054\006\026\007\027\010\040\011\036\012\022\013" +
+ "\042\014\030\015\017\016\015\026\033\027\023\030\035" +
+ "\031\041\035\025\036\053\001\002\000\012\017\uffb8\022" +
+ "\uffb8\033\uffb8\036\uffb8\001\002\000\022\003\uffab\017\uffab" +
+ "\022\uffab\025\uffab\032\uffab\033\uffab\036\uffab\037\uffab\001" +
+ "\002\000\022\003\uff9c\017\uff9c\022\uff9c\025\uff9c\032\uff9c" +
+ "\033\uff9c\036\uff9c\037\uff9c\001\002\000\004\036\045\001" +
+ "\002\000\004\017\057\001\002\000\020\003\uffdf\011\uffdf" +
+ "\012\uffdf\016\uffdf\026\uffdf\035\uffdf\036\uffdf\001\002\000" +
+ "\006\017\uffdc\020\uffdc\001\002\000\042\003\uff9b\006\uff9b" +
+ "\007\uff9b\010\uff9b\011\uff9b\012\uff9b\013\uff9b\014\uff9b\015" +
+ "\uff9b\016\uff9b\026\uff9b\027\uff9b\030\uff9b\031\uff9b\035\uff9b" +
+ "\036\uff9b\001\002\000\010\003\uff97\016\116\036\uff97\001" +
+ "\002\000\012\003\uffda\016\uffda\026\065\036\uffda\001\002" +
+ "\000\010\003\uffd9\016\uffd9\036\uffd9\001\002\000\010\027" +
+ "\071\030\072\031\070\001\002\000\020\003\uffec\011\uffec" +
+ "\012\uffec\016\uffec\026\uffec\035\uffec\036\uffec\001\002\000" +
+ "\012\003\uffd7\016\uffd7\026\uffd7\036\uffd7\001\002\000\006" +
+ "\003\uffd2\036\uffd2\001\002\000\006\003\uffd6\036\uffd6\001" +
+ "\002\000\006\003\uffd4\036\uffd4\001\002\000\006\003\077" +
+ "\036\074\001\002\000\022\003\uffae\017\uffae\020\uffae\023" +
+ "\uffae\025\uffae\032\uffae\036\uffae\037\uffae\001\002\000\010" +
+ "\017\uffcd\020\uffcd\025\uffcd\001\002\000\006\017\uffce\020" +
+ "\uffce\001\002\000\022\003\uffad\017\uffad\020\uffad\023\uffad" +
+ "\025\uffad\032\uffad\036\uffad\037\uffad\001\002\000\006\017" +
+ "\102\020\103\001\002\000\006\017\uffcf\020\uffcf\001\002" +
+ "\000\012\003\uffd3\016\uffd3\026\uffd3\036\uffd3\001\002\000" +
+ "\006\003\077\036\074\001\002\000\006\017\uffd0\020\uffd0" +
+ "\001\002\000\006\003\077\036\074\001\002\000\006\017" +
+ "\107\020\103\001\002\000\012\003\uffd5\016\uffd5\026\uffd5" +
+ "\036\uffd5\001\002\000\006\003\077\036\074\001\002\000" +
+ "\006\017\112\020\103\001\002\000\012\003\uffd1\016\uffd1" +
+ "\026\uffd1\036\uffd1\001\002\000\012\003\uffd8\016\uffd8\026" +
+ "\uffd8\036\uffd8\001\002\000\006\003\uffca\036\uffca\001\002" +
+ "\000\006\003\126\036\120\001\002\000\004\015\117\001" +
+ "\002\000\006\003\122\036\120\001\002\000\006\017\uffb0" +
+ "\024\uffb0\001\002\000\004\017\uffcc\001\002\000\004\017" +
+ "\uffaf\001\002\000\004\017\124\001\002\000\006\003\uffcb" +
+ "\036\uffcb\001\002\000\004\024\uffc7\001\002\000\006\017" +
+ "\uffc4\024\uffaf\001\002\000\010\002\ufffe\003\126\036\120" +
+ "\001\002\000\010\002\uffc8\003\uffc8\036\uffc8\001\002\000" +
+ "\010\002\uffc9\003\uffc9\036\uffc9\001\002\000\004\017\133" +
+ "\001\002\000\010\002\uffc3\003\uffc3\036\uffc3\001\002\000" +
+ "\004\024\135\001\002\000\016\003\uffc6\017\uffc6\025\uffc6" +
+ "\032\uffc6\036\uffc6\037\uffc6\001\002\000\016\003\uff97\017" +
+ "\uff97\025\uff97\032\uff97\036\uff97\037\uff97\001\002\000\016" +
+ "\003\uffbd\017\uffbd\025\uffbd\032\uffbd\036\uffbd\037\uffbd\001" +
+ "\002\000\016\003\077\017\uffbf\025\uffbf\032\147\036\074" +
+ "\037\146\001\002\000\006\017\uffc1\025\uffc1\001\002\000" +
+ "\006\017\143\025\144\001\002\000\010\002\uffc5\003\uffc5" +
+ "\036\uffc5\001\002\000\016\003\uff97\017\uff97\025\uff97\032" +
+ "\uff97\036\uff97\037\uff97\001\002\000\006\017\uffc2\025\uffc2" +
+ "\001\002\000\016\003\uffbb\017\uffbb\025\uffbb\032\uffbb\036" +
+ "\uffbb\037\uffbb\001\002\000\006\003\077\036\074\001\002" +
+ "\000\020\003\uff97\017\uff97\023\154\025\uff97\032\uff97\036" +
+ "\uff97\037\uff97\001\002\000\016\003\uffbe\017\uffbe\025\uffbe" +
+ "\032\uffbe\036\uffbe\037\uffbe\001\002\000\016\003\uffb9\017" +
+ "\uffb9\025\uffb9\032\uffb9\036\uffb9\037\uffb9\001\002\000\016" +
+ "\003\uffbc\017\uffbc\025\uffbc\032\uffbc\036\uffbc\037\uffbc\001" +
+ "\002\000\042\003\054\006\026\007\027\010\040\011\036" +
+ "\012\022\013\042\014\030\015\017\016\015\026\033\027" +
+ "\023\030\035\031\041\035\025\036\053\001\002\000\016" +
+ "\003\uffba\017\uffba\025\uffba\032\uffba\036\uffba\037\uffba\001" +
+ "\002\000\016\003\uffac\017\uffac\025\uffac\032\uffac\036\uffac" +
+ "\037\uffac\001\002\000\006\017\uffc0\025\uffc0\001\002\000" +
+ "\014\017\uffb2\020\uffb2\022\uffab\033\uffab\036\uffab\001\002" +
+ "\000\006\033\047\036\170\001\002\000\006\017\uffdd\020" +
+ "\uffdd\001\002\000\012\017\uffe6\022\uff9c\033\uff9c\036\uff9c" +
+ "\001\002\000\020\003\uffe9\011\uffe9\012\uffe9\016\uffe9\026" +
+ "\uffe9\035\uffe9\036\uffe9\001\002\000\006\017\uffe2\020\167" +
+ "\001\002\000\004\017\172\001\002\000\004\036\170\001" +
+ "\002\000\006\017\uffb2\020\uffb2\001\002\000\006\017\uffde" +
+ "\020\uffde\001\002\000\020\003\uffe1\011\uffe1\012\uffe1\016" +
+ "\uffe1\026\uffe1\035\uffe1\036\uffe1\001\002\000\004\017\174" +
+ "\001\002\000\020\003\uffe5\011\uffe5\012\uffe5\016\uffe5\026" +
+ "\uffe5\035\uffe5\036\uffe5\001\002\000\020\003\uffea\011\uffea" +
+ "\012\uffea\016\uffea\026\uffea\035\uffea\036\uffea\001\002\000" +
+ "\022\005\ufffb\007\ufffb\010\ufffb\011\ufffb\012\ufffb\013\ufffb" +
+ "\014\ufffb\035\ufffb\001\002\000\022\005\uff97\007\uff97\010" +
+ "\uff97\011\uff97\012\uff97\013\uff97\014\uff97\035\uff97\001\002" +
+ "\000\042\003\054\006\026\007\027\010\040\011\036\012" +
+ "\022\013\042\014\030\015\017\016\015\026\033\027\023" +
+ "\030\035\031\041\035\025\036\053\001\002\000\006\017" +
+ "\ufffd\022\051\001\002\000\004\017\203\001\002\000\022" +
+ "\005\ufffc\007\ufffc\010\ufffc\011\ufffc\012\ufffc\013\ufffc\014" +
+ "\ufffc\035\ufffc\001\002\000\022\005\210\007\ufff2\010\ufff2" +
+ "\011\ufff2\012\ufff2\013\ufff2\014\ufff2\035\ufff2\001\002\000" +
+ "\022\005\ufff9\007\ufff9\010\ufff9\011\ufff9\012\ufff9\013\ufff9" +
+ "\014\ufff9\035\ufff9\001\002\000\020\007\223\010\224\011" +
+ "\007\012\012\013\227\014\225\035\014\001\002\000\022" +
+ "\005\ufffa\007\ufffa\010\ufffa\011\ufffa\012\ufffa\013\ufffa\014" +
+ "\ufffa\035\ufffa\001\002\000\042\003\054\006\026\007\027" +
+ "\010\040\011\036\012\022\013\042\014\030\015\017\016" +
+ "\015\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\006\017\uffb5\022\215\001\002\000\004\017" +
+ "\ufff8\001\002\000\004\017\214\001\002\000\022\005\ufff7" +
+ "\007\ufff7\010\ufff7\011\ufff7\012\ufff7\013\ufff7\014\ufff7\035" +
+ "\ufff7\001\002\000\044\003\054\006\026\007\027\010\040" +
+ "\011\036\012\022\013\042\014\030\015\017\016\015\021" +
+ "\216\026\033\027\023\030\035\031\041\035\025\036\053" +
+ "\001\002\000\004\017\uffb6\001\002\000\020\007\ufff3\010" +
+ "\ufff3\011\ufff3\012\ufff3\013\ufff3\014\ufff3\035\ufff3\001\002" +
+ "\000\020\007\ufff5\010\ufff5\011\ufff5\012\ufff5\013\ufff5\014" +
+ "\ufff5\035\ufff5\001\002\000\020\007\ufff1\010\ufff1\011\ufff1" +
+ "\012\ufff1\013\ufff1\014\ufff1\035\ufff1\001\002\000\020\007" +
+ "\ufff4\010\ufff4\011\ufff4\012\ufff4\013\ufff4\014\ufff4\035\ufff4" +
+ "\001\002\000\004\006\246\001\002\000\004\006\243\001" +
+ "\002\000\004\015\240\001\002\000\020\007\ufff6\010\ufff6" +
+ "\011\ufff6\012\ufff6\013\ufff6\014\ufff6\035\ufff6\001\002\000" +
+ "\004\015\234\001\002\000\020\003\uff97\011\007\012\012" +
+ "\016\uff97\026\065\035\014\036\uff97\001\002\000\010\003" +
+ "\uff97\016\116\036\uff97\001\002\000\006\003\126\036\120" +
+ "\001\002\000\010\002\uffff\003\126\036\120\001\002\000" +
+ "\004\037\235\001\002\000\022\007\uff99\010\uff99\011\uff99" +
+ "\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001\002\000" +
+ "\020\007\uff98\010\uff98\011\uff98\012\uff98\013\uff98\014\uff98" +
+ "\035\uff98\001\002\000\020\007\uffee\010\uffee\011\uffee\012" +
+ "\uffee\013\uffee\014\uffee\035\uffee\001\002\000\004\037\241" +
+ "\001\002\000\022\007\uff99\010\uff99\011\uff99\012\uff99\013" +
+ "\uff99\014\uff99\017\236\035\uff99\001\002\000\020\007\uffed" +
+ "\010\uffed\011\uffed\012\uffed\013\uffed\014\uffed\035\uffed\001" +
+ "\002\000\004\037\244\001\002\000\022\007\uff99\010\uff99" +
+ "\011\uff99\012\uff99\013\uff99\014\uff99\017\236\035\uff99\001" +
+ "\002\000\020\007\uffef\010\uffef\011\uffef\012\uffef\013\uffef" +
+ "\014\uffef\035\uffef\001\002\000\004\037\247\001\002\000" +
+ "\022\007\uff99\010\uff99\011\uff99\012\uff99\013\uff99\014\uff99" +
+ "\017\236\035\uff99\001\002\000\020\007\ufff0\010\ufff0\011" +
+ "\ufff0\012\ufff0\013\ufff0\014\ufff0\035\ufff0\001\002\000\004" +
+ "\002\001\001\002" });
+
+ /** Access to parse-action table. */
+ public short[][] action_table() {return _action_table;}
+
+ /** <code>reduce_goto</code> table. */
+ protected static final short[][] _reduce_table =
+ unpackFromStrings(new String[] {
+ "\000\247\000\006\003\003\055\004\001\001\000\002\001" +
+ "\001\000\006\004\176\037\175\001\001\000\010\012\012" +
+ "\014\010\024\007\001\001\000\016\017\020\025\160\026" +
+ "\164\033\161\044\163\054\030\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\061\041\066\043" +
+ "\062\001\001\000\002\001\001\000\016\017\020\025\023" +
+ "\027\017\034\036\045\031\054\030\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\063\055\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\010\027\017\034\036\045\045" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\061\042\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\034\057\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\015\114\037\113" +
+ "\001\001\000\004\041\112\001\001\000\002\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\004" +
+ "\066\107\001\001\000\004\064\104\001\001\000\004\065" +
+ "\072\001\001\000\012\042\077\047\074\052\100\053\075" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\010\047\074\052\103\053\075\001" +
+ "\001\000\002\001\001\000\012\042\105\047\074\052\100" +
+ "\053\075\001\001\000\002\001\001\000\002\001\001\000" +
+ "\012\042\110\047\074\052\100\053\075\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\010\016\126\030\127\046\124\001\001\000\002" +
+ "\001\001\000\004\046\120\001\001\000\002\001\001\000" +
+ "\004\067\122\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\004\070\133\001\001\000\004\072" +
+ "\131\001\001\000\006\030\130\046\124\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\004\071\135\001\001\000\012" +
+ "\031\137\035\141\036\140\037\136\001\001\000\002\001" +
+ "\001\000\006\032\150\047\147\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\010\031\137\036" +
+ "\144\037\136\001\001\000\002\001\001\000\002\001\001" +
+ "\000\006\047\074\053\156\001\001\000\006\037\151\051" +
+ "\152\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\006\050\154\054\155\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\010\026\164\033\161\044\174\001\001\000\002\001" +
+ "\001\000\004\060\172\001\001\000\002\001\001\000\004" +
+ "\062\165\001\001\000\002\001\001\000\004\033\170\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\002\001\001\000\006\005\203\037\204\001\001\000\006" +
+ "\017\200\054\030\001\001\000\004\056\201\001\001\000" +
+ "\002\001\001\000\002\001\001\000\006\007\205\020\206" +
+ "\001\001\000\002\001\001\000\022\006\225\010\220\012" +
+ "\012\013\217\014\227\022\221\023\216\024\007\001\001" +
+ "\000\002\001\001\000\010\017\210\021\211\054\030\001" +
+ "\001\000\002\001\001\000\004\057\212\001\001\000\002" +
+ "\001\001\000\002\001\001\000\004\054\051\001\001\000" +
+ "\002\001\001\000\002\001\001\000\002\001\001\000\002" +
+ "\001\001\000\002\001\001\000\002\001\001\000\002\001" +
+ "\001\000\002\001\001\000\002\001\001\000\002\001\001" +
+ "\000\016\012\012\024\065\037\063\040\230\041\066\043" +
+ "\062\001\001\000\006\015\231\037\113\001\001\000\010" +
+ "\016\232\030\127\046\124\001\001\000\006\030\130\046" +
+ "\124\001\001\000\002\001\001\000\004\011\236\001\001" +
+ "\000\002\001\001\000\002\001\001\000\002\001\001\000" +
+ "\004\011\241\001\001\000\002\001\001\000\002\001\001" +
+ "\000\004\011\244\001\001\000\002\001\001\000\002\001" +
+ "\001\000\004\011\247\001\001\000\002\001\001\000\002" +
+ "\001\001" });
+
+ /** Access to <code>reduce_goto</code> table. */
+ public short[][] reduce_table() {return _reduce_table;}
+
+ /** Instance of action encapsulation class. */
+ protected CUP$parser$actions action_obj;
+
+ /** Action encapsulation object initializer. */
+ protected void init_actions()
+ {
+ action_obj = new CUP$parser$actions(this);
+ }
+
+ /** 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$parser$do_action(act_num, parser, stack, top);
+ }
+
+ /** Indicates start state. */
+ public int start_state() {return 0;}
+ /** Indicates start production. */
+ public int start_production() {return 0;}
+
+ /** <code>EOF</code> Symbol index. */
+ public int EOF_sym() {return 0;}
+
+ /** <code>error</code> Symbol index. */
+ public int error_sym() {return 1;}
+
+
+ /** User initialization code. */
+ public void user_init() throws java.lang.Exception
+ {
+ lexer.init();
+ }
+
+ /** Scan to get the next Symbol. */
+ public java_cup.runtime.Symbol 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);
+ }
+
+}
+
+/** Cup generated class to encapsulate user supplied action code.*/
+class CUP$parser$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;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+
+ private final parser parser;
+
+ /** Constructor */
+ CUP$parser$actions(parser parser) {
+ this.parser = parser;
+ }
+
+ /** Method with the actual generated action code. */
+ public final java_cup.runtime.Symbol CUP$parser$do_action(
+ int CUP$parser$act_num,
+ java_cup.runtime.lr_parser CUP$parser$parser,
+ java.util.Stack CUP$parser$stack,
+ int CUP$parser$top)
+ throws java.lang.Exception
+ {
+ /* Symbol object for return from actions */
+ java_cup.runtime.Symbol CUP$parser$result;
+
+ /* select the action based on the action number */
+ switch (CUP$parser$act_num)
+ {
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 106: // empty ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(29/*empty*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 105: // opt_semi ::= SEMI
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 104: // opt_semi ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(7/*opt_semi*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 103: // non_terminal ::= NONTERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 102: // non_terminal ::= NON TERMINAL
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(8/*non_terminal*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 101: // robust_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 100: // robust_id ::= NONASSOC
+ {
+ String RESULT = null;
+ RESULT = "nonassoc";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 99: // robust_id ::= RIGHT
+ {
+ String RESULT = null;
+ RESULT = "right";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 98: // robust_id ::= LEFT
+ {
+ String RESULT = null;
+ RESULT = "left";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 97: // robust_id ::= PRECEDENCE
+ {
+ String RESULT = null;
+ RESULT = "precedence";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 96: // robust_id ::= START
+ {
+ String RESULT = null;
+ RESULT = "start";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 95: // robust_id ::= WITH
+ {
+ String RESULT = null;
+ RESULT = "with";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 94: // robust_id ::= SCAN
+ {
+ String RESULT = null;
+ RESULT = "scan";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 93: // robust_id ::= INIT
+ {
+ String RESULT = null;
+ RESULT = "init";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 92: // robust_id ::= NONTERMINAL
+ {
+ String RESULT = null;
+ RESULT = "nonterminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 91: // robust_id ::= NON
+ {
+ String RESULT = null;
+ RESULT = "non";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 90: // robust_id ::= TERMINAL
+ {
+ String RESULT = null;
+ RESULT = "terminal";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 89: // robust_id ::= PARSER
+ {
+ String RESULT = null;
+ RESULT = "parser";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 88: // robust_id ::= ACTION
+ {
+ String RESULT = null;
+ RESULT = "action";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 87: // robust_id ::= CODE
+ {
+ String RESULT = null;
+ RESULT = "code";
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 86: // robust_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(42/*robust_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 85: // label_id ::= robust_id
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(38/*label_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 84: // symbol_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 83: // symbol_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(37/*symbol_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 82: // nt_id ::= error
+ {
+ String RESULT = null;
+
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 81: // nt_id ::= ID
+ {
+ String RESULT = null;
+ int the_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int the_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String the_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = the_id;
+ CUP$parser$result = new java_cup.runtime.Symbol(36/*nt_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 80: // new_non_term_id ::= ID
+ {
+ Object RESULT = null;
+ int non_term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int non_term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String non_term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(26/*new_non_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 79: // new_term_id ::= ID
+ {
+ Object RESULT = null;
+ int term_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(25/*new_term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 78: // type_id ::= type_id LBRACK RBRACK
+ {
+ Object RESULT = null;
+ multipart_name = multipart_name.concat("[]");
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 77: // type_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(19/*type_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 76: // import_id ::= multipart_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 75: // import_id ::= multipart_id DOT STAR
+ {
+ Object RESULT = null;
+ append_multipart("*");
+ CUP$parser$result = new java_cup.runtime.Symbol(15/*import_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 74: // multipart_id ::= robust_id
+ {
+ Object RESULT = null;
+ int an_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int an_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String an_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(an_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 73: // multipart_id ::= multipart_id DOT robust_id
+ {
+ Object RESULT = null;
+ int another_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int another_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String another_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ append_multipart(another_id);
+ CUP$parser$result = new java_cup.runtime.Symbol(13/*multipart_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 72: // opt_label ::= empty
+ {
+ String RESULT = null;
+ RESULT = null;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 71: // opt_label ::= COLON label_id
+ {
+ String RESULT = null;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+ RESULT = labid;
+ CUP$parser$result = new java_cup.runtime.Symbol(39/*opt_label*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 70: // prod_part ::= CODE_STRING
+ {
+ Object RESULT = null;
+ int code_strleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int code_strright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String code_str = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 69: // prod_part ::= symbol_id opt_label
+ {
+ Object RESULT = null;
+ int symidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int symidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String symid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int labidleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int labidright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String labid = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(24/*prod_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 68: // prod_part_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 67: // prod_part_list ::= prod_part_list prod_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(23/*prod_part_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 66: // rhs ::= prod_part_list
+ {
+ Object RESULT = null;
+
+ 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(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 65: // rhs ::= prod_part_list PERCENT_PREC term_id
+ {
+ Object RESULT = null;
+ int term_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int term_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String term_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ 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(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(28/*rhs*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 64: // rhs_list ::= rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 63: // rhs_list ::= rhs_list BAR rhs
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(27/*rhs_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 62: // production ::= error NT$13 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$13
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 61: // NT$13 ::=
+ {
+ Object RESULT = null;
+ lexer.emit_error("Syntax Error");
+ CUP$parser$result = new java_cup.runtime.Symbol(56/*NT$13*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 60: // production ::= nt_id NT$11 COLON_COLON_EQUALS NT$12 rhs_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$11
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-4)).value;
+ // propagate RESULT from NT$12
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-5)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(22/*production*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-5)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 59: // NT$12 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(55/*NT$12*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 58: // NT$11 ::=
+ {
+ Object RESULT = null;
+ int lhs_idleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int lhs_idright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String lhs_id = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* 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 +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(54/*NT$11*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 57: // production_list ::= production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 56: // production_list ::= production_list production
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(12/*production_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 55: // start_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 54: // start_spec ::= START WITH nt_id NT$10 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$10
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(11/*start_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 53: // NT$10 ::=
+ {
+ Object RESULT = null;
+ int start_nameleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int start_nameright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String start_name = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+
+ CUP$parser$result = new java_cup.runtime.Symbol(53/*NT$10*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 52: // term_id ::= symbol_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(41/*term_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 51: // terminal_id ::= term_id
+ {
+ String RESULT = null;
+ int symleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left;
+ int symright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right;
+ String sym = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value;
+
+ add_precedence(sym);
+ RESULT = sym;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(40/*terminal_id*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 50: // terminal_list ::= terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 49: // terminal_list ::= terminal_list COMMA terminal_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(32/*terminal_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 48: // preced ::= PRECEDENCE NONASSOC NT$9 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$9
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 47: // NT$9 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.nonassoc);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(52/*NT$9*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 46: // preced ::= PRECEDENCE RIGHT NT$8 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$8
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 45: // NT$8 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.right);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(51/*NT$8*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 44: // preced ::= PRECEDENCE LEFT NT$7 terminal_list SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$7
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(31/*preced*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 43: // NT$7 ::=
+ {
+ Object RESULT = null;
+
+ update_precedence(assoc.left);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(50/*NT$7*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 42: // precedence_l ::= preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 41: // precedence_l ::= precedence_l preced
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(33/*precedence_l*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 40: // precedence_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 39: // precedence_list ::= precedence_l
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(30/*precedence_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 38: // non_term_name_list ::= new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 37: // non_term_name_list ::= non_term_name_list COMMA new_non_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(21/*non_term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 36: // term_name_list ::= new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 35: // term_name_list ::= term_name_list COMMA new_term_id
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(20/*term_name_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 34: // declares_non_term ::= non_term_name_list NT$6 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$6
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(35/*declares_non_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 33: // NT$6 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(49/*NT$6*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 32: // declares_term ::= term_name_list NT$5 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$5
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(34/*declares_term*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 31: // NT$5 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(48/*NT$5*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 30: // symbol ::= non_terminal error NT$4 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$4
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 29: // NT$4 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(47/*NT$4*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 28: // symbol ::= TERMINAL error NT$3 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$3
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 27: // NT$3 ::=
+ {
+ Object RESULT = null;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(46/*NT$3*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 26: // symbol ::= non_terminal declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 25: // symbol ::= non_terminal type_id declares_non_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 24: // symbol ::= TERMINAL declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 23: // symbol ::= TERMINAL type_id declares_term
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(18/*symbol*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 22: // symbol_list ::= symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 21: // symbol_list ::= symbol_list symbol
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(10/*symbol_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 20: // scan_code ::= SCAN WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(17/*scan_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 19: // init_code ::= INIT WITH CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(16/*init_code*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 18: // parser_code_part ::= PARSER CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(9/*parser_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 17: // action_code_part ::= ACTION CODE CODE_STRING opt_semi
+ {
+ Object RESULT = null;
+ int user_codeleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int user_coderight = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ String user_code = (String)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(4/*action_code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 16: // code_parts ::= code_parts code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 15: // code_parts ::=
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(5/*code_parts*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 14: // code_part ::= scan_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 13: // code_part ::= init_code
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 12: // code_part ::= parser_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 11: // code_part ::= action_code_part
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(6/*code_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 10: // import_spec ::= IMPORT import_id NT$2 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$2
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(14/*import_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 9: // NT$2 ::=
+ {
+ Object RESULT = null;
+
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(45/*NT$2*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 8: // import_list ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 7: // import_list ::= import_list import_spec
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(3/*import_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 6: // package_spec ::= empty
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 5: // package_spec ::= PACKAGE multipart_id NT$1 SEMI
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$1
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(2/*package_spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-3)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 4: // NT$1 ::=
+ {
+ Object RESULT = null;
+
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+
+ CUP$parser$result = new java_cup.runtime.Symbol(44/*NT$1*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 3: // spec ::= error symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-4)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 2: // spec ::= NT$0 package_spec import_list code_parts symbol_list precedence_list start_spec production_list
+ {
+ Object RESULT = null;
+ // propagate RESULT from NT$0
+ if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value != null )
+ RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-7)).value;
+
+ CUP$parser$result = new java_cup.runtime.Symbol(1/*spec*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-7)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 1: // NT$0 ::=
+ {
+ Object RESULT = null;
+
+ /* 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);
+
+ CUP$parser$result = new java_cup.runtime.Symbol(43/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ return CUP$parser$result;
+
+ /*. . . . . . . . . . . . . . . . . . . .*/
+ case 0: // $START ::= spec EOF
+ {
+ Object RESULT = null;
+ int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left;
+ int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right;
+ Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value;
+ RESULT = start_val;
+ CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT);
+ }
+ /* ACCEPT */
+ CUP$parser$parser.done_parsing();
+ return CUP$parser$result;
+
+ /* . . . . . .*/
+ default:
+ throw new Exception(
+ "Invalid action number found in internal parse table");
+
+ }
+ }
+}
+
--- /dev/null
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** 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: 7/3/96
+ * @author Frank Flannery
+ */
+
+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;
+ String declare_str;
+ int rightlen = rhs_l;
+
+ /* 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");
+
+ /* I'm not translating labels anymore, I'm adding code to declare
+ labels as valid variables. This way, the users code string is
+ untouched
+ 6/96 frankf */
+
+ /* check if the last part of the right hand side is an action. If
+ it is, it won't be on the stack, so we don't want to count it
+ in the rightlen. Then when we search down the stack for a
+ Symbol, we don't try to search past action */
+
+ if (rhs_l > 0) {
+ if (rhs_parts[rhs_l - 1].is_action()) {
+ rightlen = rhs_l - 1;
+ } else {
+ rightlen = rhs_l;
+ }
+ }
+
+ /* get the generated declaration code for the necessary labels. */
+ declare_str = declare_labels(
+ rhs_parts, rightlen, action_str);
+
+ if (action_str == null)
+ action_str = declare_str;
+ else
+ action_str = declare_str + action_str;
+
+ /* 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--;
+
+ /* Why does this run through the right hand side happen
+ over and over? here a quick combination of two
+ prior runs plus one I wanted of my own
+ frankf 6/25/96 */
+ /* allocate and copy over the right-hand-side */
+ /* count use of each rhs symbol */
+ _rhs = new production_part[_rhs_length];
+ for (i=0; i<_rhs_length; i++) {
+ _rhs[i] = rhs_parts[i];
+ if (!_rhs[i].is_action()) {
+ ((symbol_part)_rhs[i]).the_symbol().note_use();
+ if (((symbol_part)_rhs[i]).the_symbol() instanceof terminal) {
+ _rhs_prec =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_num();
+ _rhs_assoc =
+ ((terminal)((symbol_part)_rhs[i]).the_symbol()).precedence_side();
+ }
+ }
+ }
+
+ /*now action string is really declaration string, so put it in front!
+ 6/14/96 frankf */
+ if (action_str == null) action_str = "";
+ if (tail_action != null && tail_action.code_string() != null)
+ action_str = action_str + "\t\t" + tail_action.code_string();
+
+ /* 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);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor with precedence and associativity of production
+ contextually define */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ String action_str,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,action_str);
+
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /* Constructor w/ no action string and contextual precedence
+ defined */
+ public production(
+ non_terminal lhs_sym,
+ production_part rhs_parts[],
+ int rhs_l,
+ int prec_num,
+ int prec_side)
+ throws internal_error
+ {
+ this(lhs_sym,rhs_parts,rhs_l,null);
+ /* set the precedence */
+ set_precedence_num(prec_num);
+ set_precedence_side(prec_side);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /*-----------------------------------------------------------*/
+ /*--- (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();}
+
+ /** Lookup a production by index. */
+ public static production find(int indx) {
+ return (production) _all.get(new Integer(indx));
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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;}
+
+
+ /** The precedence of the rule */
+ protected int _rhs_prec = -1;
+ protected int _rhs_assoc = -1;
+
+ /** Access to the precedence of the rule */
+ public int precedence_num() { return _rhs_prec; }
+ public int precedence_side() { return _rhs_assoc; }
+
+ /** Setting the precedence of a rule */
+ public void set_precedence_num(int prec_num) {
+ _rhs_prec = prec_num;
+ }
+ public void set_precedence_side(int prec_side) {
+ _rhs_assoc = prec_side;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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 ---------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+
+ /** Return label declaration code
+ * @param labelname the label name
+ * @param stack_type the stack type of label?
+ * @author frankf
+ */
+ protected String make_declaration(
+ String labelname,
+ String stack_type,
+ int offset)
+ {
+ String ret;
+
+ /* Put in the left/right value labels */
+ if (emit.lr_values())
+ ret = "\t\tint " + labelname + "left = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).left;\n" +
+ "\t\tint " + labelname + "right = ((java_cup.runtime.Symbol)" +
+ emit.pre("stack") + ".elementAt(" + emit.pre("top") +
+ "-" + offset + ")).right;\n";
+ else ret = "";
+
+ /* otherwise, just declare label. */
+ return ret + "\t\t" + stack_type + " " + labelname + " = (" + stack_type +
+ ")((" + "java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top")
+ + "-" + offset + ")).value;\n";
+
+ }
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Declare label names as valid variables within the action string
+ * @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 declare_labels(
+ production_part rhs[],
+ int rhs_len,
+ String final_action)
+ {
+ String declaration = "";
+
+ 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, make declaration! */
+ if (part.label() != null)
+ {
+ declaration = declaration +
+ make_declaration(part.label(), part.the_symbol().stack_type(),
+ rhs_len-pos-1);
+ }
+ }
+ }
+ return declaration;
+ }
+
+
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** 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.
+ */
+
+ /* the declarations added to the parent production are also passed along,
+ as they should be perfectly valid in this code string, since it
+ was originally a code string in the parent, not on its own.
+ frank 6/20/96 */
+ protected void remove_embedded_actions(
+
+ ) throws internal_error
+ {
+ non_terminal new_nt;
+ production new_prod;
+ String declare_str;
+
+ /* 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())
+ {
+
+
+ declare_str = declare_labels(
+ _rhs, act_loc, "");
+ /* create a new non terminal for the action production */
+ new_nt = non_terminal.create_new();
+ new_nt.is_embedded_action = true; /* 24-Mar-1998, CSA */
+
+ /* create a new production with just the action */
+ new_prod = new action_production(this, new_nt, null, 0,
+ declare_str + ((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;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+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 " ";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+
+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(with prod " + reduce_with().index() + ")";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+
+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(to state " + shift_to().index() + ")";}
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+
+//----------------------------------------------------
+// The following code was generated by CUP v0.10k
+// Sun Jul 25 13:35:26 EDT 1999
+//----------------------------------------------------
+
+package java_cup;
+
+/** CUP generated class containing symbol constants. */
+public class sym {
+ /* terminals */
+ public static final int NON = 8;
+ public static final int NONTERMINAL = 27;
+ public static final int STAR = 15;
+ public static final int SEMI = 13;
+ public static final int CODE = 4;
+ public static final int EOF = 0;
+ public static final int NONASSOC = 23;
+ public static final int LEFT = 21;
+ public static final int PACKAGE = 2;
+ public static final int COLON = 17;
+ public static final int WITH = 11;
+ public static final int IMPORT = 3;
+ public static final int error = 1;
+ public static final int COLON_COLON_EQUALS = 18;
+ public static final int COMMA = 14;
+ public static final int DOT = 16;
+ public static final int SCAN = 10;
+ public static final int ID = 28;
+ public static final int INIT = 9;
+ public static final int PARSER = 6;
+ public static final int TERMINAL = 7;
+ public static final int PRECEDENCE = 20;
+ public static final int LBRACK = 25;
+ public static final int RBRACK = 26;
+ public static final int PERCENT_PREC = 24;
+ public static final int START = 12;
+ public static final int RIGHT = 22;
+ public static final int BAR = 19;
+ public static final int ACTION = 5;
+ public static final int CODE_STRING = 29;
+}
+
--- /dev/null
+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: 7/3/96
+ * @author Frank Flannery
+ */
+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 = "Object";
+
+ _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();
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+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$$";
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+
+package java_cup;
+
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** 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;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
+
--- /dev/null
+package java_cup;
+
+import java_cup.assoc;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+/** 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: 7/3/96
+ * @author Frank Flannery
+ */
+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, int precedence_side, int precedence_num)
+ {
+ /* 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++;
+
+ /* set the precedence */
+ _precedence_num = precedence_num;
+ _precedence_side = precedence_side;
+
+ /* add to by_index set */
+ _all_by_index.put(new Integer(_index), this);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for non-precedented terminal
+ */
+
+ public terminal(String nm, String tp)
+ {
+ this(nm, tp, assoc.no_prec, -1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor with default type.
+ * @param nm the name of the terminal.
+ */
+ public terminal(String nm)
+ {
+ this(nm, null);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*------------------- Class Variables ---------------------*/
+ /*-----------------------------------------------------------*/
+
+ private int _precedence_num;
+ private int _precedence_side;
+
+ /*-----------------------------------------------------------*/
+ /*--- (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() + "]";
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** get the precedence of a terminal */
+ public int precedence_num() {
+ return _precedence_num;
+ }
+ public int precedence_side() {
+ return _precedence_side;
+ }
+
+ /** set the precedence of a terminal */
+ public void set_precedence(int p, int new_prec) {
+ _precedence_side = p;
+ _precedence_num = new_prec;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
--- /dev/null
+
+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;
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+
--- /dev/null
+
+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.10a).
+ * 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: 12/22/97 [CSA]
+ * @author Frank Flannery
+ */
+
+public class version {
+ /** The major version number. */
+ public static final int major = 0;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The minor version number. */
+ public static final int minor = 10;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The update letter. */
+ public static final char update = 'k';
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** String for the current version. */
+ public static final String version_str = "v" + major + "." + minor + update;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Full title of the system */
+ public static final String title_str = "CUP " + version_str;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Name of the author */
+ public static final String author_str =
+ "Scott E. Hudson, Frank Flannery, and C. Scott Ananian";
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The command name normally used to invoke this program */
+ public static final String program_name = "java_cup";
+}
--- /dev/null
+From toddk@MICROSOFT.com Tue Mar 24 22:07:19 1998
+Date: Fri, 30 Jan 1998 07:54:26 -0800
+From: Todd Knoblock <toddk@MICROSOFT.com>
+To: "'cananian@alumni.princeton.edu'" <cananian@alumni.Princeton.EDU>
+Subject: Java cup under Windows NT.
+
+I wanted to try java cup under Windows NT. Rather than transliterating the
+csh shell script, I put together a little makefile for it. I thought you
+might want to include it in the distribution so that it is available for the
+next person that wants to use java cup under Windows NT.
+
+Todd Knoblock
+
+To use, place this file in the root javacup directory (where the "java_cup"
+directory lives), and type "nmake" from that directory.
+
+[The makefile has been included in this directory. -- CSA 24-Mar-1998 ]
--- /dev/null
+#\r
+# Windows NT makefile for java_cup\r
+# by Todd Knoblock, 28 January 1998.\r
+#\r
+# To run, type "nmake all" from the directory containing the make file.\r
+# Tested under nmake version 1.62.7022\r
+\r
+JVC=jvc\r
+# -x means disable extensions\r
+# -g means include debug information\r
+# -w2 means warning level 2.\r
+# Unfornately, anything above warning level 2 is noisy\r
+JVCFLAGS= -x -g -w2\r
+JVIEW=jview\r
+\r
+.SUFFIXES: .java .class\r
+\r
+.java.class:\r
+ $(JVC) $(JVCFLAGS) $<\r
+ \r
+all: runtime simple_calc java_cup test\r
+\r
+java_cup: java_cup\*.class\r
+\r
+runtime: java_cup\runtime\*.class\r
+\r
+simple_calc: java_cup\simple_calc\sym.java \\r
+ java_cup\simple_calc\parser.java \\r
+ java_cup\simple_calc\*.class\r
+\r
+\r
+java_cup\simple_calc\sym.java: java_cup java_cup\simple_calc\parser.cup \r
+ $(JVIEW) java_cup.Main < java_cup\simple_calc\parser.cup\r
+ @del -f -q java_cup\simple_calc\sym.java >nul 2>nul \r
+ @del -f -q java_cup\simple_calc\parser.java >nul 2>nul \r
+ move sym.java java_cup\simple_calc\ \r
+ move parser.java java_cup\simple_calc\ \r
+\r
+java_cup\simple_calc\parser.java: java_cup\simple_calc\sym.java\r
+\r
+clean:\r
+ @del -f -q java_cup\simple_calc\sym.java >nul 2>nul \r
+ @del -f -q java_cup\simple_calc\parser.java >nul 2>nul \r
+ @for %d in (java_cup java_cup\runtime java_cup\simple_calc) do \\r
+ @pushd %d \\r
+ & del -f -q *.class >nul 2>nul \\r
+ & popd\r
+\r
+test: simple_calc\r
+ @echo Executing the demo program. Answer should be 5050.\r
+ echo 101*100/2; | $(JVIEW) java_cup.simple_calc.Main\r
--- /dev/null
+CLASSFILES=Main/Main.class Lex/BooleanLiteral.class \
+Lex/CharacterLiteral.class Lex/Comment.class \
+Lex/DocumentationComment.class Lex/EndOfLineComment.class \
+Lex/EOF.class Lex/EscapedUnicodeReader.class Lex/FIFO.class \
+Lex/FloatLiteral.class Lex/Identifier.class Lex/InputElement.class \
+Lex/IntegerLiteral.class Lex/Keyword.class Lex/Lexer.class \
+Lex/Literal.class Lex/LongLiteral.class Lex/NullLiteral.class \
+Lex/NumericLiteral.class Lex/Operator.class Lex/Separator.class \
+Lex/StringLiteral.class Lex/Token.class Lex/TraditionalComment.class \
+Lex/WhiteSpace.class Tree/ParseNode.class \
+Tree/ParseNodeDOTVisitor.class Tree/ParseNodeVector.class \
+Tree/Walkable.class
+
+all: Parse/Sym.class Parse/Parser.class $(CLASSFILES)
+
+Parse/Parser.java Parse/Sym.java: Parse/java14.cup
+ cd Parse && \
+ java java_cup.Main -parser Parser -symbols Sym < java14.cup
+
+%.class: %.java
+ javac $<
\ No newline at end of file