--- /dev/null
+
+/*================================================================*/
+/*
+ JavaCup Specification for the JavaCup Specification Language
+ by Scott Hudson, GVU Center, Georgia Tech, August 1995
+ and Frank Flannery, Department of Computer Science, Princeton Univ,
+ July 1996
+ Bug Fixes: C. Scott Ananian, Dept of Electrical Engineering, Princeton
+ University, October 1996. [later Massachusetts Institute of Technology]
+
+
+ This JavaCup specification is used to implement JavaCup itself.
+ It specifies the parser for the JavaCup specification language.
+ (It also serves as a reasonable example of what a typical JavaCup
+ spec looks like).
+
+ The specification has the following parts:
+ Package and import declarations
+ These serve the same purpose as in a normal Java source file
+ (and will appear in the generated code for the parser). In this
+ case we are part of the java_cup package and we import both the
+ java_cup runtime system and Hashtable from the standard Java
+ utilities package.
+
+ Action code
+ This section provides code that is included with the class encapsulating
+ the various pieces of user code embedded in the grammar (i.e., the
+ semantic actions). This provides a series of helper routines and
+ data structures that the semantic actions use.
+
+ Parser code
+ This section provides code included in the parser class itself. In
+ this case we override the default error reporting routines.
+
+ Init with and scan with
+ These sections provide small bits of code that initialize, then
+ indicate how to invoke the scanner.
+
+ Symbols and grammar
+ These sections declare all the terminal and non terminal symbols
+ and the types of objects that they will be represented by at runtime,
+ then indicate the start symbol of the grammar (), and finally provide
+ the grammar itself (with embedded actions).
+
+ Operation of the parser
+ The parser acts primarily by accumulating data structures representing
+ various parts of the specification. Various small parts (e.g., single
+ code strings) are stored as static variables of the emit class and
+ in a few cases as variables declared in the action code section.
+ Terminals, non terminals, and productions, are maintained as collection
+ accessible via static methods of those classes. In addition, two
+ symbol tables are kept:
+ symbols maintains the name to object mapping for all symbols
+ non_terms maintains a separate mapping containing only the non terms
+
+ Several intermediate working structures are also declared in the action
+ code section. These include: rhs_parts, rhs_pos, and lhs_nt which
+ build up parts of the current production while it is being parsed.
+
+ Author(s)
+ Scott Hudson, GVU Center, Georgia Tech.
+ Frank Flannery, Department of Computer Science, Princeton Univ.
+ C. Scott Ananian, Department of Electrical Engineering, Princeton Univ.
+
+ Revisions
+ v0.9a First released version [SEH] 8/29/95
+ v0.9b Updated for beta language (throws clauses) [SEH] 11/25/95
+ v0.10a Made many improvements/changes. now offers:
+ return value
+ left/right positions and propagations
+ cleaner label references
+ precedence and associativity for terminals
+ contextual precedence for productions
+ [FF] 7/3/96
+ v0.10b Fixed %prec directive so it works like it's supposed to.
+ [CSA] 10/10/96
+ v0.10g Added support for array types on symbols.
+ [CSA] 03/23/98
+ v0.10i Broaden set of IDs allowed in multipart_id and label_id so
+ that only java reserved words (and not CUP reserved words like
+ 'parser' and 'start') are prohibited. Allow reordering of
+ action code, parser code, init code, and scan with sections,
+ and made closing semicolon optional for these sections.
+ Added 'nonterminal' as a terminal symbol, finally fixing a
+ spelling mistake that's been around since the beginning.
+ For backwards compatibility, you can still misspell the
+ word if you like.
+*/
+/*================================================================*/
+
+package java_cup;
+import java_cup.runtime.*;
+import java.util.Hashtable;
+
+/*----------------------------------------------------------------*/
+
+action code {:
+ /** helper routine to clone a new production part adding a given label */
+ protected production_part add_lab(production_part part, String lab)
+ throws internal_error
+ {
+ /* if there is no label, or this is an action, just return the original */
+ if (lab == null || part.is_action()) return part;
+
+ /* otherwise build a new one with the given label attached */
+ return new symbol_part(((symbol_part)part).the_symbol(),lab);
+ }
+
+ /** max size of right hand side we will support */
+ protected final int MAX_RHS = 200;
+
+ /** array for accumulating right hand side parts */
+ protected production_part[] rhs_parts = new production_part[MAX_RHS];
+
+ /** where we are currently in building a right hand side */
+ protected int rhs_pos = 0;
+
+ /** start a new right hand side */
+ protected void new_rhs() {rhs_pos = 0; }
+
+ /** add a new right hand side part */
+ protected void add_rhs_part(production_part part) throws java.lang.Exception
+ {
+ if (rhs_pos >= MAX_RHS)
+ throw new Exception("Internal Error: Productions limited to " +
+ MAX_RHS + " symbols and actions");
+
+ rhs_parts[rhs_pos] = part;
+ rhs_pos++;
+ }
+
+ /** string to build up multiple part names */
+ protected String multipart_name = new String();
+
+ /** append a new name segment to the accumulated multipart name */
+ protected void append_multipart(String name)
+ {
+ String dot = "";
+
+ /* if we aren't just starting out, put on a dot */
+ if (multipart_name.length() != 0) dot = ".";
+
+ multipart_name = multipart_name.concat(dot + name);
+ }
+
+ /** table of declared symbols -- contains production parts indexed by name */
+ protected Hashtable symbols = new Hashtable();
+
+ /** table of just non terminals -- contains non_terminals indexed by name */
+ protected Hashtable non_terms = new Hashtable();
+
+ /** declared start non_terminal */
+ protected non_terminal start_nt = null;
+
+ /** left hand side non terminal of the current production */
+ protected non_terminal lhs_nt;
+
+ /** Current precedence number */
+ int _cur_prec = 0;
+
+ /** Current precedence side */
+ int _cur_side = assoc.no_prec;
+
+ /** update the precedences we are declaring */
+ protected void update_precedence(int p) {
+ _cur_side = p;
+ _cur_prec++;
+ }
+ /** add relevant data to terminals */
+ protected void add_precedence(String term) {
+ if (term == null) {
+ System.err.println("Unable to add precedence to nonexistent terminal");
+ } else {
+ symbol_part sp = (symbol_part)symbols.get(term);
+ if (sp == null) {
+ System.err.println("Could find terminal " + term + " while declaring precedence");
+ } else {
+ java_cup.symbol sym = sp.the_symbol();
+ if (sym instanceof terminal)
+ ((terminal)sym).set_precedence(_cur_side, _cur_prec);
+ else System.err.println("Precedence declaration: Can't find terminal " + term);
+ }
+ }
+ }
+:};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser code {:
+
+ /* override error routines */
+
+ public void report_fatal_error(
+ String message,
+ Object info)
+ {
+ done_parsing();
+ lexer.emit_error(message);
+ System.err.println("Can't recover from previous error(s), giving up.");
+ System.exit(1);
+ }
+
+ public void report_error(String message, Object info)
+ {
+ lexer.emit_error(message);
+ }
+:};
+
+/*----------------------------------------------------------------*/
+
+init with {: lexer.init(); :};
+scan with {: return lexer.next_token(); :};
+
+/*----------------------------------------------------------------*/
+
+terminal
+ PACKAGE, IMPORT, CODE, ACTION, PARSER, TERMINAL, NON, INIT, SCAN, WITH,
+ START, SEMI, COMMA, STAR, DOT, COLON, COLON_COLON_EQUALS, BAR, PRECEDENCE,
+ LEFT, RIGHT, NONASSOC, PERCENT_PREC, LBRACK, RBRACK, NONTERMINAL;
+
+terminal String ID, CODE_STRING;
+
+non terminal
+ spec, package_spec, import_list, action_code_part,
+ code_parts, code_part, opt_semi, non_terminal,
+ parser_code_part, symbol_list, start_spec, production_list,
+ multipart_id, import_spec, import_id, init_code, scan_code, symbol,
+ type_id, term_name_list, non_term_name_list, production, prod_part_list,
+ prod_part, new_term_id, new_non_term_id, rhs_list, rhs, empty,
+ precedence_list, preced, terminal_list, precedence_l, declares_term,
+ declares_non_term;
+
+non terminal String nt_id, symbol_id, label_id, opt_label, terminal_id,
+ term_id, robust_id;
+
+/*----------------------------------------------------------------*/
+
+start with spec;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+spec ::=
+ {:
+ /* declare "error" as a terminal */
+ symbols.put("error", new symbol_part(terminal.error));
+
+ /* declare start non terminal */
+ non_terms.put("$START", non_terminal.START_nt);
+ :}
+ package_spec
+ import_list
+ code_parts
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ |
+ /* error recovery assuming something went wrong before symbols
+ and we have TERMINAL or NON TERMINAL to sync on. if we get
+ an error after that, we recover inside symbol_list or
+ production_list
+ */
+ error
+ symbol_list
+ precedence_list
+ start_spec
+ production_list
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+package_spec ::=
+ PACKAGE
+ multipart_id
+ {:
+ /* save the package name */
+ emit.package_name = multipart_name;
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_list ::=
+ import_list
+ import_spec
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_spec ::=
+ IMPORT
+ import_id
+ {:
+ /* save this import on the imports list */
+ emit.import_list.push(multipart_name);
+
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+// allow any order; all parts are optional. [CSA, 23-Jul-1999]
+// (we check in the part action to make sure we don't have 2 of any part)
+code_part ::=
+ action_code_part | parser_code_part | init_code | scan_code ;
+code_parts ::=
+ | code_parts code_part;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+action_code_part ::=
+ ACTION CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.action_code!=null)
+ lexer.emit_error("Redundant action code (skipping)");
+ else /* save the user included code string */
+ emit.action_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+parser_code_part ::=
+ PARSER CODE CODE_STRING:user_code opt_semi
+ {:
+ if (emit.parser_code!=null)
+ lexer.emit_error("Redundant parser code (skipping)");
+ else /* save the user included code string */
+ emit.parser_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+init_code ::=
+ INIT WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.init_code!=null)
+ lexer.emit_error("Redundant init code (skipping)");
+ else /* save the user code */
+ emit.init_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+scan_code ::=
+ SCAN WITH CODE_STRING:user_code opt_semi
+ {:
+ if (emit.scan_code!=null)
+ lexer.emit_error("Redundant scan code (skipping)");
+ else /* save the user code */
+ emit.scan_code = user_code;
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_list ::= symbol_list symbol | symbol;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol ::=
+ TERMINAL
+ type_id
+ declares_term
+ |
+ TERMINAL
+ declares_term
+ |
+ non_terminal
+ type_id
+ declares_non_term
+ |
+ non_terminal
+ declares_non_term
+ |
+ /* error recovery productions -- sync on semicolon */
+
+ TERMINAL
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ |
+ non_terminal
+ error
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_term ::=
+ term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+declares_non_term ::=
+ non_term_name_list
+ {:
+ /* reset the accumulated multipart name */
+ multipart_name = new String();
+ :}
+ SEMI
+ ;
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_name_list ::= term_name_list COMMA new_term_id | new_term_id;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_term_name_list ::=
+ non_term_name_list
+ COMMA
+ new_non_term_id
+ |
+ new_non_term_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+
+precedence_list ::= precedence_l | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+precedence_l ::= precedence_l preced | preced;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+preced ::=
+ PRECEDENCE LEFT
+ {:
+ update_precedence(assoc.left);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE RIGHT
+ {:
+ update_precedence(assoc.right);
+ :}
+ terminal_list SEMI
+ |
+ PRECEDENCE NONASSOC
+ {:
+ update_precedence(assoc.nonassoc);
+ :}
+ terminal_list SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_list ::= terminal_list COMMA terminal_id
+ |
+ terminal_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+terminal_id ::= term_id:sym
+ {:
+ add_precedence(sym);
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+term_id ::= symbol_id:sym
+ {:
+ /* check that the symbol_id is a terminal */
+ if (symbols.get(sym) == null)
+ {
+ /* issue a message */
+ lexer.emit_error("Terminal \"" + sym +
+ "\" has not been declared");
+ }
+ RESULT = sym;
+ :};
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+start_spec ::=
+ START WITH nt_id:start_name
+ {:
+ /* verify that the name has been declared as a non terminal */
+ non_terminal nt = (non_terminal)non_terms.get(start_name);
+ if (nt == null)
+ {
+ lexer.emit_error( "Start non terminal \"" + start_name +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* remember the non-terminal for later */
+ start_nt = nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt), "start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ new_rhs();
+ }
+ :}
+ SEMI
+ |
+ empty
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production_list ::= production_list production | production;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+production ::=
+ nt_id:lhs_id
+ {:
+ /* lookup the lhs nt */
+ lhs_nt = (non_terminal)non_terms.get(lhs_id);
+
+ /* if it wasn't declared, emit a message */
+ if (lhs_nt == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("LHS non terminal \"" + lhs_id +
+ "\" has not been declared");
+ }
+
+ /* reset the rhs accumulation */
+ new_rhs();
+ :}
+ COLON_COLON_EQUALS
+ {: :}
+ rhs_list
+ SEMI
+ |
+ error
+ {: lexer.emit_error("Syntax Error"); :}
+ SEMI
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs_list ::= rhs_list BAR rhs | rhs;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+rhs ::=
+ prod_part_list PERCENT_PREC term_id:term_name
+ {:
+ java_cup.symbol sym = null;
+ if (lhs_nt != null)
+ {
+ /* Find the precedence symbol */
+ if (term_name == null) {
+ System.err.println("No terminal for contextual precedence");
+ sym = null;
+ } else {
+ sym = ((symbol_part)symbols.get(term_name)).the_symbol();
+ }
+ /* build the production */
+ production p;
+ if ((sym!=null) && (sym instanceof terminal)) {
+ p = new production(lhs_nt, rhs_parts, rhs_pos,
+ ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ ((symbol_part)symbols.get(term_name)).the_symbol().note_use();
+ } else {
+ System.err.println("Invalid terminal " + term_name +
+ " for contextual precedence assignment");
+ p = new production(lhs_nt, rhs_parts, rhs_pos);
+ }
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ if ((sym!=null) && (sym instanceof terminal)) {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts,
+ rhs_pos, ((terminal)sym).precedence_num(),
+ ((terminal)sym).precedence_side());
+ } else {
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+ }
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ |
+ prod_part_list
+ {:
+ if (lhs_nt != null)
+ {
+ /* build the production */
+ production p = new production(lhs_nt, rhs_parts, rhs_pos);
+
+ /* if we have no start non-terminal declared and this is
+ the first production, make its lhs nt the start_nt
+ and build a special start production for it. */
+ if (start_nt == null)
+ {
+ start_nt = lhs_nt;
+
+ /* build a special start production */
+ new_rhs();
+ add_rhs_part(add_lab(new symbol_part(start_nt),"start_val"));
+ add_rhs_part(new symbol_part(terminal.EOF));
+ add_rhs_part(new action_part("RESULT = start_val;"));
+ emit.start_production =
+ new production(non_terminal.START_nt, rhs_parts, rhs_pos);
+
+ new_rhs();
+ }
+ }
+
+ /* reset the rhs accumulation in any case */
+ new_rhs();
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part_list ::= prod_part_list prod_part | empty;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+prod_part ::=
+ symbol_id:symid opt_label:labid
+ {:
+ /* try to look up the id */
+ production_part symb = (production_part)symbols.get(symid);
+
+ /* if that fails, symbol is undeclared */
+ if (symb == null)
+ {
+ if (lexer.error_count == 0)
+ lexer.emit_error("java_cup.runtime.Symbol \"" + symid +
+ "\" has not been declared");
+ }
+ else
+ {
+ /* add a labeled production part */
+ add_rhs_part(add_lab(symb, labid));
+ }
+ :}
+ |
+ CODE_STRING:code_str
+ {:
+ /* add a new production part */
+ add_rhs_part(new action_part(code_str));
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_label ::=
+ COLON label_id:labid
+ {: RESULT = labid; :}
+ |
+ empty
+ {: RESULT = null; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+multipart_id ::=
+ multipart_id DOT robust_id:another_id
+ {: append_multipart(another_id); :}
+ |
+ robust_id:an_id
+ {: append_multipart(an_id); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+import_id ::=
+ multipart_id DOT STAR
+ {: append_multipart("*"); :}
+ |
+ multipart_id
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+type_id ::= multipart_id
+ | type_id LBRACK RBRACK
+ {: multipart_name = multipart_name.concat("[]"); :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_term_id ::=
+ ID:term_id
+ {:
+ /* see if this terminal has been declared before */
+ if (symbols.get(term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error("java_cup.runtime.Symbol \"" + term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ /* if no type declared, declare one */
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build a production_part and put it in the table */
+ symbols.put(term_id,
+ new symbol_part(new terminal(term_id, multipart_name)));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+new_non_term_id ::=
+ ID:non_term_id
+ {:
+ /* see if this non terminal has been declared before */
+ if (symbols.get(non_term_id) != null)
+ {
+ /* issue a message */
+ lexer.emit_error( "java_cup.runtime.Symbol \"" + non_term_id +
+ "\" has already been declared");
+ }
+ else
+ {
+ if (multipart_name.equals("")) {
+ append_multipart("Object");
+ }
+ /* build the non terminal object */
+ non_terminal this_nt =
+ new non_terminal(non_term_id, multipart_name);
+
+ /* put it in the non_terms table */
+ non_terms.put(non_term_id, this_nt);
+
+ /* build a production_part and put it in the symbols table */
+ symbols.put(non_term_id, new symbol_part(this_nt));
+ }
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+nt_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+symbol_id ::=
+ ID:the_id
+ {: RESULT = the_id; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+label_id ::=
+ robust_id:the_id
+ {: RESULT = the_id; :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+robust_id ::= /* all ids that aren't reserved words in Java */
+ ID:the_id {: RESULT = the_id; :}
+ /* package is reserved. */
+ /* import is reserved. */
+ | CODE {: RESULT = "code"; :}
+ | ACTION {: RESULT = "action"; :}
+ | PARSER {: RESULT = "parser"; :}
+ | TERMINAL {: RESULT = "terminal"; :}
+ | NON {: RESULT = "non"; :}
+ | NONTERMINAL {: RESULT = "nonterminal"; :}
+ | INIT {: RESULT = "init"; :}
+ | SCAN {: RESULT = "scan"; :}
+ | WITH {: RESULT = "with"; :}
+ | START {: RESULT = "start"; :}
+ | PRECEDENCE {: RESULT = "precedence"; :}
+ | LEFT {: RESULT = "left"; :}
+ | RIGHT {: RESULT = "right"; :}
+ | NONASSOC {: RESULT = "nonassoc"; :}
+ | error
+ {:
+ lexer.emit_error("Illegal use of reserved word");
+ RESULT="ILLEGAL";
+ :}
+ ;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+non_terminal ::= NON TERMINAL | NONTERMINAL;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+opt_semi ::= /* nothing */
+ | SEMI;
+
+/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+empty ::= /* nothing */;
+
+/*----------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+