Checking in stuff
[IRC.git] / Robust / cup / java_cup / parser.cup
diff --git a/Robust/cup/java_cup/parser.cup b/Robust/cup/java_cup/parser.cup
new file mode 100644 (file)
index 0000000..8af0d05
--- /dev/null
@@ -0,0 +1,863 @@
+
+/*================================================================*/ 
+/* 
+  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 */;
+
+/*----------------------------------------------------------------*/ 
+
+
+
+
+
+
+
+
+