diff options
Diffstat (limited to 'src/syntaxParser/java_cup/SAVE/parser.cup')
| -rw-r--r-- | src/syntaxParser/java_cup/SAVE/parser.cup | 863 |
1 files changed, 863 insertions, 0 deletions
diff --git a/src/syntaxParser/java_cup/SAVE/parser.cup b/src/syntaxParser/java_cup/SAVE/parser.cup new file mode 100644 index 0000000..8af0d05 --- /dev/null +++ b/src/syntaxParser/java_cup/SAVE/parser.cup @@ -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 */; + +/*----------------------------------------------------------------*/ + + + + + + + + + |
