META-INF/MANIFEST.MF
java_cup/action_part.class
java_cup/action_part.java
java_cup/action_production.class
java_cup/action_production.java
java_cup/assoc.class
java_cup/assoc.java
java_cup/CHANGELOG
java_cup/CUP$parser$actions.class
java_cup/cup_logo.gif
java_cup/emit.class
java_cup/emit.java
java_cup/hs_err_pid14251.log
java_cup/INSTALL
java_cup/INSTALL.QUICK
java_cup/internal_error.class
java_cup/internal_error.java
java_cup/lalr_item.class
java_cup/lalr_item.java
java_cup/lalr_item_set.class
java_cup/lalr_item_set.java
java_cup/lalr_state.class
java_cup/lalr_state.java
java_cup/lalr_transition.class
java_cup/lalr_transition.java
java_cup/lexer.class
java_cup/lexer.java
java_cup/LICENSE
java_cup/lr_item_core.class
java_cup/lr_item_core.java
java_cup/Main.class
java_cup/Main.java
java_cup/Makefile
java_cup/manual.html
java_cup/nonassoc_action.class
java_cup/nonassoc_action.java
java_cup/non_terminal.class
java_cup/non_terminal.java
java_cup/parser.class
java_cup/parser.cup
java_cup/parser.java
java_cup/parse_action.class
java_cup/parse_action.java
java_cup/parse_action_row.class
java_cup/parse_action_row.java
java_cup/parse_action_table.class
java_cup/parse_action_table.java
java_cup/parse_reduce_row.class
java_cup/parse_reduce_row.java
java_cup/parse_reduce_table.class
java_cup/parse_reduce_table.java
java_cup/production.class
java_cup/production.java
java_cup/production_part.class
java_cup/production_part.java
java_cup/README
java_cup/reduce_action.class
java_cup/reduce_action.java
java_cup/runtime/lr_parser.class
java_cup/runtime/lr_parser.java
java_cup/runtime/Scanner.class
java_cup/runtime/Scanner.java
java_cup/runtime/Symbol.class
java_cup/runtime/Symbol.java
java_cup/runtime/virtual_parse_stack.class
java_cup/runtime/virtual_parse_stack.java
java_cup/shift_action.class
java_cup/shift_action.java
java_cup/sym.class
java_cup/sym.java
java_cup/symbol.class
java_cup/symbol.java
java_cup/symbol_part.class
java_cup/symbol_part.java
java_cup/symbol_set.class
java_cup/symbol_set.java
java_cup/terminal.class
java_cup/terminal.java
java_cup/terminal_set.class
java_cup/terminal_set.java
java_cup/Thumbs.db
java_cup/version.class
java_cup/version.java
Manifest-Version: 1.0
Created-By: 1.6.0_07 (Sun Microsystems Inc.)
action_part
package java_cup;
public synchronized class action_part extends production_part {
protected String _code_string;
public void action_part(String);
public String code_string();
public void set_code_string(String);
public boolean is_action();
public boolean equals(action_part);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/action_part.java
java_cup/action_part.java
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() + “}”;
}
/*———————————————————–*/
}
action_production
package java_cup;
public synchronized class action_production extends production {
protected production _base_production;
public void action_production(production, non_terminal, production_part[], int, String) throws internal_error;
public production base_production();
}
java_cup/action_production.java
java_cup/action_production.java
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;}
}
assoc
package java_cup;
public synchronized class assoc {
public static final int left = 0;
public static final int right = 1;
public static final int nonassoc = 2;
public static final int no_prec = -1;
public void assoc();
}
java_cup/assoc.java
java_cup/assoc.javapackage 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;
}
CUP version 0.10k is a maintenance release.
CUP will now accept a filename on the command-line if it is the last
argument and does not start with “-“. This allows better GUI
integration. Some unix-isms in end-of-line handling have been fixed,
too; thanks to Jean Vaucher
The java_cup.runtime.Scanner interface has been refined to allow
the scanner to return null to signal EOF. JLex and JFlex users will
like this, as it means they can use the default scanner EOF behavior.
Bruce Hutton
and Vladimir Antonevich
reports touching on erroneous error recovery in the parser runtime.
Dr. Hutton provided the fixes that I’ve adopted; Zerksis sent a very
helpful CUP-vs-bison test case. If you’re in a position to notice
correct/incorrect error recovery and this release works better for you
than previous ones, thank them — and send me email so I know whether
we’ve quashed this bug for good.
Klaus Georg Barthelmann
oversight in the constructors for java_cup.runtime.Symbol. I’ve also
taken an obsolete constructor allowing specification of a start state
for some symbol to package-scope; if this causes anyone backwards
compatibility problems, email me and I will consider changing it back.
C. Scott Ananian
Laboratory for Computer Science
Massachusetts Institute of Technology
Jul-24-1999 [CSA]
————————————————————————
CUP version 0.10j adds new features.
A “-version” command-line option is now accepted, which prints out the
working version of CUP and halts. This allows automatic version-checking,
for those applications which require it.
Broadened the CUP input grammar to allow CUP reserved words in package and
import statements, and in (non)terminal labels. In addition, semicolons
after ‘action code’, ‘parser code’, ‘init code’, and ‘scan with’ sections
have been made optional (if language noise annoys you). Also, these four
sections may now appear in any order, instead of the strict ordering
previously required. Finally, you can now spell ‘non-terminal’ as either
“non terminal” (old way) *or* “nonterminal” without upsetting CUP.
[Flexibility requested by Stefan Kahrs
[Package and import reserved word issues noted by Frank Rehberger,
Brandon Schendel, and Bernie Honeisen, among others.]
Clarified the parse table dumps generated by the -dump* options.
I have added code to lr_parser to detect illegal Symbol recycling by the
scanner and to throw an Error in this case. The scanner must return
a fresh Symbol object on each invocation, because these objects are
tagged with parse state and added to the parse stack. Object sharing
does evil things to the parser; don’t do it (you won’t get away with it).
[Symbol recycling problems reported by Ken Arnold
Improved scanner interface, designed by David MacMahon
The new java_cup.runtime.Scanner interface is used by the default
implementation of lr_parser.scan(). See the manual for more details.
Old parsers will work with the new runtime, but parsers generated with
0.10j will not work with the runtime from earlier versions unless you
specify the (new) “-noscanner” option.
C. Scott Ananian
Laboratory for Computer Science
Massachusetts Institute of Technology
Jul-24-1999 [CSA]
————————————————————————
CUP version 0.10i is a maintenance release.
A one-off bug in the parser error-recovery code has been caught and corrected
by Chris Harris
The fields in the emitted symbol class have been made public, rather than
package scope, since the class already was public.
The issues formerly addressed in Appendix D (accessing parser methods/fields
from the action class) have been partially addressed by adding a new
private final field named ‘parser’ to the action object that points to
the parser object. THIS INTRODUCES A POTENTIAL INCOMPATIBILITY if you had
previously defined a field named ‘parser’ in the ‘action code {: … :}’
portion of your grammar. The solution is to rename your field.
Finally, incorporated Jako Andras’ suggestions to make CUP more friendly
to makefiles.
A reminder: please submit bug-fixes or feature-additions as *patches*, not
complete archives. Your patch will have a greater chance of integration
into the distribution if you package each feature or fix as a separate patch,
instead of lumping everything together and leaving it to me to figure out
what you’ve changed and why.
C. Scott Ananian
Laboratory for Computer Science
Massachusetts Institute of Technology
Feb-18-1999 [CSA]
————————————————————————
CUP version 0.10h is a maintenance release.
Starting with this version, CUP encodes the various parser tables as strings
to get around java’s 64k method-size limitation. This allows larger
parse tables and thus more complicated grammars.
Furthermore, a long-standing buglet that would cause CUP to occasionally
generate “Attempt to construct a duplicate state” internal errors has been
fixed.
Another contributed Microsoft-compatible makefile has also been added
to the distribution.
C. Scott Ananian
Laboratory for Computer Science
Massachusetts Institute of Technology
Feb-10-1999 [CSA]
————————————————————————
CUP version 0.10g contains bug fixes, added functionality, and
performance improvements. Thanks to Matthias Zenger, Peter Selinger,
Jaroslaw Kachinarz, Ian Davis and others for contributions.
– New command line option ‘-interface’ added. This causes JavaCUP to
emit an *interface* with the symbol constants, instead of a
*class*. Without the command-line flag, behavior is identical to
v0.10f and before: the symbols are emitted as a class.
– (minor) Added toString() method to java_cup.runtime.Symbol and
modified the debugging parser to use it. This allows you to
override toString() to allow a more intelligible debugging parse.
– The CUP grammar has been extended to allow one to declare array types
for javaCUP terminals and non-terminals. Matthias Zenger first
suggested this feature; Peter Selinger was the first to show the
right way to do it.
– The symbols prefixed with CUP$ now have the parser class file name
added to the prefix as well, to allow more than one parser object
per package. Thanks to Jaroslaw Kachniarz for pointing out this
problem.
– Fixed bug that prevented one from invoking the parser multiple times.
To quote Ian Davis, who found and diagnosed the bug:
Repeat invocations of the same instantiation of lr_parser.java to parse
distinct input statements fail for the simple reason that the stack is
not emptied at start of parsing, but the stack offset is reset to 0.
This has been fixed.
– Fixed bug with implicit start productions not receiving a RESULT.
– Fixed bug with RESULT assignments that are not right-most in the
production.
– Updated documentation.
Known issues:
– All known bugs have been fixed.
– The java_cup.runtime.SymbolStack / java_cup.runtime.intStack
performance hack originally suggested by Matthias Zenger has been
postponed to the next release. By eliminating typecasts and
synchronized methods, a substantial performance improvement can be
obtained. Backwards-compatibility issues have forced the postponement
of the code merge.
C. Scott Ananian
Laboratory for Computer Science
Massachusetts Institute of Technology
3/24/98 [CSA]
————————————————————————
CUP version 0.10f is a maintenance release. The code has been cleaned up
for JDK 1.1 functionality. No major functionality has been added; any bugs
in 0.10e are still in 0.10f.
– Removed trailing semicolons from class definitions which upset strict
compilers (not Sun’s javac, for some reason).
– Changed ‘PrintStream’s to ‘PrintWriter’s to eliminate deprecation
warnings.
As of this release, the javaCUP code is being maintained by
C. Scott Ananian. Suggestions and bug-fixes should be sent to
cananian@alumni.princeton.edu.
Known issues:
– Precedence bug: rules unmarked by precedence information are treated
as if they had existing, but very low, precedence. This can mask
parser conflicts.
– Efficiency hack: java.util.Stack will be replaced in the next
release with a special-purpose stack to eliminate
performance-robbing type-casts.
– It has been suggested that the symbol *class* should be an
*interface* instead. This will be a command-line option in the next
release.
C. Scott Ananian
Laboratory for Computer Science
Massachusetts Institute of Technology
12/21/97 [CSA]
————————————————————————
CUP version 0.10e contains a few bug fixes from 0.10a
– %prec directive now works correctly
fixed by cananian@princeton.edu
– Shift reduce conflicts are now correctly reported
fixed by danwang@cs.princeton.edu
– Error with reporting the positon of the error token also fixed
fixed by cananian@princeton.edu
– INSTALL script now has a slightly more complex test.
– foo.java.diff included for changes from previous release
– Fixed more bugs with reporting of shift reduce conflicts.
fixed by danwang@cs.princeton.edu
– Fixed bug introduced by previous fix patches from
Added ‘\r’ as a whitespace character for the lexer suggested by
(dladd@spyglass.com)
– Fixed botched relase
Daniel Wang
Department of Computer Science
Princeton University
Last updated: 9/12/97 [DW]
————————————————————————
Changes and Additions to CUP v0.9e
CUP version 0.10a is a major overhaul of CUP. The changes are severe,
meaning no backwards compatibility to older versions.
Here are the changes:
1. CUP now interfaces with the lexer in a completely different
manner. In the previous releases, a new class was used for every
distinct type of terminal. This release, however, uses only one class:
The Symbol class. The Symbol class has three instance variables which
are significant to the parser when passing information from the lexer.
The first is the value instance variable. This variable contains the
value of that terminal. It is of the type declared as the terminal type
in the parser specification file. The second two are the instance
variables left and right. They should be filled with the int value of
where in the input file, character-wise, that terminal was found.
2. Terminal and non-nonterminal declarations now can be declared in two
different ways to indicate the values of the terminals or non-terminals.
The previous declarations of the form
terminal {classname} {terminal} [, terminal …];
still works. The classname, however indicates the type of the value of
the terminal or non-terminal, and does not indicate the type of object
placed on the parse stack.
A declaration, such as:
terminal {terminal} [, terminal …];
indicates the terminals in the list hold no value.
3. CUP doesn’t use the Symbol class for just terminals, but for all
non-terminals as well. When a production reduces to a non-terminal, a
new Symbol is created, and the value field is filled with the value of
that non-terminal. The user must know that the terminal and non terminal
declarations specify a type corresponding to the type of the value field
for the symbol representing that terminal or non-terminal.
4. Label references do not refer to the object on the parse stack, as in
the old CUP, but rather to the value of the value instance variable of
the Symbol that represents that terminal or non-terminal. Hence,
references to terminal and non-terminal values is direct, as opposed to
the old CUP, where the labels referred to objects containing the value
of the terminal or non-terminal.
5. The RESULT variable refers directly to the value of the non-terminal
to which a rule reduces, rather than to the object on the parse stack.
Hence, RESULT is of the same type the non-terminal to which it reduces,
as declared in the non terminal declaration. Again, the reference is
direct, rather than to something that will contain the data.
6. For every label, two more variables are declared, which are the label
plus left or the label plus right. These correspond to the left and
right locations in the input stream to which that terminal or
non-terminal came from. These values are propagated from the input
terminals, so that the starting non-terminal should have a left value of
0 and a right value of the location of the last character read.
7. A call to parse() or debug_parse() return a Symbol. This Symbol is
of the start non-terminal, so the value field contains the final RESULT
assignment.
8. CUP now has precedenced terminals. a new declaration section,
occurring between the terminal and non-terminal declarations and the
grammar specifies the precedence and associativity of rules. The
declarations are of the form:
precedence {left| right | nonassoc} terminal[, terminal …];
…
The terminals are assigned a precedence, where terminals on the same
line have equal precedences, and the precedence declarations farther
down the list of precedence declarations have higher precedence. left,
right and nonassoc specify the associativity of these terminals. left
associativity corresponds to a reduce on conflict, right to a shift on
conflict, and nonassoc to an error on conflict. Hence, ambiguous
grammars may now be used. For a better explanation, see the manual.
9. Finally the new CUP adds contextual precedence. A production may be
declare as followed:
lhs ::= {right hand side list of terminals, non-terminals and actions}
%prec {terminal};
this production would then have a precedence equal to the terminal
specified after the “%prec”. Hence, shift/reduce conflicts can be
contextually resolved. Note that the “%prec terminal” part comes after
all actions strings. It does not come before the last action string.
For more information read the manual, found in manual.html
Frank Flannery
Department of Computer Science
Princeton University
Last updated: 7/3/96 [FF]
CUP$parser$actions
package java_cup;
synchronized class CUP$parser$actions {
protected final int MAX_RHS;
protected production_part[] rhs_parts;
protected int rhs_pos;
protected String multipart_name;
protected java.util.Hashtable symbols;
protected java.util.Hashtable non_terms;
protected non_terminal start_nt;
protected non_terminal lhs_nt;
int _cur_prec;
int _cur_side;
private final parser parser;
protected production_part add_lab(production_part, String) throws internal_error;
protected void new_rhs();
protected void add_rhs_part(production_part) throws Exception;
protected void append_multipart(String);
protected void update_precedence(int);
protected void add_precedence(String);
void CUP$parser$actions(parser);
public final runtime.Symbol CUP$parser$do_action(int, runtime.lr_parser, java.util.Stack, int) throws Exception;
}
emit
package java_cup;
public synchronized class emit {
public static String prefix;
public static String package_name;
public static String symbol_const_class_name;
public static String parser_class_name;
public static String action_code;
public static String parser_code;
public static String init_code;
public static String scan_code;
public static production start_production;
public static java.util.Stack import_list;
public static int num_conflicts;
public static boolean nowarn;
public static int not_reduced;
public static int unused_term;
public static int unused_non_term;
public static long symbols_time;
public static long parser_time;
public static long action_code_time;
public static long production_table_time;
public static long action_table_time;
public static long goto_table_time;
protected static boolean _lr_values;
static void
private void emit();
public static boolean lr_values();
protected static void set_lr_values(boolean);
protected static String pre(String);
protected static void emit_package(java.io.PrintWriter);
public static void symbols(java.io.PrintWriter, boolean, boolean);
protected static void emit_action_code(java.io.PrintWriter, production) throws internal_error;
protected static void emit_production_table(java.io.PrintWriter);
protected static void do_action_table(java.io.PrintWriter, parse_action_table, boolean) throws internal_error;
protected static void do_reduce_table(java.io.PrintWriter, parse_reduce_table);
protected static void do_table_as_string(java.io.PrintWriter, short[][]);
protected static int do_newline(java.io.PrintWriter, int, int);
protected static int do_escaped(java.io.PrintWriter, char);
public static void parser(java.io.PrintWriter, parse_action_table, parse_reduce_table, int, production, boolean, boolean) throws internal_error;
}
java_cup/emit.java
java_cup/emit.javapackage 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.
*
* Three classes are produced by this code:
*
-
*
- symbol constant class
* - this contains constant declarations for each terminal (and
* optionally each non-terminal).
* - action class
* - this non-public class contains code to invoke all the user actions
* that were embedded in the parser specification.
* - parser class
* - the specialized parser class consisting primarily of some user
* supplied general and initialization code, and the parse tables.
*
*
* Three parse tables are created as part of the parser class:
*
-
*
- production table
* - lists the LHS non terminal number, and the length of the RHS of
* each production.
* - action table
* - for each state of the parse machine, gives the action to be taken
* (shift, reduce, or error) under each lookahead symbol.
* - reduce-goto table
* - 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.
*
*
* 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).
*
* This class is “static” (contains only static data and methods).
*
* @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
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 reduce_goto
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
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
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(" /** EOF
Symbol index. */”);
out.println(” public int EOF_sym() {return ” + terminal.EOF.index() +
“;}”);
out.println();
out.println(” /** error
Symbol index. */”);
out.println(” public int error_sym() {return ” + terminal.error.index() +
“;}”);
out.println();
/* user supplied code for user_init() */
if (init_code != null)
{
out.println();
out.println(” /** User initialization 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;
}
/*———————————————————–*/
}
An unexpected exception has been detected in native code outside the VM.
Unexpected Signal : 11 occurred at PC=0x40030056
Function name=(N/A)
Library=/lib/i686/libpthread.so.0
NOTE: We are unable to locate the function name symbol for the error
just occurred. Please refer to release documentation for possible
reason and solutions.
Current Java thread:
Dynamic libraries:
08048000-0804c000 r-xp 00000000 00:14 1593841 /direct/pkgs/jdk-1.3.1_02/linux/bin/i386/native_threads/javac
0804c000-0804d000 rw-p 00003000 00:14 1593841 /direct/pkgs/jdk-1.3.1_02/linux/bin/i386/native_threads/javac
40000000-40013000 r-xp 00000000 09:00 163991 /lib/ld-2.2.5.so
40013000-40014000 rw-p 00013000 09:00 163991 /lib/ld-2.2.5.so
40024000-40025000 r–p 00000000 09:00 98337 /usr/lib/locale/en_US/LC_IDENTIFICATION
40025000-40026000 r–p 00000000 09:00 163898 /usr/lib/locale/en_US/LC_MEASUREMENT
40026000-40033000 r-xp 00000000 09:00 163989 /lib/i686/libpthread-0.9.so
40033000-4003a000 rw-p 0000d000 09:00 163989 /lib/i686/libpthread-0.9.so
4003b000-40044000 r-xp 00000000 00:14 1367121 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/native_threads/libhpi.so
40044000-40045000 rw-p 00008000 00:14 1367121 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/native_threads/libhpi.so
40045000-40235000 r-xp 00000000 00:14 1382433 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/client/libjvm.so
40235000-40333000 rw-p 001ef000 00:14 1382433 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/client/libjvm.so
4034a000-4034c000 r-xp 00000000 09:00 164004 /lib/libdl-2.2.5.so
4034c000-4034d000 rw-p 00001000 09:00 164004 /lib/libdl-2.2.5.so
4034d000-4035f000 r-xp 00000000 09:00 164008 /lib/libnsl-2.2.5.so
4035f000-40360000 rw-p 00012000 09:00 164008 /lib/libnsl-2.2.5.so
40362000-40383000 r-xp 00000000 09:00 163987 /lib/i686/libm-2.2.5.so
40383000-40384000 rw-p 00020000 09:00 163987 /lib/i686/libm-2.2.5.so
40385000-403b9000 r-xp 00000000 09:00 327752 /usr/lib/libstdc++-2-libc6.1-1-2.9.0.so
403b9000-403c5000 rw-p 00033000 09:00 327752 /usr/lib/libstdc++-2-libc6.1-1-2.9.0.so
403c7000-403d8000 r-xp 00000000 00:14 1356186 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/libverify.so
403d8000-403da000 rw-p 00010000 00:14 1356186 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/libverify.so
403da000-403fb000 r-xp 00000000 00:14 1356187 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/libjava.so
403fb000-403fd000 rw-p 00020000 00:14 1356187 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/libjava.so
403fe000-40412000 r-xp 00000000 00:14 1356188 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/libzip.so
40412000-40415000 rw-p 00013000 00:14 1356188 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i386/libzip.so
40415000-41146000 r–s 00000000 00:14 1582644 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/rt.jar
41173000-41418000 r–s 00000000 00:14 1582645 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/i18n.jar
41418000-4142e000 r–s 00000000 00:14 1582628 /direct/pkgs/jdk-1.3.1_02/linux/jre/lib/sunrsasign.jar
41b25000-41b26000 r–p 00000000 09:00 98423 /usr/lib/locale/en_US/LC_TELEPHONE
41b26000-41b27000 r–p 00000000 09:00 98425 /usr/lib/locale/en_US/LC_ADDRESS
41b27000-41b28000 r–p 00000000 09:00 98424 /usr/lib/locale/en_US/LC_NAME
41b28000-41b29000 r–p 00000000 09:00 426105 /usr/lib/locale/en_US/LC_PAPER
41b29000-41b2a000 r–p 00000000 09:00 442481 /usr/lib/locale/en_US/LC_MESSAGES/SYS_LC_MESSAGES
41b2a000-41b2b000 r–p 00000000 09:00 163897 /usr/lib/locale/en_US/LC_MONETARY
41b2b000-41b31000 r–p 00000000 09:00 295074 /usr/lib/locale/en_US/LC_COLLATE
41b31000-41b32000 r–p 00000000 09:00 98338 /usr/lib/locale/en_US/LC_TIME
41b32000-41b33000 r–p 00000000 09:00 163901 /usr/lib/locale/en_US/LC_NUMERIC
41b33000-41b5e000 r–p 00000000 09:00 295073 /usr/lib/locale/en_US/LC_CTYPE
41b70000-41b79000 r-xp 00000000 09:00 164024 /lib/libnss_files-2.2.5.so
41b79000-41b7a000 rw-p 00009000 09:00 164024 /lib/libnss_files-2.2.5.so
42000000-4212c000 r-xp 00000000 09:00 163985 /lib/i686/libc-2.2.5.so
4212c000-42131000 rw-p 0012c000 09:00 163985 /lib/i686/libc-2.2.5.so
4a700000-4ab7f000 r–s 00000000 00:14 1563987 /direct/pkgs/jdk-1.3.1_02/linux/lib/tools.jar
Local Time = Sat Nov 8 20:37:55 2003
Elapsed Time = 0
#
# The exception above was detected in native code outside the VM
#
# Java VM: Java HotSpot(TM) Client VM (1.3.1_02-b02 mixed mode)
#
#!/bin/csh -f
#
# Cup install and test script
# Scott Hudson 8/31/95
#
# Last revision 7/3/96 (for v0.10a)
# By Frank Flannery
#
# Last revision 11/16/96 (for v0.10b)
# By Daniel Wang
#
# Updated version number 7/24/99 for 0.10k
# By C. Scott Ananian
echo
echo “================================”
echo “Installing and testing Cup v0.10k”
echo “================================”
echo
# check for this directory in CLASSPATH
#
set cwd = `pwd`
set c_path = `printenv CLASSPATH`
if ($c_path !~ “*$cwd*”) then
echo ” ”
echo “WARNING:”
echo “WARNING: The current directory does not appear in your CLASSPATH”
echo “WARNING: it will be added for this install/test only”
echo “WARNING:”
echo ” ”
setenv CLASSPATH $cwd’:’$c_path
echo “CLASSPATH now set to ”
printenv CLASSPATH
endif
# change to the demo directory
#
echo ” ”
echo “changing to simple_calc subdirectory…”
echo “cd java_cup/simple_calc”
cd java_cup/simple_calc
# remove old copies of parser.java and sym.java
#
echo ” ”
echo “removing any old copies of parser.java and sym.java…”
echo “rm -f parser.java sym.java”
rm -f parser.java sym.java
# compile java_cup and run it against the demo program
# the -cs (for “checksource”) option here will force the
# java_cup and java_cup.runtime source to be compiled prior
# to running it.
#
echo ” ”
echo “compiling java_cup then generating demo program…”
echo “java -cs java_cup.Main < parser.cup"
java -cs java_cup.Main < parser.cup
# make sure parser.java and sym.java now exist
#
if ( ! -e parser.java) then
echo " "
echo "ERROR: for some reason parser.java was not created"
echo "ERROR: install was not successful"
exit 1
endif
if ( ! -e sym.java) then
echo " "
echo "ERROR: for some reason sym.java was not created"
echo "ERROR: install was not successful"
exit 1
endif
# run the demo
# again, the -cs option will cause compilation of all the parts
# of the demo program (including parser.java and sym.java that
# should have been generated in the previous step).
#
echo "removing old test results..."
echo "rm -f test_results"
rm -f test_results
echo " "
echo "executing the demo program..."
echo "echo '1*-2+2;' | java -cs java_cup.simple_calc.Main >& test_results”
echo ‘1*-2+2;’ | java -cs java_cup.simple_calc.Main >& test_results
# compare with standard results
#
set res = `tail -1 test_results`
if (“$res” !~ “= 0”) then
echo “ERROR: test program produced the wrong results”
echo “ERROR: output was:”
cat test_results
echo “ERROR: install was not successful”
rm -f test_results
exit 2
endif
# all is well
#
rm -f test_results
echo ” ”
echo “==============================”
echo “Install and test was successful”
echo “==============================”
exit 0
This is a quick installation guide for the CUP system.
For most people, the following steps will suffice:
1) extract the java_cup files somewhere, and ensure that
the extraction directory is in your classpath.
This will ensure that java_cup.Main properly refers to the
Main class in the java_cup subdirectory of this release.
2) compile java_cup and its runtime system.
From the installation directory:
javac java_cup/*.java java_cup/runtime/*.java
That’s it! Read the manual now.
–Scott
24-Mar-1998
internal_error
package java_cup;
public synchronized class internal_error extends Exception {
public void internal_error(String);
public void crash();
}
java_cup/internal_error.java
java_cup/internal_error.java
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);
}
}
lalr_item
package java_cup;
public synchronized class lalr_item extends lr_item_core {
protected terminal_set _lookahead;
protected java.util.Stack _propagate_items;
protected boolean needs_propagation;
public void lalr_item(production, int, terminal_set) throws internal_error;
public void lalr_item(production, terminal_set) throws internal_error;
public void lalr_item(production) throws internal_error;
public terminal_set lookahead();
public java.util.Stack propagate_items();
public void add_propagate(lalr_item);
public void propagate_lookaheads(terminal_set) throws internal_error;
public lalr_item shift() throws internal_error;
public terminal_set calc_lookahead(terminal_set) throws internal_error;
public boolean lookahead_visible() throws internal_error;
public boolean equals(lalr_item);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/lalr_item.java
java_cup/lalr_item.javapackage 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:
* [A ::= B * C d E , {a,b,c}] *
* indicates that the parser is in the middle of parsing the production
* A ::= B C d E *
* 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.
*
* 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
* 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:
* [L ::= a *N alpha, l] *
* (where N is a a non terminal and alpha is a string of symbols) make
* sure there are also items of the form:
* [N ::= *beta, first(alpha l)] *
* 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();
}
/*-----------------------------------------------------------*/
}
lalr_state
package java_cup;
public synchronized class lalr_state {
protected static java.util.Hashtable _all;
protected static java.util.Hashtable _all_kernels;
protected static int next_index;
protected lalr_item_set _items;
protected lalr_transition _transitions;
protected int _index;
static void
public void lalr_state(lalr_item_set) throws internal_error;
public static java.util.Enumeration all();
public static int number();
public static lalr_state find_state(lalr_item_set);
public lalr_item_set items();
public lalr_transition transitions();
public int index();
protected static void dump_state(lalr_state) throws internal_error;
protected static void propagate_all_lookaheads() throws internal_error;
public void add_transition(symbol, lalr_state) throws internal_error;
public static lalr_state build_machine(production) throws internal_error;
protected void propagate_lookaheads() throws internal_error;
public void build_table_entries(parse_action_table, parse_reduce_table) throws internal_error;
protected boolean fix_with_precedence(production, int, parse_action_row, parse_action) throws internal_error;
protected parse_action insert_action(parse_action, parse_action, int) throws internal_error;
protected parse_action insert_shift(parse_action, parse_action) throws internal_error;
protected parse_action insert_reduce(parse_action, parse_action) throws internal_error;
protected void report_conflicts(terminal_set) throws internal_error;
protected void report_reduce_reduce(lalr_item, lalr_item) throws internal_error;
protected void report_shift_reduce(lalr_item, int) throws internal_error;
public boolean equals(lalr_state);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/lalr_state.java
java_cup/lalr_state.java
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:
* [A ::= B * C d E , {a,b,c}] *
* 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:
* [C ::= * X e Z, {d}] * [X ::= * f, {e}] *
* 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.
*
* 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() + “] {“); * in some state, then we would be making a transition under X to a new * The full state would then be formed by “closing” this kernel set of
* public static lalr_state build_machine(production start_prod) /* sanity check */ /* build item with dot at front of start production and EOF lookahead */ itm = new lalr_item(start_prod); start_items.add(itm); /* create copy the item set to form the kernel */ /* create the closure from that item set */ /* build a state out of that item set and put it in our work set */ /* enter the state using the kernel as the key */ /* continue looking at new states until we have no more work to do */ /* gather up all the symbols that appear before dots */ /* add the symbol before the dot (if any) to our collection */ /* now create a transition out for each individual symbol */ /* will be keeping the set of items with propagate links */ /* gather up shifted versions of all the items that have this /* if this is the symbol we are working on now, add to set */ /* remember that itm has propagate link to it */ /* use new items as state kernel */ /* have we seen this one already? */ /* if we haven’t, build a new state out of the item set */ /* build the new state */ /* add the new state to our work set */ /* put it in our kernel table */ /* look at each propagate link out of that item */
* Conflicts occur if more than one action needs to go in one entry of the /* pull out our rows from the tables */ /* consider each item in our state */ /* if its completed (dot at end) then reduce under the lookahead */ /* consider each lookahead symbol */ /* if production precedes terminal, put reduce in table */ /* if terminal precedes rule, put shift in table */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /* given two actions, and an action type, return the /* find the shift in the two actions */ /* find the reduce in the two actions */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Produce warning messages for all conflicts found in this state. */ boolean after_itm; /* consider each element */ /* clear the S/R conflict set for this item */ /* if it results in a reduce, it could be a conflict */ /* compare this item against all others looking for conflicts */ /* if this is the item, next one is after it */ /* only look at it if its not the same item */ java_cup/lexer.java import java_cup.runtime.Symbol; /** This class implements a small scanner (aka lexical analyzer or lexer) for
* Symbols currently returned include: * All symbol constants are defined in sym.java which is generated by
*
* /*———————————————————–*/ /** The only constructor is private, so no instances can be created. */ /*———————————————————–*/ /** First character of lookahead. */ /** Second character of lookahead. */ /** Second character of lookahead. */ /** Second character of lookahead. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** EOF constant. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Table of keywords. Keywords are initially treated as identifiers. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Table of single character symbols. For ease of implementation, we /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Current line number for use in error messages. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Character position in current line. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Character position in current line. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Count of total errors detected so far. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Count of warnings issued so far */ /*———————————————————–*/ /** Initialize the scanner. This sets up the keywords and char_symbols /* set up the table of single character symbols */ /* read two characters of lookahead */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Advance the scanner one character in the input stream. This moves old_char = next_char; /* count this */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Emit an error message. The message will be marked with both the /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Emit a warning message. The message will be marked with both the /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Determine if a character is ok to start an id. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** The actual routine to return one Symbol. This is normally called from for (;;) /* look for a single character symbol */ /* look for : or ::= */ /* move forward and look for the ‘=’ */ /* find a “%prec” string and return it. otherwise, a ‘%’ was found, /* look for a comment */ /* look for start of code string */ /* look for an id or keyword */ /* look for EOF */ /* if we get here, we have an unrecognized character */ /* advance past it */ /*———————————————————–*/ CUP PARSER GENERATOR COPYRIGHT NOTICE, LICENSE AND DISCLAIMER. Copyright 1996 by Scott Hudson, Frank Flannery, C. Scott Ananian Permission to use, copy, modify, and distribute this software and its The authors and their employers disclaim all warranties with regard to lr_item_core package java_cup; java_cup/lr_item_core.java /** The “core” of an LR item. This includes a production and the position * This represents a point in a parse where the parser is trying to match public class lr_item_core { /** Full constructor. if (prod == null) _the_production = prod; if (pos < 0 || pos > _the_production.rhs_length()) _dot_pos = pos; /* compute and cache hash code now */ /* cache the symbol after the dot */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Return the symbol after the dot. If there is no symbol after the dot /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Determine if we have a dot before a non terminal, and if so which one /* get the symbol after the dot */ /* if it exists and is a non terminal, return it */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Produce a new lr_item_core that results from shifting the dot one return new lr_item_core(_the_production, _dot_pos+1); /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality comparison for the core only. This is separate out because we /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality comparison. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Generic equality comparison. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Hash code for the core (separated so we keep non overridden version). */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Hash code for the item. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Return the hash code that object would have provided for us so we have /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Convert to a string (separated out from toString() so we can call it if (_the_production.lhs() != 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;
}
}
/*-----------------------------------------------------------*/
}
Main
package java_cup;
public synchronized class Main {
protected static boolean print_progress;
protected static boolean opt_dump_states;
protected static boolean opt_dump_tables;
protected static boolean opt_dump_grammar;
protected static boolean opt_show_timing;
protected static boolean opt_do_debug;
protected static boolean opt_compact_red;
protected static boolean include_non_terms;
protected static boolean no_summary;
protected static int expect_conflicts;
protected static boolean lr_values;
protected static boolean sym_interface;
protected static boolean suppress_scanner;
protected static long start_time;
protected static long prelim_end;
protected static long parse_end;
protected static long check_end;
protected static long dump_end;
protected static long build_end;
protected static long nullability_end;
protected static long first_end;
protected static long machine_end;
protected static long table_end;
protected static long reduce_check_end;
protected static long emit_end;
protected static long final_time;
protected static java.io.BufferedInputStream input_file;
protected static java.io.PrintWriter parser_class_file;
protected static java.io.PrintWriter symbol_class_file;
protected static lalr_state start_state;
protected static parse_action_table action_table;
protected static parse_reduce_table reduce_table;
static void java_cup/Main.java import java.util.Enumeration; /** This class serves as the main driver for the JavaCup system.
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
* state. This new state would be formed by a “kernel” of items
* corresponding to moving the dot past the X. In this case:
* [A ::= a b X * c, {d,e}]
* [B ::= a b X * Y, {a,b}]
*
* 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).
* 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
*/
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;
if (start_prod == null)
throw new internal_error(
“Attempt to build viable prefix recognizer using a null production”);
start_items = new lalr_item_set();
itm.lookahead().add(terminal.EOF);
kernel = new lalr_item_set(start_items);
start_items.compute_closure();
start_state = new lalr_state(start_items);
work_stack.push(start_state);
_all_kernels.put(kernel, start_state);
while (!work_stack.empty())
{
/* remove a state from the work set */
st = (lalr_state)work_stack.pop();
outgoing = new symbol_set();
for (i = st.items().all(); i.hasMoreElements(); )
{
itm = (lalr_item)i.nextElement();
sym = itm.symbol_after_dot();
if (sym != null) outgoing.add(sym);
}
for (s = outgoing.all(); s.hasMoreElements(); )
{
sym = (symbol)s.nextElement();
linked_items = new lalr_item_set();
symbol before the dot */
new_items = new lalr_item_set();
for (i = st.items().all(); i.hasMoreElements();)
{
itm = (lalr_item)i.nextElement();
sym2 = itm.symbol_after_dot();
if (sym.equals(sym2))
{
/* add to the kernel of the new state */
new_items.add(itm.shift());
linked_items.add(itm);
}
}
kernel = new lalr_item_set(new_items);
new_st = (lalr_state)_all_kernels.get(kernel);
if (new_st == null)
{
/* compute closure of the kernel for the full item set */
new_items.compute_closure();
new_st = new lalr_state(new_items);
work_stack.push(new_st);
_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();
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.
* 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();
our_act_row = act_table.under_state[index()];
our_red_row = reduce_table.under_state[index()];
for (Enumeration i = items().all(); i.hasMoreElements(); )
{
itm = (lalr_item)i.nextElement();
if (itm.dot_at_end())
{
act = new reduce_action(itm.the_production());
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 (p.precedence_num() > term.precedence_num()) {
table_row.under_term[term_index] =
insert_reduce(table_row.under_term[term_index],act);
return true;
}
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;
}
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”);
}
}
protected parse_action insert_shift(
parse_action a1,
parse_action a2)
throws internal_error
{
return insert_action(a1, a2, parse_action.SHIFT);
}
protected parse_action insert_reduce(
parse_action a1,
parse_action a2)
throws internal_error
{
return insert_action(a1, a2, parse_action.REDUCE);
}
protected void report_conflicts(terminal_set conflict_set)
throws internal_error
{
lalr_item itm, compare;
symbol shift_sym;
for (Enumeration itms = items().all(); itms.hasMoreElements(); )
{
itm = (lalr_item)itms.nextElement();
if (itm.dot_at_end())
{
/* not yet after itm */
after_itm = false;
for (Enumeration comps = items().all(); comps.hasMoreElements(); )
{
compare = (lalr_item)comps.nextElement();
if (itm == compare) after_itm = true;
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;
}
/*-----------------------------------------------------------*/
}
lalr_transition
package java_cup;
public synchronized class lalr_transition {
protected symbol _on_symbol;
protected lalr_state _to_state;
protected lalr_transition _next;
public void lalr_transition(symbol, lalr_state, lalr_transition) throws internal_error;
public void lalr_transition(symbol, lalr_state) throws internal_error;
public symbol on_symbol();
public lalr_state to_state();
public lalr_transition next();
public String toString();
}
java_cup/lalr_transition.java
java_cup/lalr_transition.javapackage 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;
}
/*-----------------------------------------------------------*/
}
lexer
package java_cup;
public synchronized class lexer {
protected static int next_char;
protected static int next_char2;
protected static int next_char3;
protected static int next_char4;
protected static final int EOF_CHAR = -1;
protected static java.util.Hashtable keywords;
protected static java.util.Hashtable char_symbols;
protected static int current_line;
protected static int current_position;
protected static int absolute_position;
public static int error_count;
public static int warning_count;
static void
private void lexer();
public static void init() throws java.io.IOException;
protected static void advance() throws java.io.IOException;
public static void emit_error(String);
public static void emit_warn(String);
protected static boolean id_start_char(int);
protected static boolean id_char(int);
protected static int find_single_char(int);
protected static void swallow_comment() throws java.io.IOException;
protected static runtime.Symbol do_code_string() throws java.io.IOException;
protected static runtime.Symbol do_id() throws java.io.IOException;
public static runtime.Symbol next_token() throws java.io.IOException;
public static runtime.Symbol debug_next_token() throws java.io.IOException;
protected static runtime.Symbol real_next_token() throws java.io.IOException;
}
java_cup/lexer.javapackage java_cup;
import java.util.Hashtable;
* 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.
* 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
*
* JavaCup from parser.cup.
* 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.
* 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) —————————————-*/
/*———————————————————–*/
private lexer() { }
/*— Static (Class) Variables ——————————*/
/*———————————————————–*/
protected static int next_char;
protected static int next_char2;
protected static int next_char3;
protected static int next_char4;
protected static final int EOF_CHAR = -1;
* 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);
* 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);
protected static int current_line = 1;
protected static int current_position = 1;
protected static int absolute_position = 1;
public static int error_count = 0;
public static int warning_count = 0;
/*— Static Methods —————————————-*/
/*———————————————————–*/
* 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));
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));
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();
}
}
}
}
* next_char2 to next_char and then reads a new next_char2.
*/
protected static void advance() throws java.io.IOException
{
int old_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();
}
}
}
absolute_position++;
current_position++;
if (old_char == ‘\n’ || (old_char == ‘\r’ && next_char!=’\n’))
{
current_line++;
current_position = 1;
}
}
* 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++;
}
* 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++;
}
* @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;
}
* 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;
{
/* 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;
}
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);
}
if (next_char == ‘:’)
{
/* if we don’t have a second ‘:’ return COLON */
if (next_char2 != ‘:’)
{
advance();
return new Symbol(sym.COLON);
}
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);
}
}
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”);
}
}
if (next_char == ‘/’ && (next_char2 == ‘*’ || next_char2 == ‘/’))
{
/* swallow then continue the scan */
swallow_comment();
continue;
}
if (next_char == ‘{‘ && next_char2 == ‘:’)
return do_code_string();
if (id_start_char(next_char)) return do_id();
if (next_char == EOF_CHAR) return new Symbol(sym.EOF);
emit_warn(“Unrecognized character ‘” +
new Character((char)next_char) + “‘(” + next_char +
“) — ignored”);
advance();
}
}
}
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both the copyright notice and this permission notice and warranty
disclaimer appear in supporting documentation, and that the names of
the authors or their employers not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
this software, including all implied warranties of merchantability and
fitness. In no event shall the authors or their employers be liable
for any special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether in an
action of contract, negligence or other tortious action, arising out of
or in connection with the use or performance of this software.
public synchronized class lr_item_core {
protected production _the_production;
protected int _dot_pos;
protected int _core_hash_cache;
protected symbol _symbol_after_dot;
public void lr_item_core(production, int) throws internal_error;
public void lr_item_core(production) throws internal_error;
public production the_production();
public int dot_pos();
public boolean dot_at_end();
public symbol symbol_after_dot();
public non_terminal dot_before_nt();
public lr_item_core shift_core() throws internal_error;
public boolean core_equals(lr_item_core);
public boolean equals(lr_item_core);
public boolean equals(Object);
public int core_hashCode();
public int hashCode();
protected int obj_hash();
public String to_simple_string() throws internal_error;
public String toString();
}
java_cup/lr_item_core.java
package java_cup;
* 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:
* A ::= B * C d E
*
* 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
*/
/*———————————————————–*/
/*— Constructor(s) —————————————-*/
/*———————————————————–*/
* @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;
throw new internal_error(
“Attempt to create an lr_item_core with a null production”);
throw new internal_error(
“Attempt to create an lr_item_core with a bad dot position”);
_core_hash_cache = 13*_the_production.hashCode() + pos;
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();
}
* we return null. */
public symbol symbol_after_dot()
{
/* use the cached symbol */
return _symbol_after_dot;
}
* (return null or the non terminal).
*/
public non_terminal dot_before_nt()
{
symbol sym;
sym = symbol_after_dot();
if (sym != null && sym.is_non_term())
return (non_terminal)sym;
else
return null;
}
* 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”);
}
* 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;
}
public boolean equals(lr_item_core other) {return core_equals(other);}
public boolean equals(Object other)
{
if (!(other instanceof lr_item_core))
return false;
else
return equals((lr_item_core)other);
}
public int core_hashCode()
{
return _core_hash_cache;
}
public int hashCode()
{
return _core_hash_cache;
}
* a (nearly) unique id for debugging.
*/
protected int obj_hash()
{
return super.hashCode();
}
* from subclass that overrides toString()).
*/
public String to_simple_string() throws internal_error
{
String result;
production_part part;
_the_production.lhs().the_symbol() != null &&
_the_production.lhs().the_symbol().name() != null)
result = _the_production.lhs().the_symbol().name();
else
result = “$$NULL$$”;
private void Main();
public static void main(String[]) throws internal_error, java.io.IOException, Exception;
protected static void usage(String);
protected static void parse_args(String[]);
protected static void open_files();
protected static void close_files() throws java.io.IOException;
protected static void parse_grammar_spec() throws Exception;
protected static void check_unused();
protected static void build_parser() throws internal_error;
protected static void emit_parser() throws internal_error;
protected static String plural(int);
protected static void emit_summary(boolean);
protected static void show_times();
protected static String timestr(long, long);
public static void dump_grammar() throws internal_error;
public static void dump_machine();
public static void dump_tables();
}
java_cup/Main.java
package java_cup;
import java.io.*;
* It accepts user options and coordinates overall control flow.
* The main flow of control includes the following activities:
*
*
*
*
*
*
*
*
*
*
*
* Options to the main program include:
-
*
- -package name
* - specify package generated classes go in [default none]
* - -parser name
* - specify parser class name [default “parser”]
* - -symbols name
* - specify name for symbol constant class [default “sym”]
* - -interface
* - emit symbol constant interface, rather than class
* - -nonterms
* - put non terminals in symbol constant class
* - -expect #
* - number of conflicts expected/allowed [default 0]
* - -compact_red
* - compact tables by defaulting to most frequent reduce
* - -nowarn
* - don’t warn about useless productions, etc.
* - -nosummary
* - don’t print the usual summary of parse states, etc.
* - -progress
* - print messages to indicate progress of the system
* - -time
* - print time usage summary
* - -dump_grammar
* - produce a dump of the symbols and grammar
* - -dump_states
* - produce a dump of parse state machine
* - -dump_tables
* - produce a dump of the parse tables
* - -dump
* - produce a dump of all of the above
* - -debug
* - turn on debugging messages within JavaCup
* - -nopositions
* - don’t generate the positions code
* - -noscanner
* - don’t refer to java_cup.runtime.Scanner in the parser
* (for compatibility with old runtimes)
* - -version
* - print version information for JavaCUP and halt.
*
*
* @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
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:
-
*
- Computing nullability of non-terminals.
* - Computing first sets of non-terminals and productions.
* - Building the viable prefix recognizer machine.
* - Filling in the (internal) parse tables.
* - Checking for unreduced productions.
*
*/
protected static void build_parser() throws internal_error
{
/* compute nullability of all non terminals */
if (opt_do_debug || print_progress)
System.err.println(” Computing non-terminal nullability…”);
non_terminal.compute_nullability();
nullability_end = System.currentTimeMillis();
/* compute first sets of all non terminals */
if (opt_do_debug || print_progress)
System.err.println(” Computing first sets…”);
non_terminal.compute_first_sets();
first_end = System.currentTimeMillis();
/* build the LR viable prefix recognition machine */
if (opt_do_debug || print_progress)
System.err.println(” Building state machine…”);
start_state = lalr_state.build_machine(emit.start_production);
machine_end = System.currentTimeMillis();
/* build the LR parser action and reduce-goto tables */
if (opt_do_debug || print_progress)
System.err.println(” Filling in tables…”);
action_table = new parse_action_table();
reduce_table = new parse_reduce_table();
for (Enumeration st = lalr_state.all(); st.hasMoreElements(); )
{
lalr_state lst = (lalr_state)st.nextElement();
lst.build_table_entries(
action_table, reduce_table);
}
table_end = System.currentTimeMillis();
/* check and warn for non-reduced productions */
if (opt_do_debug || print_progress)
System.err.println(” Checking for non-reduced productions…”);
action_table.check_reductions();
reduce_check_end = System.currentTimeMillis();
/* if we have more conflicts than we expected issue a message and die */
if (emit.num_conflicts > expect_conflicts)
{
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
Appendix C: Incompatibilites between CUP 0.9 and CUP 0.10
CUP version 0.10a is a major overhaul of CUP. The changes are severe,
meaning no backwards compatibility to older versions.
The changes consist of:
A different lexical interface,
New terminal/non-terminal declarations,
Different label references,
A different way of passing RESULT,
New position values and propagation,
Parser now returns a value,
Terminal precedence declarations and
Rule contextual precedence assignment
Lexical Interface
CUP now interfaces with the lexer in a completely different
manner. In the previous releases, a new class was used for every
distinct type of terminal. This release, however, uses only one class:
The Symbol class. The Symbol class has three instance
variables which
are significant to the parser when passing information from the lexer.
The first is the value instance variable. This variable
contains the
value of that terminal. It is of the type declared as the terminal type
in the parser specification file. The second two are the instance
variables left and right. They should be filled with
the int value of
where in the input file, character-wise, that terminal was found.
For more information, refer to the manual on scanners.
Terminal/Non-Terminal Declarations
Terminal and non-terminal declarations now can be declared in two
different ways to indicate the values of the terminals or
non-terminals. The previous declarations of the form
terminal classname terminal [, terminal …];
still works. The classname, however indicates the type of the value of
the terminal or non-terminal, and does not indicate the type of object
placed on the parse stack.
A declaration, such as:
terminal terminal [, terminal …];
indicates the terminals in the list hold no value.
For more information, refer to the manual on declarations.
Label References
Label references do not refer to the object on the parse stack, as in
the old CUP, but rather to the value of the value
instance variable of
the Symbol that represents that terminal or non-terminal. Hence,
references to terminal and non-terminal values is direct, as opposed to
the old CUP, where the labels referred to objects containing the value
of the terminal or non-terminal.
For more information, refer to the manual on labels.
RESULT Value
The RESULT variable refers directly to the value of the
non-terminal
to which a rule reduces, rather than to the object on the parse stack.
Hence, RESULT is of the same type the non-terminal to which
it reduces,
as declared in the non-terminal declaration. Again, the reference is
direct, rather than to something that will contain the data.
For more information, refer to the manual on RESULT.
Position Propagation
For every label, two more variables are declared, which are the label
plus left or the label plus right. These correspond
to the left and
right locations in the input stream to which that terminal or
non-terminal came from. These values are propagated from the input
terminals, so that the starting non-terminal should have a left value of
0 and a right value of the location of the last character read.
For more information, refer to the manual on positions.
Return Value
A call to parse() or debug_parse() returns a
Symbol. This Symbol is the start non-terminal, so the value
instance variable contains the final RESULT assignment.
Precedence
CUP now has precedenced terminals. a new declaration section,
occurring between the terminal and non-terminal declarations and the
grammar specifies the precedence and associativity of rules. The
declarations are of the form:
precedence {left| right | nonassoc} terminal[, terminal …];
…
The terminals are assigned a precedence, where terminals on the same
line have equal precedences, and the precedence declarations farther
down the list of precedence declarations have higher precedence.
left, right and nonassoc specify the associativity
of these terminals. left
associativity corresponds to a reduce on conflict, right to a shift on
conflict, and nonassoc to an error on conflict. Hence, ambiguous
grammars may now be used.
For more information, refer to the manual on precedence.
Contextual Precedence
Finally the new CUP adds contextual precedence. A production may be
declare as followed:
lhs ::= {right hand side list of terminals, non-terminals and actions}
%prec {terminal};
this production would then have a precedence equal to the terminal
specified after the %prec. Hence, shift/reduce conflicts can be
contextually resolved. Note that the %prec terminal
part comes after all actions strings. It does not come before the
last action string.
For more information, refer to the manual on contextual
precedence.
These changes implemented by:
Frank Flannery
Department of Computer Science
Princeton University
Appendix D: Bugs
In this version of CUP it’s difficult for the semantic action phrases (Java code attached
to productions) to access the report_error method and other similar methods and
objects defined in the parser code directive.
This is because the parsing tables (and parsing engine) are in one object (belonging to
class parser or whatever name is specified by the -parser directive),
and the semantic actions are in another object (of class CUP$actions).
However, there is a way to do it, though it’s a bit inelegant.
The action object has a private final field named
parser that points to the parsing object. Thus,
methods and instance variables of the parser can be accessed within semantic actions as:
parser.report_error(message,info);
x = parser.mydata;
Perhaps this will not be necessary in a future release, and that
such methods and variables as report_error and
mydata will be available
directly from the semantic actions; we will achieve this by combining the
“parser” object and the “actions” object together.
For a list of any other currently known bugs in CUP, see
http://www.cs.princeton.edu/~appel/modern/java/CUP/bugs.html.
Appendix E: Change log
0.9e
March 1996, Scott Hudson’s original version.
0.10a
August 1996, several major changes to
the interface.
0.10b
November 1996, fixes a few minor bugs.
0.10c
July 1997, fixes a bug related to precedence declarations.
0.10e
September 1997, fixes a bug introduced in 0.10c relating
to nonassoc precedence. Thanks to
Tony Hosking
for reporting the bug and providing the fix.
Also recognizes carriage-return character as white space and fixes a
number of other small bugs.
0.10f
December 1997, was a maintenance release. The CUP source
was cleaned up for JDK 1.1.
0.10g
March 1998, adds new features and fixes old bugs.
The behavior of RESULT assignments was normalized, and a problem
with implicit start productions was fixed. The CUP grammar was
extended to allow array types for terminals and non-terminals, and
a command-line flag was added to allow the generation of a symbol
interface, rather than class. Bugs associated with multiple
invocations of a single parser object and multiple CUP classes in one
package have been stomped on. Documentation was updated, as well.
0.10h-0.10i
February 1999, are maintenance releases.
0.10j
July 1999, broadened the CUP input grammar to allow more
flexibility and improved scanner integration via the
java_cup.runtime.Scanner interface.
Java and HotJava are
trademarks of Sun Microsystems, Inc.,
and refer to Sun’s Java programming language and HotJava browser
technologies.
CUP is not sponsored by or affiliated with Sun Microsystems, Inc.
nonassoc_action
package java_cup;
public synchronized class nonassoc_action extends parse_action {
public void nonassoc_action() throws internal_error;
public int kind();
public boolean equals(parse_action);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/nonassoc_action.java
java_cup/nonassoc_action.java
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”;
}
/*———————————————————–*/
}
non_terminal
package java_cup;
public synchronized class non_terminal extends symbol {
protected static java.util.Hashtable _all;
protected static java.util.Hashtable _all_by_index;
protected static int next_index;
protected static int next_nt;
public static final non_terminal START_nt;
public boolean is_embedded_action;
protected java.util.Hashtable _productions;
protected boolean _nullable;
protected terminal_set _first_set;
static void
public void non_terminal(String, String);
public void non_terminal(String);
public static java.util.Enumeration all();
public static non_terminal find(String);
public static non_terminal find(int);
public static int number();
static non_terminal create_new(String) throws internal_error;
static non_terminal create_new() throws internal_error;
public static void compute_nullability() throws internal_error;
public static void compute_first_sets() throws internal_error;
public java.util.Enumeration productions();
public int num_productions();
public void add_production(production) throws internal_error;
public boolean nullable();
public terminal_set first_set();
public boolean is_non_term();
protected boolean looks_nullable() throws internal_error;
public String toString();
}
java_cup/non_terminal.java
java_cup/non_terminal.javapackage 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() ? “*” : “”);
}
/*———————————————————–*/
}
parser
package java_cup;
public synchronized class parser extends runtime.lr_parser {
protected static final short[][] _production_table;
protected static final short[][] _action_table;
protected static final short[][] _reduce_table;
protected CUP$parser$actions action_obj;
static void
public void parser();
public void parser(runtime.Scanner);
public short[][] production_table();
public short[][] action_table();
public short[][] reduce_table();
protected void init_actions();
public runtime.Symbol do_action(int, runtime.lr_parser, java.util.Stack, int) throws Exception;
public int start_state();
public int start_production();
public int EOF_sym();
public int error_sym();
public void user_init() throws Exception;
public runtime.Symbol scan() throws Exception;
public void report_fatal_error(String, Object);
public void report_error(String, Object);
}
/*================================================================*/
/*
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 */;
/*—————————————————————-*/
java_cup/parser.java
java_cup/parser.java
//—————————————————-
// 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;}
/** reduce_goto
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 reduce_goto
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;}
/** EOF
Symbol index. */
public int EOF_sym() {return 0;}
/** error
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”);
}
}
}
parse_action
package java_cup;
public synchronized class parse_action {
public static final int ERROR = 0;
public static final int SHIFT = 1;
public static final int REDUCE = 2;
public static final int NONASSOC = 3;
public void parse_action();
public int kind();
public boolean equals(parse_action);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/parse_action.java
java_cup/parse_action.java
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”;}
/*———————————————————–*/
}
parse_action_row
package java_cup;
public synchronized class parse_action_row {
protected static int _size;
protected static int[] reduction_count;
public parse_action[] under_term;
public int default_reduce;
static void
public void parse_action_row();
public static int size();
public void compute_default();
}
java_cup/parse_action_row.java
java_cup/parse_action_row.java
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;
}
/*———————————————————–*/
}
parse_action_table
package java_cup;
public synchronized class parse_action_table {
protected int _num_states;
public parse_action_row[] under_state;
public void parse_action_table();
public int num_states();
public void check_reductions() throws internal_error;
public String toString();
}
java_cup/parse_action_table.java
java_cup/parse_action_table.java
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;
}
/*-----------------------------------------------------------*/
}
parse_reduce_row
package java_cup;
public synchronized class parse_reduce_row {
protected static int _size;
public lalr_state[] under_non_term;
static void
public void parse_reduce_row();
public static int size();
}
java_cup/parse_reduce_row.java
java_cup/parse_reduce_row.java
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[];
}
parse_reduce_table
package java_cup;
public synchronized class parse_reduce_table {
protected int _num_states;
public parse_reduce_row[] under_state;
public void parse_reduce_table();
public int num_states();
public String toString();
}
java_cup/parse_reduce_table.java
java_cup/parse_reduce_table.java
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;
}
/*———————————————————–*/
}
production
package java_cup;
public synchronized class production {
protected static java.util.Hashtable _all;
protected static int next_index;
protected symbol_part _lhs;
protected int _rhs_prec;
protected int _rhs_assoc;
protected production_part[] _rhs;
protected int _rhs_length;
protected action_part _action;
protected int _index;
protected int _num_reductions;
protected boolean _nullable_known;
protected boolean _nullable;
protected terminal_set _first_set;
static void
public void production(non_terminal, production_part[], int, String) throws internal_error;
public void production(non_terminal, production_part[], int) throws internal_error;
public void production(non_terminal, production_part[], int, String, int, int) throws internal_error;
public void production(non_terminal, production_part[], int, int, int) throws internal_error;
public static java.util.Enumeration all();
public static production find(int);
public static int number();
public symbol_part lhs();
public int precedence_num();
public int precedence_side();
public void set_precedence_num(int);
public void set_precedence_side(int);
public production_part rhs(int) throws internal_error;
public int rhs_length();
public action_part action();
public int index();
public int num_reductions();
public void note_reduction_use();
public boolean nullable_known();
public boolean nullable();
public terminal_set first_set();
protected static boolean is_id_start(char);
protected static boolean is_id_char(char);
protected String make_declaration(String, String, int);
protected String declare_labels(production_part[], int, String);
protected int merge_adjacent_actions(production_part[], int);
protected action_part strip_trailing_action(production_part[], int);
protected void remove_embedded_actions() throws internal_error;
public boolean check_nullable() throws internal_error;
boolean set_nullable(boolean);
public terminal_set check_first_set() throws internal_error;
public boolean equals(production);
public boolean equals(Object);
public int hashCode();
public String toString();
public String to_simple_string() throws internal_error;
}
java_cup/production.java
java_cup/production.java
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.
*
* 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.
*
* Factoring out of actions is accomplished by creating new “hidden”
* non terminals. For example if the production was originally:
* A ::= B {action} C D *
* then it is factored into two productions:
* A ::= B X C D * X ::= {action} *
* (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 * then it will be factored into: * where NT$1 and NT$2 are new system created non terminals. /* the declarations added to the parent production are also passed along, /*———————————————————–*/ /*———————————————————–*/ /** Optional label for referring to the part within an action (null for /*———————————————————–*/ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality comparison. */ /* compare the labels */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Generic equality comparison. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Produce a hash code. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Convert to a string. */ /*———————————————————–*/ } This directory contains the CUP v0.10k release in source form. You should README This file. To get started quickly, read INSTALL.QUICK. If you are on a Windows To install the release, copy the contents of this directory (if you Once files have been copied to an appropriate location, you should be able to A manual page that explains the operation and use of the system can be found Bug reports regarding the installation The CUP home page where the latest information regarding CUP can be found http://www.cs.princeton.edu/~appel/modern/java/CUP/ Enjoy, Scott Hudson Last updated: 23-Jul-1999 [CSA] reduce_action package java_cup; java_cup/reduce_action.java /** This class represents a reduce action within the parse table. /** Simple constructor. _reduce_with = prod; /*———————————————————–*/ /** The production we reduce with. */ /*———————————————————–*/ /** Quick access to type of action. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality test. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Generic equality test. */ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Compute a hash code. */ /** Convert to string. */ /*———————————————————–*/ } lr_parser package java_cup.runtime; java_cup/runtime/lr_parser.java import java.util.Stack; /** This class implements a skeleton table driven LR parser. In general,
*
*
*
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
* A ::= B NT$1 C NT$2 D
* NT$1 ::= {action1}
* NT$2 ::= {action2}
*
*/
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
* 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;
* 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();
public boolean equals(production_part other)
{
if (other == null) return false;
if (label() != null)
return label().equals(other.label());
else
return other.label() == null;
}
public boolean equals(Object other)
{
if (!(other instanceof production_part))
return false;
else
return equals((production_part)other);
}
public int hashCode()
{
return label()==null ? 0 : label().hashCode();
}
public String toString()
{
if (label() != null)
return label() + “:”;
else
return ” “;
}
find the following files and subdirectories in this release:
INSTALL.QUICK Quick installation instruction.
CHANGELOG A brief overview of the changes in v0.10k
java_cup A subdirectory containing CUP, runtime, and test sources.
cup_logo.gif A logo image used by the manual.
manual.html A user’s manual in HTML format. (OLD)
INSTALL A shell script to install and test the system
platform, you might want to look in the winnt subdirectory.
For complete installation information, keep reading.
haven’t done so already) into a “classes” directory accessible to the
java interpreter (i.e., a directory that is listed in the colon
separated list of directories in your CLASSPATH environment variable).
Note: if you have an older version of the system already accessible
from your CLASSPATH you will want to temporarily remove it to avoid
conflicts.
both compile and test the system by executing the INSTALL shell script
(sorry, but non Unix users are still on their own). Again, be sure that
you have placed these sources in a directory listed in your CLASSPATH
environment variable (or changed your CLASSPATH to include this directory).
in manual.html and from the CUP home page mentioned below.
process or the system as a whole should be sent to
(e.g., new releases) is:
Graphics, Visualization, and Usability Center
Georgia Institute of Technology
public synchronized class reduce_action extends parse_action {
protected production _reduce_with;
public void reduce_action(production) throws internal_error;
public production reduce_with();
public int kind();
public boolean equals(reduce_action);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/reduce_action.java
package java_cup;
* 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) —————————————-*/
/*———————————————————–*/
* @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”);
}
/*— (Access to) Instance Variables ————————*/
/*———————————————————–*/
/** The production we reduce with. */
protected production _reduce_with;
public production reduce_with() {return _reduce_with;}
/*— General Methods —————————————*/
/*———————————————————–*/
public int kind() {return REDUCE;}
public boolean equals(reduce_action other)
{
return other != null && other.reduce_with() == reduce_with();
}
public boolean equals(Object other)
{
if (other instanceof reduce_action)
return equals((reduce_action)other);
else
return false;
}
public int hashCode()
{
/* use the hash code of the production we are reducing with */
return reduce_with().hashCode();
}
public String toString()
{
return “REDUCE(with prod ” + reduce_with().index() + “)”;
}
public abstract synchronized class lr_parser {
protected static final int _error_sync_size = 3;
protected boolean _done_parsing;
protected int tos;
protected Symbol cur_token;
protected java.util.Stack stack;
protected short[][] production_tab;
protected short[][] action_tab;
protected short[][] reduce_tab;
private Scanner _scanner;
protected Symbol[] lookahead;
protected int lookahead_pos;
public void lr_parser();
public void lr_parser(Scanner);
protected int error_sync_size();
public abstract short[][] production_table();
public abstract short[][] action_table();
public abstract short[][] reduce_table();
public abstract int start_state();
public abstract int start_production();
public abstract int EOF_sym();
public abstract int error_sym();
public void done_parsing();
public void setScanner(Scanner);
public Scanner getScanner();
public abstract Symbol do_action(int, lr_parser, java.util.Stack, int) throws Exception;
public void user_init() throws Exception;
protected abstract void init_actions() throws Exception;
public Symbol scan() throws Exception;
public void report_fatal_error(String, Object) throws Exception;
public void report_error(String, Object);
public void syntax_error(Symbol);
public void unrecovered_syntax_error(Symbol) throws Exception;
protected final short get_action(int, int);
protected final short get_reduce(int, int);
public Symbol parse() throws Exception;
public void debug_message(String);
public void dump_stack();
public void debug_reduce(int, int, int);
public void debug_shift(Symbol);
public void debug_stack();
public Symbol debug_parse() throws Exception;
protected boolean error_recovery(boolean) throws Exception;
protected boolean shift_under_error();
protected boolean find_recovery_config(boolean);
protected void read_lookahead() throws Exception;
protected Symbol cur_err_token();
protected boolean advance_lookahead();
protected void restart_lookahead() throws Exception;
protected boolean try_parse_ahead(boolean) throws Exception;
protected void parse_lookahead(boolean) throws Exception;
protected static short[][] unpackFromStrings(String[]);
}
java_cup/runtime/lr_parser.java
package java_cup.runtime;
* LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce
* parsers act by shifting input onto a parse stack until the Symbols
* matching the right hand side of a production appear on the top of the
* stack. Once this occurs, a reduce is performed. This involves removing
* the Symbols corresponding to the right hand side of the production
* (the so called “handle”) and replacing them with the non-terminal from
* the left hand side of the production.
* To control the decision of whether to shift or reduce at any given point,
* the parser uses a state machine (the “viable prefix recognition machine”
* built by the parser generator). The current state of the machine is placed
* on top of the parse stack (stored as part of a Symbol object representing
* a terminal or non terminal). The parse action table is consulted
* (using the current state and the current lookahead Symbol as indexes) to
* determine whether to shift or to reduce. When the parser shifts, it
* changes to a new state by pushing a new Symbol (containing a new state)
* onto the stack. When the parser reduces, it pops the handle (right hand
* side of a production) off the stack. This leaves the parser in the state
* it was in before any of those Symbols were matched. Next the reduce-goto
* table is consulted (using the new state and current lookahead Symbol as
* indexes) to determine a new state to go to. The parser then shifts to
* this goto state by pushing the left hand side Symbol of the production
* (also containing the new state) onto the stack.
* This class actually provides four LR parsers. The methods parse() and
* debug_parse() provide two versions of the main parser (the only difference
* being that debug_parse() emits debugging trace messages as it parses).
* In addition to these main parsers, the error recovery mechanism uses two
* more. One of these is used to simulate “parsing ahead” in the input
* without carrying out actions (to verify that a potential error recovery
* has worked), and the other is used to parse through buffered “parse ahead”
* input in order to execute all actions and re-synchronize the actual parser
* configuration.
* This is an abstract class which is normally filled out by a subclass
* generated by the JavaCup parser generator. In addition to supplying
* the actual parse tables, generated code also supplies methods which
* invoke various pieces of user supplied code, provide access to certain
* special Symbols (e.g., EOF and error), etc. Specifically, the following
* abstract methods are normally supplied by generated code:
*
*
*
* the left hand side non terminal and the length of the right hand side
* for each production in the grammar).
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* the point of a reduce in the parse, so this code also allocates and
* fills in the left hand side non terminal Symbol object that is to be
* pushed onto the stack for the reduce.
*
*
* actions (this object is used by do_action() to actually carry out the
* actions).
*
*
* In addition to these routines that must be supplied by the
* generated subclass there are also a series of routines that may
* be supplied. These include:
*
-
*
- Symbol scan()
* - Used to get the next input Symbol from the scanner.
* - Scanner getScanner()
* - Used to provide a scanner for the default implementation of
* scan().
* - int error_sync_size()
* - This determines how many Symbols past the point of an error
* must be parsed without error in order to consider a recovery to
* be valid. This defaults to 3. Values less than 2 are not
* recommended.
* - void report_error(String message, Object info)
* - This method is called to report an error. The default implementation
* simply prints a message to System.err and where the error occurred.
* This method is often replaced in order to provide a more sophisticated
* error reporting mechanism.
* - void report_fatal_error(String message, Object info)
* - This method is called when a fatal error that cannot be recovered from
* is encountered. In the default implementation, it calls
* report_error() to emit a message, then throws an exception.
* - void syntax_error(Symbol cur_token)
* - This method is called as soon as syntax error is detected (but
* before recovery is attempted). In the default implementation it
* invokes: report_error(“Syntax error”, null);
* - void unrecovered_syntax_error(Symbol cur_token)
* - This method is called if syntax error recovery fails. In the default
* implementation it invokes:
* report_fatal_error(“Couldn’t repair and continue parse”, null);
*
*
* @see java_cup.runtime.Symbol
* @see java_cup.runtime.Symbol
* @see java_cup.runtime.virtual_parse_stack
* @version last updated: 7/3/96
* @author Frank Flannery
*/
public abstract class lr_parser {
/*———————————————————–*/
/*— Constructor(s) —————————————-*/
/*———————————————————–*/
/** Simple constructor. */
public lr_parser()
{
/* nothing to do here */
}
/** Constructor that sets the default scanner. [CSA/davidm] */
public lr_parser(Scanner s) {
this(); /* in case default constructor someday does something */
setScanner(s);
}
/*———————————————————–*/
/*— (Access to) Static (Class) Variables ——————*/
/*———————————————————–*/
/** The default number of Symbols after an error we much match to consider
* it recovered from.
*/
protected final static int _error_sync_size = 3;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The number of Symbols after an error we much match to consider it
* recovered from.
*/
protected int error_sync_size() {return _error_sync_size; }
/*———————————————————–*/
/*— (Access to) Instance Variables ————————*/
/*———————————————————–*/
/** Table of production information (supplied by generated subclass).
* This table contains one entry per production and is indexed by
* the negative-encoded values (reduce actions) in the action_table.
* Each entry has two parts, the index of the non-terminal on the
* left hand side of the production, and the number of Symbols
* on the right hand side.
*/
public abstract short[][] production_table();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The action table (supplied by generated subclass). This table is
* indexed by state and terminal number indicating what action is to
* be taken when the parser is in the given state (i.e., the given state
* is on top of the stack) and the given terminal is next on the input.
* States are indexed using the first dimension, however, the entries for
* a given state are compacted and stored in adjacent index, value pairs
* which are searched for rather than accessed directly (see get_action()).
* The actions stored in the table will be either shifts, reduces, or
* errors. Shifts are encoded as positive values (one greater than the
* state shifted to). Reduces are encoded as negative values (one less
* than the production reduced by). Error entries are denoted by zero.
*
* @see java_cup.runtime.lr_parser#get_action
*/
public abstract short[][] action_table();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The reduce-goto table (supplied by generated subclass). This
* table is indexed by state and non-terminal number and contains
* state numbers. States are indexed using the first dimension, however,
* the entries for a given state are compacted and stored in adjacent
* index, value pairs which are searched for rather than accessed
* directly (see get_reduce()). When a reduce occurs, the handle
* (corresponding to the RHS of the matched production) is popped off
* the stack. The new top of stack indicates a state. This table is
* then indexed by that state and the LHS of the reducing production to
* indicate where to “shift” to.
*
* @see java_cup.runtime.lr_parser#get_reduce
*/
public abstract short[][] reduce_table();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The index of the start state (supplied by generated subclass). */
public abstract int start_state();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The index of the start production (supplied by generated subclass). */
public abstract int start_production();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The index of the end of file terminal Symbol (supplied by generated
* subclass).
*/
public abstract int EOF_sym();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The index of the special error Symbol (supplied by generated subclass). */
public abstract int error_sym();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Internal flag to indicate when parser should quit. */
protected boolean _done_parsing = false;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** This method is called to indicate that the parser should quit. This is
* normally called by an accept action, but can be used to cancel parsing
* early in other circumstances if desired.
*/
public void done_parsing()
{
_done_parsing = true;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/* Global parse state shared by parse(), error recovery, and
* debugging routines */
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Indication of the index for top of stack (for use by actions). */
protected int tos;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The current lookahead Symbol. */
protected Symbol cur_token;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The parse stack itself. */
protected Stack stack = new Stack();
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Direct reference to the production table. */
protected short[][] production_tab;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Direct reference to the action table. */
protected short[][] action_tab;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Direct reference to the reduce-goto table. */
protected short[][] reduce_tab;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** This is the scanner object used by the default implementation
* of scan() to get Symbols. To avoid name conflicts with existing
* code, this field is private. [CSA/davidm] */
private Scanner _scanner;
/**
* Simple accessor method to set the default scanner.
*/
public void setScanner(Scanner s) { _scanner = s; }
/**
* Simple accessor method to get the default scanner.
*/
public Scanner getScanner() { return _scanner; }
/*———————————————————–*/
/*— General Methods —————————————*/
/*———————————————————–*/
/** Perform a bit of user supplied action code (supplied by generated
* subclass). Actions are indexed by an internal action number assigned
* at parser generation time.
*
* @param act_num the internal index of the action to be performed.
* @param parser the parser object we are acting for.
* @param stack the parse stack of that object.
* @param top the index of the top element of the parse stack.
*/
public abstract Symbol do_action(
int act_num,
lr_parser parser,
Stack stack,
int top)
throws java.lang.Exception;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** User code for initialization inside the parser. Typically this
* initializes the scanner. This is called before the parser requests
* the first Symbol. Here this is just a placeholder for subclasses that
* might need this and we perform no action. This method is normally
* overridden by the generated code using this contents of the “init with”
* clause as its body.
*/
public void user_init() throws java.lang.Exception { }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Initialize the action object. This is called before the parser does
* any parse actions. This is filled in by generated code to create
* an object that encapsulates all action code.
*/
protected abstract void init_actions() throws java.lang.Exception;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Get the next Symbol from the input (supplied by generated subclass).
* Once end of file has been reached, all subsequent calls to scan
* should return an EOF Symbol (which is Symbol number 0). By default
* this method returns getScanner().next_token(); this implementation
* can be overriden by the generated parser using the code declared in
* the “scan with” clause. Do not recycle objects; every call to
* scan() should return a fresh object.
*/
public Symbol scan() throws java.lang.Exception {
Symbol sym = getScanner().next_token();
return (sym!=null) ? sym : new Symbol(EOF_sym());
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Report a fatal error. This method takes a message string and an
* additional object (to be used by specializations implemented in
* subclasses). Here in the base class a very simple implementation
* is provided which reports the error then throws an exception.
*
* @param message an error message.
* @param info an extra object reserved for use by specialized subclasses.
*/
public void report_fatal_error(
String message,
Object info)
throws java.lang.Exception
{
/* stop parsing (not really necessary since we throw an exception, but) */
done_parsing();
/* use the normal error message reporting to put out the message */
report_error(message, info);
/* throw an exception */
throw new Exception(“Can’t recover from previous error(s)”);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Report a non fatal error (or warning). This method takes a message
* string and an additional object (to be used by specializations
* implemented in subclasses). Here in the base class a very simple
* implementation is provided which simply prints the message to
* System.err.
*
* @param message an error message.
* @param info an extra object reserved for use by specialized subclasses.
*/
public void report_error(String message, Object info)
{
System.err.print(message);
if (info instanceof Symbol)
if (((Symbol)info).left != -1)
System.err.println(” at character ” + ((Symbol)info).left +
” of input”);
else System.err.println(“”);
else System.err.println(“”);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** This method is called when a syntax error has been detected and recovery
* is about to be invoked. Here in the base class we just emit a
* “Syntax error” error message.
*
* @param cur_token the current lookahead Symbol.
*/
public void syntax_error(Symbol cur_token)
{
report_error(“Syntax error”, cur_token);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** This method is called if it is determined that syntax error recovery
* has been unsuccessful. Here in the base class we report a fatal error.
*
* @param cur_token the current lookahead Symbol.
*/
public void unrecovered_syntax_error(Symbol cur_token)
throws java.lang.Exception
{
report_fatal_error(“Couldn’t repair and continue parse”, cur_token);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Fetch an action from the action table. The table is broken up into
* rows, one per state (rows are indexed directly by state number).
* Within each row, a list of index, value pairs are given (as sequential
* entries in the table), and the list is terminated by a default entry
* (denoted with a Symbol index of -1). To find the proper entry in a row
* we do a linear or binary search (depending on the size of the row).
*
* @param state the state index of the action being accessed.
* @param sym the Symbol index of the action being accessed.
*/
protected final short get_action(int state, int sym)
{
short tag;
int first, last, probe;
short[] row = action_tab[state];
/* linear search if we are < 10 entries */
if (row.length < 20)
for (probe = 0; probe < row.length; probe++)
{
/* is this entry labeled with our Symbol or the default? */
tag = row[probe++];
if (tag == sym || tag == -1)
{
/* return the next entry */
return row[probe];
}
}
/* otherwise binary search */
else
{
first = 0;
last = (row.length-1)/2 - 1; /* leave out trailing default entry */
while (first <= last)
{
probe = (first+last)/2;
if (sym == row[probe*2])
return row[probe*2+1];
else if (sym > row[probe*2])
first = probe+1;
else
last = probe-1;
}
/* not found, use the default at the end */
return row[row.length-1];
}
/* shouldn’t happened, but if we run off the end we return the
default (error == 0) */
return 0;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Fetch a state from the reduce-goto table. The table is broken up into
* rows, one per state (rows are indexed directly by state number).
* Within each row, a list of index, value pairs are given (as sequential
* entries in the table), and the list is terminated by a default entry
* (denoted with a Symbol index of -1). To find the proper entry in a row
* we do a linear search.
*
* @param state the state index of the entry being accessed.
* @param sym the Symbol index of the entry being accessed.
*/
protected final short get_reduce(int state, int sym)
{
short tag;
short[] row = reduce_tab[state];
/* if we have a null row we go with the default */
if (row == null)
return -1;
for (int probe = 0; probe < row.length; probe++)
{
/* is this entry labeled with our Symbol or the default? */
tag = row[probe++];
if (tag == sym || tag == -1)
{
/* return the next entry */
return row[probe];
}
}
/* if we run off the end we return the default (error == -1) */
return -1;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** This method provides the main parsing routine. It returns only when
* done_parsing() has been called (typically because the parser has
* accepted, or a fatal error has been reported). See the header
* documentation for the class regarding how shift/reduce parsers operate
* and how the various tables are used.
*/
public Symbol parse() throws java.lang.Exception
{
/* the current action code */
int act;
/* the Symbol/stack element returned by a reduce */
Symbol lhs_sym = null;
/* information about production being reduced with */
short handle_size, lhs_sym_num;
/* set up direct reference to tables to drive the parser */
production_tab = production_table();
action_tab = action_table();
reduce_tab = reduce_table();
/* initialize the action encapsulation object */
init_actions();
/* do user initialization */
user_init();
/* get the first token */
cur_token = scan();
/* push dummy Symbol with start state to get us underway */
stack.removeAllElements();
stack.push(new Symbol(0, start_state()));
tos = 0;
/* continue until we are told to stop */
for (_done_parsing = false; !_done_parsing; )
{
/* Check current token for freshness. */
if (cur_token.used_by_parser)
throw new Error("Symbol recycling detected (fix your scanner).");
/* current state is always on the top of the stack */
/* look up action out of the current state with the current input */
act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
/* decode the action -- > 0 encodes shift */
if (act > 0)
{
/* shift to the encoded state by pushing it on the stack */
cur_token.parse_state = act-1;
cur_token.used_by_parser = true;
stack.push(cur_token);
tos++;
/* advance to the next Symbol */
cur_token = scan();
}
/* if its less than zero, then it encodes a reduce action */
else if (act < 0)
{
/* perform the action for the reduce */
lhs_sym = do_action((-act)-1, this, stack, tos);
/* look up information about the production */
lhs_sym_num = production_tab[(-act)-1][0];
handle_size = production_tab[(-act)-1][1];
/* pop the handle off the stack */
for (int i = 0; i < handle_size; i++)
{
stack.pop();
tos--;
}
/* look up the state to go to from the one popped back to */
act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
/* shift to that state */
lhs_sym.parse_state = act;
lhs_sym.used_by_parser = true;
stack.push(lhs_sym);
tos++;
}
/* finally if the entry is zero, we have an error */
else if (act == 0)
{
/* call user syntax error reporting routine */
syntax_error(cur_token);
/* try to error recover */
if (!error_recovery(false))
{
/* if that fails give up with a fatal syntax error */
unrecovered_syntax_error(cur_token);
/* just in case that wasn't fatal enough, end parse */
done_parsing();
} else {
lhs_sym = (Symbol)stack.peek();
}
}
}
return lhs_sym;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Write a debugging message to System.err for the debugging version
* of the parser.
*
* @param mess the text of the debugging message.
*/
public void debug_message(String mess)
{
System.err.println(mess);
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Dump the parse stack for debugging purposes. */
public void dump_stack()
{
if (stack == null)
{
debug_message("# Stack dump requested, but stack is null");
return;
}
debug_message("============ Parse Stack Dump ============");
/* dump the stack */
for (int i=0; i
if ((i%3)==2 || (i==(stack.size()-1))) {
debug_message(sb.toString());
sb = new StringBuffer(” “);
}
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Perform a parse with debugging output. This does exactly the
* same things as parse(), except that it calls debug_shift() and
* debug_reduce() when shift and reduce moves are taken by the parser
* and produces various other debugging messages.
*/
public Symbol debug_parse()
throws java.lang.Exception
{
/* the current action code */
int act;
/* the Symbol/stack element returned by a reduce */
Symbol lhs_sym = null;
/* information about production being reduced with */
short handle_size, lhs_sym_num;
/* set up direct reference to tables to drive the parser */
production_tab = production_table();
action_tab = action_table();
reduce_tab = reduce_table();
debug_message(“# Initializing parser”);
/* initialize the action encapsulation object */
init_actions();
/* do user initialization */
user_init();
/* the current Symbol */
cur_token = scan();
debug_message(“# Current Symbol is #” + cur_token.sym);
/* push dummy Symbol with start state to get us underway */
stack.removeAllElements();
stack.push(new Symbol(0, start_state()));
tos = 0;
/* continue until we are told to stop */
for (_done_parsing = false; !_done_parsing; )
{
/* Check current token for freshness. */
if (cur_token.used_by_parser)
throw new Error(“Symbol recycling detected (fix your scanner).”);
/* current state is always on the top of the stack */
//debug_stack();
/* look up action out of the current state with the current input */
act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym);
/* decode the action — > 0 encodes shift */
if (act > 0)
{
/* shift to the encoded state by pushing it on the stack */
cur_token.parse_state = act-1;
cur_token.used_by_parser = true;
debug_shift(cur_token);
stack.push(cur_token);
tos++;
/* advance to the next Symbol */
cur_token = scan();
debug_message(“# Current token is ” + cur_token);
}
/* if its less than zero, then it encodes a reduce action */
else if (act < 0)
{
/* perform the action for the reduce */
lhs_sym = do_action((-act)-1, this, stack, tos);
/* look up information about the production */
lhs_sym_num = production_tab[(-act)-1][0];
handle_size = production_tab[(-act)-1][1];
debug_reduce((-act)-1, lhs_sym_num, handle_size);
/* pop the handle off the stack */
for (int i = 0; i < handle_size; i++)
{
stack.pop();
tos--;
}
/* look up the state to go to from the one popped back to */
act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
debug_message("# Reduce rule: top state " +
((Symbol)stack.peek()).parse_state +
", lhs sym " + lhs_sym_num + " -> state ” + act);
/* shift to that state */
lhs_sym.parse_state = act;
lhs_sym.used_by_parser = true;
stack.push(lhs_sym);
tos++;
debug_message(“# Goto state #” + act);
}
/* finally if the entry is zero, we have an error */
else if (act == 0)
{
/* call user syntax error reporting routine */
syntax_error(cur_token);
/* try to error recover */
if (!error_recovery(true))
{
/* if that fails give up with a fatal syntax error */
unrecovered_syntax_error(cur_token);
/* just in case that wasn’t fatal enough, end parse */
done_parsing();
} else {
lhs_sym = (Symbol)stack.peek();
}
}
}
return lhs_sym;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/* Error recovery code */
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Attempt to recover from a syntax error. This returns false if recovery
* fails, true if it succeeds. Recovery happens in 4 steps. First we
* pop the parse stack down to a point at which we have a shift out
* of the top-most state on the error Symbol. This represents the
* initial error recovery configuration. If no such configuration is
* found, then we fail. Next a small number of “lookahead” or “parse
* ahead” Symbols are read into a buffer. The size of this buffer is
* determined by error_sync_size() and determines how many Symbols beyond
* the error must be matched to consider the recovery a success. Next,
* we begin to discard Symbols in attempt to get past the point of error
* to a point where we can continue parsing. After each Symbol, we attempt
* to “parse ahead” though the buffered lookahead Symbols. The “parse ahead”
* process simulates that actual parse, but does not modify the real
* parser’s configuration, nor execute any actions. If we can parse all
* the stored Symbols without error, then the recovery is considered a
* success. Once a successful recovery point is determined, we do an
* actual parse over the stored input — modifying the real parse
* configuration and executing all actions. Finally, we return the the
* normal parser to continue with the overall parse.
*
* @param debug should we produce debugging messages as we parse.
*/
protected boolean error_recovery(boolean debug)
throws java.lang.Exception
{
if (debug) debug_message(“# Attempting error recovery”);
/* first pop the stack back into a state that can shift on error and
do that shift (if that fails, we fail) */
if (!find_recovery_config(debug))
{
if (debug) debug_message(“# Error recovery fails”);
return false;
}
/* read ahead to create lookahead we can parse multiple times */
read_lookahead();
/* repeatedly try to parse forward until we make it the required dist */
for (;;)
{
/* try to parse forward, if it makes it, bail out of loop */
if (debug) debug_message(“# Trying to parse ahead”);
if (try_parse_ahead(debug))
{
break;
}
/* if we are now at EOF, we have failed */
if (lookahead[0].sym == EOF_sym())
{
if (debug) debug_message(“# Error recovery fails at EOF”);
return false;
}
/* otherwise, we consume another Symbol and try again */
// BUG FIX by Bruce Hutton
// Computer Science Department, University of Auckland,
// Auckland, New Zealand.
// It is the first token that is being consumed, not the one
// we were up to parsing
if (debug)
debug_message(“# Consuming Symbol #” + lookahead[ 0 ].sym);
restart_lookahead();
}
/* we have consumed to a point where we can parse forward */
if (debug) debug_message(“# Parse-ahead ok, going back to normal parse”);
/* do the real parse (including actions) across the lookahead */
parse_lookahead(debug);
/* we have success */
return true;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Determine if we can shift under the special error Symbol out of the
* state currently on the top of the (real) parse stack.
*/
protected boolean shift_under_error()
{
/* is there a shift under error Symbol */
return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Put the (real) parse stack into error recovery configuration by
* popping the stack down to a state that can shift on the special
* error Symbol, then doing the shift. If no suitable state exists on
* the stack we return false
*
* @param debug should we produce debugging messages as we parse.
*/
protected boolean find_recovery_config(boolean debug)
{
Symbol error_token;
int act;
if (debug) debug_message(“# Finding recovery state on stack”);
/* Remember the right-position of the top symbol on the stack */
int right_pos = ((Symbol)stack.peek()).right;
int left_pos = ((Symbol)stack.peek()).left;
/* pop down until we can shift under error Symbol */
while (!shift_under_error())
{
/* pop the stack */
if (debug)
debug_message(“# Pop stack by one, state was # ” +
((Symbol)stack.peek()).parse_state);
left_pos = ((Symbol)stack.pop()).left;
tos–;
/* if we have hit bottom, we fail */
if (stack.empty())
{
if (debug) debug_message(“# No recovery state found on stack”);
return false;
}
}
/* state on top of the stack can shift under error, find the shift */
act = get_action(((Symbol)stack.peek()).parse_state, error_sym());
if (debug)
{
debug_message(“# Recover state found (#” +
((Symbol)stack.peek()).parse_state + “)”);
debug_message(“# Shifting on error to state #” + (act-1));
}
/* build and shift a special error Symbol */
error_token = new Symbol(error_sym(), left_pos, right_pos);
error_token.parse_state = act-1;
error_token.used_by_parser = true;
stack.push(error_token);
tos++;
return true;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Lookahead Symbols used for attempting error recovery “parse aheads”. */
protected Symbol lookahead[];
/** Position in lookahead input buffer used for “parse ahead”. */
protected int lookahead_pos;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Read from input to establish our buffer of “parse ahead” lookahead
* Symbols.
*/
protected void read_lookahead() throws java.lang.Exception
{
/* create the lookahead array */
lookahead = new Symbol[error_sync_size()];
/* fill in the array */
for (int i = 0; i < error_sync_size(); i++)
{
lookahead[i] = cur_token;
cur_token = scan();
}
/* start at the beginning */
lookahead_pos = 0;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Return the current lookahead in our error "parse ahead" buffer. */
protected Symbol cur_err_token() { return lookahead[lookahead_pos]; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Advance to next "parse ahead" input Symbol. Return true if we have
* input to advance to, false otherwise.
*/
protected boolean advance_lookahead()
{
/* advance the input location */
lookahead_pos++;
/* return true if we didn't go off the end */
return lookahead_pos < error_sync_size();
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Reset the parse ahead input to one Symbol past where we started error
* recovery (this consumes one new Symbol from the real input).
*/
protected void restart_lookahead() throws java.lang.Exception
{
/* move all the existing input over */
for (int i = 1; i < error_sync_size(); i++)
lookahead[i-1] = lookahead[i];
/* read a new Symbol into the last spot */
// BUG Fix by Bruce Hutton
// Computer Science Department, University of Auckland,
// Auckland, New Zealand. [applied 5-sep-1999 by csa]
// The following two lines were out of order!!
lookahead[error_sync_size()-1] = cur_token;
cur_token = scan();
/* reset our internal position marker */
lookahead_pos = 0;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Do a simulated parse forward (a "parse ahead") from the current
* stack configuration using stored lookahead input and a virtual parse
* stack. Return true if we make it all the way through the stored
* lookahead input without error. This basically simulates the action of
* parse() using only our saved "parse ahead" input, and not executing any
* actions.
*
* @param debug should we produce debugging messages as we parse.
*/
protected boolean try_parse_ahead(boolean debug)
throws java.lang.Exception
{
int act;
short lhs, rhs_size;
/* create a virtual stack from the real parse stack */
virtual_parse_stack vstack = new virtual_parse_stack(stack);
/* parse until we fail or get past the lookahead input */
for (;;)
{
/* look up the action from the current state (on top of stack) */
act = get_action(vstack.top(), cur_err_token().sym);
/* if its an error, we fail */
if (act == 0) return false;
/* > 0 encodes a shift */
if (act > 0)
{
/* push the new state on the stack */
vstack.push(act-1);
if (debug) debug_message(“# Parse-ahead shifts Symbol #” +
cur_err_token().sym + ” into state #” + (act-1));
/* advance simulated input, if we run off the end, we are done */
if (!advance_lookahead()) return true;
}
/* < 0 encodes a reduce */
else
{
/* if this is a reduce with the start production we are done */
if ((-act)-1 == start_production())
{
if (debug) debug_message("# Parse-ahead accepts");
return true;
}
/* get the lhs Symbol and the rhs size */
lhs = production_tab[(-act)-1][0];
rhs_size = production_tab[(-act)-1][1];
/* pop handle off the stack */
for (int i = 0; i < rhs_size; i++)
vstack.pop();
if (debug)
debug_message("# Parse-ahead reduces: handle size = " +
rhs_size + " lhs = #" + lhs + " from state #" + vstack.top());
/* look up goto and push it onto the stack */
vstack.push(get_reduce(vstack.top(), lhs));
if (debug)
debug_message("# Goto state #" + vstack.top());
}
}
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Parse forward using stored lookahead Symbols. In this case we have
* already verified that parsing will make it through the stored lookahead
* Symbols and we are now getting back to the point at which we can hand
* control back to the normal parser. Consequently, this version of the
* parser performs all actions and modifies the real parse configuration.
* This returns once we have consumed all the stored input or we accept.
*
* @param debug should we produce debugging messages as we parse.
*/
protected void parse_lookahead(boolean debug)
throws java.lang.Exception
{
/* the current action code */
int act;
/* the Symbol/stack element returned by a reduce */
Symbol lhs_sym = null;
/* information about production being reduced with */
short handle_size, lhs_sym_num;
/* restart the saved input at the beginning */
lookahead_pos = 0;
if (debug)
{
debug_message("# Reparsing saved input with actions");
debug_message("# Current Symbol is #" + cur_err_token().sym);
debug_message("# Current state is #" +
((Symbol)stack.peek()).parse_state);
}
/* continue until we accept or have read all lookahead input */
while(!_done_parsing)
{
/* current state is always on the top of the stack */
/* look up action out of the current state with the current input */
act =
get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym);
/* decode the action -- > 0 encodes shift */
if (act > 0)
{
/* shift to the encoded state by pushing it on the stack */
cur_err_token().parse_state = act-1;
cur_err_token().used_by_parser = true;
if (debug) debug_shift(cur_err_token());
stack.push(cur_err_token());
tos++;
/* advance to the next Symbol, if there is none, we are done */
if (!advance_lookahead())
{
if (debug) debug_message(“# Completed reparse”);
/* scan next Symbol so we can continue parse */
// BUGFIX by Chris Harris
// correct a one-off error by commenting out
// this next line.
/*cur_token = scan();*/
/* go back to normal parser */
return;
}
if (debug)
debug_message(“# Current Symbol is #” + cur_err_token().sym);
}
/* if its less than zero, then it encodes a reduce action */
else if (act < 0)
{
/* perform the action for the reduce */
lhs_sym = do_action((-act)-1, this, stack, tos);
/* look up information about the production */
lhs_sym_num = production_tab[(-act)-1][0];
handle_size = production_tab[(-act)-1][1];
if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size);
/* pop the handle off the stack */
for (int i = 0; i < handle_size; i++)
{
stack.pop();
tos--;
}
/* look up the state to go to from the one popped back to */
act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num);
/* shift to that state */
lhs_sym.parse_state = act;
lhs_sym.used_by_parser = true;
stack.push(lhs_sym);
tos++;
if (debug) debug_message("# Goto state #" + act);
}
/* finally if the entry is zero, we have an error
(shouldn't happen here, but...)*/
else if (act == 0)
{
report_fatal_error("Syntax error", lhs_sym);
return;
}
}
}
/*-----------------------------------------------------------*/
/** Utility function: unpacks parse tables from strings */
protected static short[][] unpackFromStrings(String[] sa)
{
// Concatanate initialization strings.
StringBuffer sb = new StringBuffer(sa[0]);
for (int i=1; i
* of scanners implementing Scanner
is facilitated.
*
* @version last updated 23-Jul-1999
* @author David MacMahon
*/
/* *************************************************
Interface Scanner
Declares the next_token() method that should be
implemented by scanners. This method is typically
called by lr_parser.scan(). End-of-file can be
indicated either by returning
new Symbol(lr_parser.EOF_sym())
or
null
.
***************************************************/
public interface Scanner {
/** Return the next token, or null
on end-of-file. */
public Symbol next_token() throws java.lang.Exception;
}
Symbol
package java_cup.runtime;
public synchronized class Symbol {
public int sym;
public int parse_state;
boolean used_by_parser;
public int left;
public int right;
public Object value;
public void Symbol(int, int, int, Object);
public void Symbol(int, Object);
public void Symbol(int, int, int);
public void Symbol(int);
void Symbol(int, int);
public String toString();
}
java_cup/runtime/Symbol.java
java_cup/runtime/Symbol.javapackage java_cup.runtime;
/**
* Defines the Symbol class, which is used to represent all terminals
* and nonterminals while parsing. The lexer should pass CUP Symbols
* and CUP returns a Symbol.
*
* @version last updated: 7/3/96
* @author Frank Flannery
*/
/* ****************************************************************
Class Symbol
what the parser expects to receive from the lexer.
the token is identified as follows:
sym: the symbol type
parse_state: the parse state.
value: is the lexical value of type Object
left : is the left position in the original input file
right: is the right position in the original input file
******************************************************************/
public class Symbol {
/*******************************
Constructor for l,r values
*******************************/
public Symbol(int id, int l, int r, Object o) {
this(id);
left = l;
right = r;
value = o;
}
/*******************************
Constructor for no l,r values
********************************/
public Symbol(int id, Object o) {
this(id, -1, -1, o);
}
/*****************************
Constructor for no value
***************************/
public Symbol(int id, int l, int r) {
this(id, l, r, null);
}
/***********************************
Constructor for no value or l,r
***********************************/
public Symbol(int sym_num) {
this(sym_num, -1);
left = -1;
right = -1;
value = null;
}
/***********************************
Constructor to give a start state
***********************************/
Symbol(int sym_num, int state)
{
sym = sym_num;
parse_state = state;
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The symbol number of the terminal or non terminal being represented */
public int sym;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The parse state to be recorded on the parse stack with this symbol.
* This field is for the convenience of the parser and shouldn’t be
* modified except by the parser.
*/
public int parse_state;
/** This allows us to catch some errors caused by scanners recycling
* symbols. For the use of the parser only. [CSA, 23-Jul-1999] */
boolean used_by_parser = false;
/*******************************
The data passed to parser
*******************************/
public int left, right;
public Object value;
/*****************************
Printing this token out. (Override for pretty-print).
****************************/
public String toString() { return “#”+sym; }
}
virtual_parse_stack
package java_cup.runtime;
public synchronized class virtual_parse_stack {
protected java.util.Stack real_stack;
protected int real_next;
protected java.util.Stack vstack;
public void virtual_parse_stack(java.util.Stack) throws Exception;
protected void get_from_real();
public boolean empty();
public int top() throws Exception;
public void pop() throws Exception;
public void push(int);
}
java_cup/runtime/virtual_parse_stack.java
java_cup/runtime/virtual_parse_stack.java
package java_cup.runtime;
import java.util.Stack;
/** This class implements a temporary or “virtual” parse stack that
* replaces the top portion of the actual parse stack (the part that
* has been changed by some set of operations) while maintaining its
* original contents. This data structure is used when the parse needs
* to “parse ahead” to determine if a given error recovery attempt will
* allow the parse to continue far enough to consider it successful. Once
* success or failure of parse ahead is determined the system then
* reverts to the original parse stack (which has not actually been
* modified). Since parse ahead does not execute actions, only parse
* state is maintained on the virtual stack, not full Symbol objects.
*
* @see java_cup.runtime.lr_parser
* @version last updated: 7/3/96
* @author Frank Flannery
*/
public class virtual_parse_stack {
/*———————————————————–*/
/*— Constructor(s) —————————————-*/
/*———————————————————–*/
/** Constructor to build a virtual stack out of a real stack. */
public virtual_parse_stack(Stack shadowing_stack) throws java.lang.Exception
{
/* sanity check */
if (shadowing_stack == null)
throw new Exception(
“Internal parser error: attempt to create null virtual stack”);
/* set up our internals */
real_stack = shadowing_stack;
vstack = new Stack();
real_next = 0;
/* get one element onto the virtual portion of the stack */
get_from_real();
}
/*———————————————————–*/
/*— (Access to) Instance Variables ————————*/
/*———————————————————–*/
/** The real stack that we shadow. This is accessed when we move off
* the bottom of the virtual portion of the stack, but is always left
* unmodified.
*/
protected Stack real_stack;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Top of stack indicator for where we leave off in the real stack.
* This is measured from top of stack, so 0 would indicate that no
* elements have been “moved” from the real to virtual stack.
*/
protected int real_next;
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** The virtual top portion of the stack. This stack contains Integer
* objects with state numbers. This stack shadows the top portion
* of the real stack within the area that has been modified (via operations
* on the virtual stack). When this portion of the stack becomes empty we
* transfer elements from the underlying stack onto this stack.
*/
protected Stack vstack;
/*———————————————————–*/
/*— General Methods —————————————*/
/*———————————————————–*/
/** Transfer an element from the real to the virtual stack. This assumes
* that the virtual stack is currently empty.
*/
protected void get_from_real()
{
Symbol stack_sym;
/* don’t transfer if the real stack is empty */
if (real_next >= real_stack.size()) return;
/* get a copy of the first Symbol we have not transfered */
stack_sym = (Symbol)real_stack.elementAt(real_stack.size()-1-real_next);
/* record the transfer */
real_next++;
/* put the state number from the Symbol onto the virtual stack */
vstack.push(new Integer(stack_sym.parse_state));
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Indicate whether the stack is empty. */
public boolean empty()
{
/* if vstack is empty then we were unable to transfer onto it and
the whole thing is empty. */
return vstack.empty();
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Return value on the top of the stack (without popping it). */
public int top() throws java.lang.Exception
{
if (vstack.empty())
throw new Exception(
“Internal parser error: top() called on empty virtual stack”);
return ((Integer)vstack.peek()).intValue();
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Pop the stack. */
public void pop() throws java.lang.Exception
{
if (vstack.empty())
throw new Exception(
“Internal parser error: pop from empty virtual stack”);
/* pop it */
vstack.pop();
/* if we are now empty transfer an element (if there is one) */
if (vstack.empty())
get_from_real();
}
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
/** Push a state number onto the stack. */
public void push(int state_num)
{
vstack.push(new Integer(state_num));
}
/*———————————————————–*/
}
shift_action
package java_cup;
public synchronized class shift_action extends parse_action {
protected lalr_state _shift_to;
public void shift_action(lalr_state) throws internal_error;
public lalr_state shift_to();
public int kind();
public boolean equals(shift_action);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/shift_action.java
java_cup/shift_action.java
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() + “)”;}
/*———————————————————–*/
}
sym
package java_cup;
public synchronized class sym {
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;
public void sym();
}
java_cup/sym.java
java_cup/sym.java
//—————————————————-
// 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;
}
symbol
package java_cup;
public abstract synchronized class symbol {
protected String _name;
protected String _stack_type;
protected int _use_count;
protected int _index;
public void symbol(String, String);
public void symbol(String);
public String name();
public String stack_type();
public int use_count();
public void note_use();
public int index();
public abstract boolean is_non_term();
public String toString();
}
java_cup/symbol.java
java_cup/symbol.javapackage 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();
}
/*———————————————————–*/
}
symbol_part
package java_cup;
public synchronized class symbol_part extends production_part {
protected symbol _the_symbol;
public void symbol_part(symbol, String) throws internal_error;
public void symbol_part(symbol) throws internal_error;
public symbol the_symbol();
public boolean is_action();
public boolean equals(symbol_part);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/symbol_part.java
java_cup/symbol_part.javapackage 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$$”;
}
/*———————————————————–*/
}
symbol_set
package java_cup;
public synchronized class symbol_set {
protected java.util.Hashtable _all;
public void symbol_set();
public void symbol_set(symbol_set) throws internal_error;
public java.util.Enumeration all();
public int size();
protected void not_null(Object) throws internal_error;
public boolean contains(symbol);
public boolean is_subset_of(symbol_set) throws internal_error;
public boolean is_superset_of(symbol_set) throws internal_error;
public boolean add(symbol) throws internal_error;
public void remove(symbol) throws internal_error;
public boolean add(symbol_set) throws internal_error;
public void remove(symbol_set) throws internal_error;
public boolean equals(symbol_set);
public boolean equals(Object);
public int hashCode();
public String toString();
}
java_cup/symbol_set.java
java_cup/symbol_set.java
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;
}
/*-----------------------------------------------------------*/
}
terminal
package java_cup;
public synchronized class terminal extends symbol {
private int _precedence_num;
private int _precedence_side;
protected static java.util.Hashtable _all;
protected static java.util.Hashtable _all_by_index;
protected static int next_index;
public static final terminal EOF;
public static final terminal error;
static void
public void terminal(String, String, int, int);
public void terminal(String, String);
public void terminal(String);
public static java.util.Enumeration all();
public static terminal find(String);
public static terminal find(int);
public static int number();
public boolean is_non_term();
public String toString();
public int precedence_num();
public int precedence_side();
public void set_precedence(int, int);
}
java_cup/terminal.java
java_cup/terminal.javapackage 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;
}
/*———————————————————–*/
}
terminal_set
package java_cup;
public synchronized class terminal_set {
public static final terminal_set EMPTY;
protected java.util.BitSet _elements;
static void
public void terminal_set();
public void terminal_set(terminal_set) throws internal_error;
protected void not_null(Object) throws internal_error;
public boolean empty();
public boolean contains(terminal) throws internal_error;
public boolean contains(int);
public boolean is_subset_of(terminal_set) throws internal_error;
public boolean is_superset_of(terminal_set) throws internal_error;
public boolean add(terminal) throws internal_error;
public void remove(terminal) throws internal_error;
public boolean add(terminal_set) throws internal_error;
public boolean intersects(terminal_set) throws internal_error;
public boolean equals(terminal_set);
public boolean equals(Object);
public String toString();
}
java_cup/terminal_set.java
java_cup/terminal_set.java
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;
}
/*-----------------------------------------------------------*/
}
version
package java_cup;
public synchronized class version {
public static final int major = 0;
public static final int minor = 10;
public static final char update = 107;
public static final String version_str = v0.10k;
public static final String title_str = CUP v0.10k;
public static final String author_str = Scott E. Hudson, Frank Flannery, and C. Scott Ananian;
public static final String program_name = java_cup;
public void version();
}
java_cup/version.java
java_cup/version.java
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 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”;
}