/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Produce a human readable dump of the grammar. */ public static void dump_grammar() { System.Console.Error.WriteLine("===== Terminals ====="); for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++) { System.Console.Error.Write("["+tidx+"]"+terminal.find(tidx).name()+" "); if ((cnt+1) % 5 == 0) System.Console.Error.WriteLine(); } System.Console.Error.WriteLine(); System.Console.Error.WriteLine(); System.Console.Error.WriteLine("===== Non terminals ====="); for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++) { System.Console.Error.Write("["+nidx+"]"+non_terminal.find(nidx).name()+" "); if ((cnt+1) % 5 == 0) System.Console.Error.WriteLine(); } System.Console.Error.WriteLine(); System.Console.Error.WriteLine(); System.Console.Error.WriteLine("===== Productions ====="); for (int pidx=0; pidx < production.number(); pidx++) { production prod = production.find(pidx); System.Console.Error.Write("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= "); for (int i=0; i<prod.rhs_length(); i++) if (prod.rhs(i).is_action()) System.Console.Error.Write("{action} "); else System.Console.Error.Write( ((symbol_part)prod.rhs(i)).the_symbol().name() + " "); System.Console.Error.WriteLine(); } System.Console.Error.WriteLine(); }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality comparison. */ public bool Equals(production other) { if (other == null) { return(false); } return(other._index == _index); }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Add a production to our Set of productions. */ public void add_production(production prod) { /* 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.Add(prod, prod); }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Emit the production table. * @param out stream to produce output on. */ protected static void emit_production_table(TextWriter cout) { production[] all_prods; production prod; long start_time = DateTime.Now.Ticks; /* collect up the productions in order */ all_prods = new production[production.number()]; IEnumerator p = production.all(); while (p.MoveNext()) { prod = (production)p.Current; all_prods[prod.index()] = prod; } short[][] prod_table = new short[production.number()][]; for (int i = 0; i < production.number(); i++) { prod_table[i] = new short[2]; } for (int i = 0; i < production.number(); i++) { prod = all_prods[i]; // { lhs symbol , rhs size } prod_table[i][0] = (short)prod.lhs().the_symbol().index(); prod_table[i][1] = (short)prod.rhs_length(); } /* do the top of the table */ cout.WriteLine(); cout.WriteLine(" /** Production table. */"); cout.WriteLine(" protected static readonly short[][] _production_table = "); #if JAVA_CUP_WAY cout.Write(" unpackFromStrings("); do_table_as_string(cout, prod_table); cout.WriteLine(");"); #else //JCM: Parsing table Optimization: //See : https://github.com/TypeCobolTeam/TypeCobol/issues/897 do_table_as_table(cout, prod_table); #endif /* do the public accessor method */ cout.WriteLine(); cout.WriteLine(" /** Access to production table. */"); cout.WriteLine(" public override short[][] production_table() " + "{return _production_table;}"); production_table_time = DateTime.Now.Ticks - start_time; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Emit the production table. * @param out stream to produce output on. */ protected static void emit_production_table(TextWriter cout) { production[] all_prods; production prod; long start_time = DateTime.Now.Ticks; /* collect up the productions in order */ all_prods = new production[production.number()]; IEnumerator p = production.all(); while ( p.MoveNext() ) { prod = (production)p.Current; all_prods[prod.index()] = prod; } short[][] prod_table=new short[production.number()][]; for (int i=0;i<production.number();i++) { prod_table[i]= new short[2]; } for (int i = 0; i<production.number(); i++) { prod = all_prods[i]; // { lhs symbol , rhs size } prod_table[i][0] = (short) prod.lhs().the_symbol().index(); prod_table[i][1] = (short) prod.rhs_length(); } /* do the top of the table */ cout.WriteLine(); cout.WriteLine(" /** Production table. */"); cout.WriteLine(" protected static readonly short[][] _production_table = "); cout.Write (" unpackFromStrings("); do_table_as_string(cout, prod_table); cout.WriteLine(");"); /* do the public accessor method */ cout.WriteLine(); cout.WriteLine(" /** Access to production table. */"); cout.WriteLine(" public override short[][] production_table() " + "{return _production_table;}"); production_table_time = DateTime.Now.Ticks - start_time; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** 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( TextWriter cout, parse_action_table action_table, parse_reduce_table reduce_table, int start_st, production start_prod, bool compact_reduces, bool suppress_scanner) { long start_time = DateTime.Now.Ticks; /* top of file */ cout.WriteLine(); cout.WriteLine("//----------------------------------------------------"); cout.WriteLine("// The following code was generated by " + version.title_str); cout.WriteLine("// " + DateTime.Now); cout.WriteLine("//----------------------------------------------------"); cout.WriteLine(); emit_package(cout); /* user supplied imports */ IEnumerator myEnum= import_list.GetEnumerator(); while (myEnum.MoveNext()) cout.WriteLine("using " + myEnum.Current.ToString() + ";"); /* class header */ cout.WriteLine(); cout.WriteLine("/** "+version.title_str+" generated parser."); cout.WriteLine(" * @version " + DateTime.Now); cout.WriteLine(" */"); cout.WriteLine("public class " + parser_class_name + " : TUVienna.CS_CUP.Runtime.lr_parser {"); /* constructors [CSA/davidm, 24-jul-99] */ cout.WriteLine(); cout.WriteLine(" /** Default constructor. */"); cout.WriteLine(" public " + parser_class_name + "():base() {;}"); if (!suppress_scanner) { cout.WriteLine(); cout.WriteLine(" /** Constructor which sets the default scanner. */"); cout.WriteLine(" public " + parser_class_name + "(TUVienna.CS_CUP.Runtime.Scanner s): base(s) {;}"); } /* emit the various tables */ emit_production_table(cout); do_action_table(cout, action_table, compact_reduces); do_reduce_table(cout, reduce_table); /* instance of the action encapsulation class */ cout.WriteLine(" /** Instance of action encapsulation class. */"); cout.WriteLine(" protected " + pre("actions") + " action_obj;"); cout.WriteLine(); /* action object initializer */ cout.WriteLine(" /** Action encapsulation object initializer. */"); cout.WriteLine(" protected override void init_actions()"); cout.WriteLine(" {"); cout.WriteLine(" action_obj = new " + pre("actions") + "(this);"); cout.WriteLine(" }"); cout.WriteLine(); /* access to action code */ cout.WriteLine(" /** Invoke a user supplied parse action. */"); cout.WriteLine(" public override TUVienna.CS_CUP.Runtime.Symbol do_action("); cout.WriteLine(" int act_num,"); cout.WriteLine(" TUVienna.CS_CUP.Runtime.lr_parser parser,"); cout.WriteLine(" System.Collections.Stack xstack1,"); cout.WriteLine(" int top)"); cout.WriteLine(" {"); cout.WriteLine(" mStack CUP_parser_stack= new mStack(xstack1);"); cout.WriteLine(" /* call code in generated class */"); cout.WriteLine(" return action_obj." + pre("do_action(") + "act_num, parser, stack, top);"); cout.WriteLine(" }"); cout.WriteLine(""); /* method to tell the parser about the start state */ cout.WriteLine(" /** Indicates start state. */"); cout.WriteLine(" public override int start_state() {return " + start_st + ";}"); /* method to indicate start production */ cout.WriteLine(" /** Indicates start production. */"); cout.WriteLine(" public override int start_production() {return " + start_production.index() + ";}"); cout.WriteLine(); /* methods to indicate EOF and error symbol indexes */ cout.WriteLine(" /** <code>EOF</code> Symbol index. */"); cout.WriteLine(" public override int EOF_sym() {return " + terminal.EOF.index() + ";}"); cout.WriteLine(); cout.WriteLine(" /** <code>error</code> Symbol index. */"); cout.WriteLine(" public override int error_sym() {return " + terminal.error.index() + ";}"); cout.WriteLine(); /* user supplied code for user_init() */ if (init_code != null) { cout.WriteLine(); cout.WriteLine(" /** User initialization code. */"); cout.WriteLine(" public override void user_init() "); cout.WriteLine(" {"); cout.WriteLine(init_code); cout.WriteLine(" }"); } /* user supplied code for scan */ if (scan_code != null) { cout.WriteLine(); cout.WriteLine(" /** Scan to get the next Symbol. */"); cout.WriteLine(" public override TUVienna.CS_CUP.Runtime.Symbol scan()"); cout.WriteLine(" {"); cout.WriteLine(scan_code); cout.WriteLine(" }"); } /* user supplied code */ if (parser_code != null) { cout.WriteLine(); cout.WriteLine(parser_code); } /* end of class */ cout.WriteLine("}"); /* put out the action code class */ emit_action_code(cout, start_prod); if (package_name!=null) cout.WriteLine("}"); parser_time = DateTime.Now.Ticks - start_time; }
/** Method with the actual generated action code. */ public Symbol CUP_parser_do_action( int CUP_parser_act_num, lr_parser CUP_parser_parser, Stack CUP_parser_stack1, int CUP_parser_top) { /* Symbol object for return from actions */ Symbol CUP_parser_result; mStack CUP_parser_stack= new mStack(CUP_parser_stack1); /* select the action based on the action number */ switch (CUP_parser_act_num) { /*. . . . . . . . . . . . . . . . . . . .*/ case 106: // empty ::= { object RESULT = null; CUP_parser_result = new Symbol(29/*empty*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(7/*opt_semi*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(7/*opt_semi*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(8/*non_terminal*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(8/*non_terminal*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int the_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string the_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; RESULT = the_id; CUP_parser_result = new Symbol(42/*robust_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int the_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string the_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; RESULT = the_id; CUP_parser_result = new Symbol(38/*label_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(37/*symbol_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int the_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string the_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; RESULT = the_id; CUP_parser_result = new Symbol(37/*symbol_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(36/*nt_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int the_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string the_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; RESULT = the_id; CUP_parser_result = new Symbol(36/*nt_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int non_term_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string non_term_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; /* see if this non terminal has been declared before */ if (symbols[non_term_id] != null) { /* issue a message */ lexer.emit_error( "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.Add(non_term_id, this_nt); /* build a production_part and put it in the symbols table */ symbols.Add(non_term_id, new symbol_part(this_nt)); } CUP_parser_result = new Symbol(26/*new_non_term_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int term_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string term_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; /* see if this terminal has been declared before */ if (symbols[term_id] != null) { /* issue a message */ lexer.emit_error("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.Add(term_id, new symbol_part(new terminal(term_id, multipart_name))); } CUP_parser_result = new Symbol(25/*new_term_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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+"[]"; CUP_parser_result = new Symbol(19/*type_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(19/*type_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(15/*import_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(15/*import_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int an_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string an_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; append_multipart(an_id); CUP_parser_result = new Symbol(13/*multipart_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int another_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string another_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; append_multipart(another_id); CUP_parser_result = new Symbol(13/*multipart_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(39/*opt_label*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int labidright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string labid = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; RESULT = labid; CUP_parser_result = new Symbol(39/*opt_label*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int code_strright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string code_str = (string)((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 Symbol(24/*prod_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left; int symidright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).right; string symid = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; int labidleft = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int labidright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string labid = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; /* try to look up the id */ production_part symb = (production_part)symbols[symid]; /* if that fails, symbol is undeclared */ if (symb == null) { if (lexer.error_count == 0) lexer.emit_error("Symbol \"" + symid + "\" has not been declared"); } else { /* add a labeled production part */ add_rhs_part(add_lab(symb, labid)); } CUP_parser_result = new Symbol(24/*prod_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(23/*prod_part_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(23/*prod_part_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(28/*rhs*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int term_nameright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string term_name = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; symbol sym = null; if (lhs_nt != null) { /* Find the precedence symbol */ if (term_name == null) { System.Console.Error.WriteLine("No terminal for contextual precedence"); sym = null; } else { sym = ((symbol_part)symbols[term_name]).the_symbol(); } /* build the production */ production p; if ((sym!=null) && (sym.GetType()==typeof(terminal))) { p = new production(lhs_nt, rhs_parts, rhs_pos, ((terminal)sym).precedence_num(), ((terminal)sym).precedence_side()); ((symbol_part)symbols[term_name]).the_symbol().note_use(); } else { System.Console.Error.WriteLine("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.GetType()==typeof(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 Symbol(28/*rhs*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(27/*rhs_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(27/*rhs_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(22/*production*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(56/*NT$13*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-4)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-4)).value; // propagate RESULT from NT$12 if ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value; int lhs_idleft = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-5)).left; int lhs_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-5)).right; string lhs_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-5)).value; CUP_parser_result = new Symbol(22/*production*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-5)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left; int lhs_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).right; string lhs_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value; CUP_parser_result = new Symbol(55/*NT$12*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int lhs_idright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string lhs_id = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; /* lookup the lhs nt */ lhs_nt = (non_terminal)non_terms[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 Symbol(54/*NT$11*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(12/*production_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(12/*production_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(11/*start_spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; int start_nameleft = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left; int start_nameright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).right; string start_name = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value; CUP_parser_result = new Symbol(11/*start_spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-4)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int start_nameright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string start_name = (string)((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[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 Symbol(53/*NT$10*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int symright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string sym = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; /* check that the symbol_id is a terminal */ if (symbols[sym] == null) { /* issue a message */ lexer.emit_error("Terminal \"" + sym + "\" has not been declared"); } RESULT = sym; CUP_parser_result = new Symbol(41/*term_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left; int symright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right; string sym = (string)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-0)).value; add_precedence(sym); RESULT = sym; CUP_parser_result = new Symbol(40/*terminal_id*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(32/*terminal_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(32/*terminal_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value; CUP_parser_result = new Symbol(31/*preced*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-4)).left, ((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 Symbol(52/*NT$9*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value; CUP_parser_result = new Symbol(31/*preced*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-4)).left, ((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 Symbol(51/*NT$8*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-2)).value; CUP_parser_result = new Symbol(31/*preced*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-4)).left, ((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 Symbol(50/*NT$7*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(33/*precedence_l*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(33/*precedence_l*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(30/*precedence_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(30/*precedence_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(21/*non_term_name_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(21/*non_term_name_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(20/*term_name_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(20/*term_name_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(35/*declares_non_term*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 = ""; CUP_parser_result = new Symbol(49/*NT$6*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(34/*declares_term*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 = ""; CUP_parser_result = new Symbol(48/*NT$5*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(18/*symbol*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ""; CUP_parser_result = new Symbol(47/*NT$4*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(18/*symbol*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ""; CUP_parser_result = new Symbol(46/*NT$3*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(18/*symbol*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(18/*symbol*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(18/*symbol*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(18/*symbol*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-2)).left, ((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 Symbol(10/*symbol_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(10/*symbol_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left; int user_coderight = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).right; string user_code = ((string)((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 Symbol(17/*scan_code*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left; int user_coderight = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).right; string user_code = (string)((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 Symbol(16/*init_code*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left; int user_coderight = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).right; string user_code = (string)((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 Symbol(9/*parser_code_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left; int user_coderight = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).right; string user_code = (string)((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 Symbol(4/*action_code_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 Symbol(5/*code_parts*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(5/*code_parts*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(6/*code_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(6/*code_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(6/*code_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(6/*code_part*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(14/*import_spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ""; CUP_parser_result = new Symbol(45/*NT$2*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(3/*import_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 Symbol(3/*import_list*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((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 Symbol(2/*package_spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; CUP_parser_result = new Symbol(2/*package_spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-3)).left, ((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 = ""; CUP_parser_result = new Symbol(44/*NT$1*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 Symbol(1/*spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-4)).left, ((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 ( ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-7)).value != null ) RESULT = (object) ((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-7)).value; CUP_parser_result = new Symbol(1/*spec*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-7)).left, ((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.Add("error", new symbol_part(terminal.error)); /* declare start non terminal */ non_terms.Add("$START", non_terminal.START_nt); CUP_parser_result = new Symbol(43/*NT$0*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, ((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 = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left; int start_valright = ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).right; object start_val = (object)((Symbol) CUP_parser_stack.elementAt(CUP_parser_top-1)).value; RESULT = start_val; CUP_parser_result = new Symbol(0/*$START*/, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-1)).left, ((Symbol)CUP_parser_stack.elementAt(CUP_parser_top-0)).right, RESULT); } /* ACCEPT */ CUP_parser_parser.done_parsing(); return CUP_parser_result; /* . . . . . .*/ default: throw new System.Exception( "Invalid action number found in internal parse table"); } }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** 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(TextWriter cout, production start_prod) { production prod; long start_time = DateTime.Now.Ticks; /* class header */ cout.WriteLine(); cout.WriteLine( "/** Cup generated class to encapsulate user supplied action code.*/" ); cout.WriteLine("public class " + pre("actions") + " {"); /* user supplied code */ if (action_code != null) { cout.WriteLine(); cout.WriteLine(action_code); } /* field for parser object */ cout.WriteLine(" private "+ parser_class_name+" my_parser;"); /* constructor */ cout.WriteLine(); cout.WriteLine(" /** Constructor */"); cout.WriteLine(" public " + pre("actions") + "("+ parser_class_name+" t_parser) {"); cout.WriteLine(" this.my_parser = t_parser;"); cout.WriteLine(" }"); /* action method head */ cout.WriteLine(); cout.WriteLine(" /** Method with the actual generated action code. */"); cout.WriteLine(" public TUVienna.CS_CUP.Runtime.Symbol " + pre("do_action") + "("); cout.WriteLine(" int " + pre("act_num,")); cout.WriteLine(" TUVienna.CS_CUP.Runtime.lr_parser " + pre("parser,")); cout.WriteLine(" System.Collections.Stack xstack1,"); cout.WriteLine(" int " + pre("top)")); // cout.WriteLine(" throws java.lang.Exception"); cout.WriteLine(" {"); /* declaration of result symbol */ /* New declaration!! now return Symbol 6/13/96 frankf */ cout.WriteLine(" /* Symbol object for return from actions */"); cout.WriteLine(" mStack "+pre("stack")+" =new mStack(xstack1);"); cout.WriteLine(" TUVienna.CS_CUP.Runtime.Symbol " + pre("result") + ";"); cout.WriteLine(); /* switch top */ cout.WriteLine(" /* select the action based on the action number */"); cout.WriteLine(" switch (" + pre("act_num") + ")"); cout.WriteLine(" {"); /* emit action code for each production as a separate case */ IEnumerator p = production.all(); while ( p.MoveNext()) { prod = (production)p.Current; /* case label */ cout.WriteLine(" /*. . . . . . . . . . . . . . . . . . . .*/"); cout.WriteLine(" case " + prod.index() + ": // " + prod.to_simple_string()); /* give them their own block to work in */ cout.WriteLine(" {"); /* 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 */ cout.WriteLine(" " + prod.lhs().the_symbol().stack_type() + " RESULT = null;"); /* Add code to propagate RESULT assignments that occur in * action code embedded in a production (ie, non-rightmost * action code). 24-Mar-1998 CSA */ for (int i=0; i<prod.rhs_length(); i++) { // only interested in non-terminal symbols. if (prod.rhs(i).GetType()!= typeof(symbol_part)) continue; symbol s = ((symbol_part)prod.rhs(i)).the_symbol(); if (s.GetType()!=typeof(non_terminal)) continue; // skip this non-terminal unless it corresponds to // an embedded action production. if (((non_terminal)s).is_embedded_action == false) continue; // OK, it fits. Make a conditional assignment to RESULT. int index = prod.rhs_length() - i - 1; // last rhs is on top. cout.WriteLine(" " + "// propagate RESULT from " + s.name()); cout.WriteLine(" " + "if ( " + "((TUVienna.CS_CUP.Runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + index + ")).value != null )"); cout.WriteLine(" " + "RESULT = " + "(" + prod.lhs().the_symbol().stack_type() + ") " + "((TUVienna.CS_CUP.Runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + index + ")).value;"); } /* if there is an action string, emit it */ if (prod.action() != null && prod.action().code_string() != null && !prod.action().Equals("")) cout.WriteLine(prod.action().code_string()); /* here we have the left and right values being propagated. must make this a command line option. frankf 6/18/96 */ /* Create the code that assigns the left and right values of the new Symbol that the production is reducing to */ if (emit.lr_values()) { int loffset; string leftstring, rightstring; int roffset = 0; rightstring = "((TUVienna.CS_CUP.Runtime.Symbol)" + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + roffset + ")).right"; if (prod.rhs_length() == 0) leftstring = rightstring; else { loffset = prod.rhs_length() - 1; leftstring = "((TUVienna.CS_CUP.Runtime.Symbol)" + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + loffset + ")).left"; } cout.WriteLine(" " + pre("result") + " = new TUVienna.CS_CUP.Runtime.Symbol(" + prod.lhs().the_symbol().index() + "/*" + prod.lhs().the_symbol().name() + "*/" + ", " + leftstring + ", " + rightstring + ", RESULT);"); } else { cout.WriteLine(" " + pre("result") + " = new TUVienna.CS_CUP.Runtime.Symbol(" + prod.lhs().the_symbol().index() + "/*" + prod.lhs().the_symbol().name() + "*/" + ", RESULT);"); } /* end of their block */ cout.WriteLine(" }"); /* if this was the start production, do action for accept */ if (prod == start_prod) { cout.WriteLine(" /* ACCEPT */"); cout.WriteLine(" " + pre("parser") + ".done_parsing();"); } /* code to return lhs symbol */ cout.WriteLine(" return " + pre("result") + ";"); cout.WriteLine(); } /* end of switch */ cout.WriteLine(" /* . . . . . .*/"); cout.WriteLine(" default:"); cout.WriteLine(" throw new System.Exception("); cout.WriteLine(" \"Invalid action number found in " + "internal parse table\");"); cout.WriteLine(); cout.WriteLine(" }"); /* end of method */ cout.WriteLine(" }"); /* end of class */ cout.WriteLine("}"); cout.WriteLine(); action_code_time = DateTime.Now.Ticks - 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(TextWriter cout, production start_prod) { production prod; long start_time = DateTime.Now.Ticks; /* class header */ cout.WriteLine(); cout.WriteLine( "/** Cup generated class to encapsulate user supplied action code.*/" ); cout.WriteLine("public class " + pre("actions") + " {"); /* user supplied code */ if (action_code != null) { cout.WriteLine(); cout.WriteLine(action_code); } /* field for parser object */ cout.WriteLine(" private " + parser_class_name + " my_parser;"); /* constructor */ cout.WriteLine(); cout.WriteLine(" /** Constructor */"); cout.WriteLine(" public " + pre("actions") + "(" + parser_class_name + " t_parser) {"); cout.WriteLine(" this.my_parser = t_parser;"); cout.WriteLine(" }"); /* action method head */ cout.WriteLine(); cout.WriteLine(" /** Method with the actual generated action code. */"); cout.WriteLine(" public TUVienna.CS_CUP.Runtime.Symbol " + pre("do_action") + "("); cout.WriteLine(" int " + pre("act_num,")); cout.WriteLine(" TUVienna.CS_CUP.Runtime.lr_parser " + pre("parser,")); cout.WriteLine(" System.Collections.Stack xstack1,"); cout.WriteLine(" int " + pre("top)")); // cout.WriteLine(" throws java.lang.Exception"); cout.WriteLine(" {"); /* declaration of result symbol */ /* New declaration!! now return Symbol * 6/13/96 frankf */ cout.WriteLine(" /* Symbol object for return from actions */"); cout.WriteLine(" mStack " + pre("stack") + " =new mStack(xstack1);"); cout.WriteLine(" TUVienna.CS_CUP.Runtime.Symbol " + pre("result") + ";"); cout.WriteLine(); /* switch top */ cout.WriteLine(" /* select the action based on the action number */"); cout.WriteLine(" switch (" + pre("act_num") + ")"); cout.WriteLine(" {"); /* emit action code for each production as a separate case */ IEnumerator p = production.all(); while (p.MoveNext()) { prod = (production)p.Current; /* case label */ cout.WriteLine(" /*. . . . . . . . . . . . . . . . . . . .*/"); cout.WriteLine(" case " + prod.index() + ": // " + prod.to_simple_string()); /* give them their own block to work in */ cout.WriteLine(" {"); /* 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 */ cout.WriteLine(" " + prod.lhs().the_symbol().stack_type() + " RESULT = null;"); /* Add code to propagate RESULT assignments that occur in * action code embedded in a production (ie, non-rightmost * action code). 24-Mar-1998 CSA */ for (int i = 0; i < prod.rhs_length(); i++) { // only interested in non-terminal symbols. if (prod.rhs(i).GetType() != typeof(symbol_part)) { continue; } symbol s = ((symbol_part)prod.rhs(i)).the_symbol(); if (s.GetType() != typeof(non_terminal)) { continue; } // skip this non-terminal unless it corresponds to // an embedded action production. if (((non_terminal)s).is_embedded_action == false) { continue; } // OK, it fits. Make a conditional assignment to RESULT. int index = prod.rhs_length() - i - 1; // last rhs is on top. cout.WriteLine(" " + "// propagate RESULT from " + s.name()); cout.WriteLine(" " + "if ( " + "((TUVienna.CS_CUP.Runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + index + ")).value != null )"); cout.WriteLine(" " + "RESULT = " + "(" + prod.lhs().the_symbol().stack_type() + ") " + "((TUVienna.CS_CUP.Runtime.Symbol) " + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + index + ")).value;"); } /* if there is an action string, emit it */ if (prod.action() != null && prod.action().code_string() != null && !prod.action().Equals("")) { cout.WriteLine(prod.action().code_string()); } /* here we have the left and right values being propagated. * must make this a command line option. * frankf 6/18/96 */ /* Create the code that assigns the left and right values of * the new Symbol that the production is reducing to */ if (emit.lr_values()) { int loffset; string leftstring, rightstring; int roffset = 0; rightstring = "((TUVienna.CS_CUP.Runtime.Symbol)" + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + roffset + ")).right"; if (prod.rhs_length() == 0) { leftstring = rightstring; } else { loffset = prod.rhs_length() - 1; leftstring = "((TUVienna.CS_CUP.Runtime.Symbol)" + emit.pre("stack") + ".elementAt(" + emit.pre("top") + "-" + loffset + ")).left"; } cout.WriteLine(" " + pre("result") + " = new TUVienna.CS_CUP.Runtime.Symbol(" + prod.lhs().the_symbol().index() + "/*" + prod.lhs().the_symbol().name() + "*/" + ", " + leftstring + ", " + rightstring + ", RESULT);"); } else { cout.WriteLine(" " + pre("result") + " = new TUVienna.CS_CUP.Runtime.Symbol(" + prod.lhs().the_symbol().index() + "/*" + prod.lhs().the_symbol().name() + "*/" + ", RESULT);"); } /* end of their block */ cout.WriteLine(" }"); /* if this was the start production, do action for accept */ if (prod == start_prod) { cout.WriteLine(" /* ACCEPT */"); cout.WriteLine(" " + pre("parser") + ".done_parsing();"); } /* code to return lhs symbol */ cout.WriteLine(" return " + pre("result") + ";"); cout.WriteLine(); } /* end of switch */ cout.WriteLine(" /* . . . . . .*/"); cout.WriteLine(" default:"); cout.WriteLine(" throw new System.Exception("); cout.WriteLine(" \"Invalid action number found in " + "internal parse table\");"); cout.WriteLine(); cout.WriteLine(" }"); /* end of method */ cout.WriteLine(" }"); /* end of class */ cout.WriteLine("}"); cout.WriteLine(); action_code_time = DateTime.Now.Ticks - start_time; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** 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( TextWriter cout, parse_action_table action_table, parse_reduce_table reduce_table, int start_st, production start_prod, bool compact_reduces, bool suppress_scanner) { long start_time = DateTime.Now.Ticks; /* top of file */ cout.WriteLine(); cout.WriteLine("//----------------------------------------------------"); cout.WriteLine("// The following code was generated by " + version.title_str); cout.WriteLine("// " + DateTime.Now); cout.WriteLine("//----------------------------------------------------"); cout.WriteLine(); emit_package(cout); /* user supplied imports */ IEnumerator myEnum = import_list.GetEnumerator(); while (myEnum.MoveNext()) { cout.WriteLine("using " + myEnum.Current.ToString() + ";"); } /* class header */ cout.WriteLine(); cout.WriteLine("/** " + version.title_str + " generated parser."); cout.WriteLine(" * @version " + DateTime.Now); cout.WriteLine(" */"); cout.WriteLine("public class " + parser_class_name + " : TUVienna.CS_CUP.Runtime.lr_parser {"); /* constructors [CSA/davidm, 24-jul-99] */ cout.WriteLine(); cout.WriteLine(" /** Default constructor. */"); cout.WriteLine(" public " + parser_class_name + "():base() {;}"); if (!suppress_scanner) { cout.WriteLine(); cout.WriteLine(" /** Constructor which sets the default scanner. */"); cout.WriteLine(" public " + parser_class_name + "(TUVienna.CS_CUP.Runtime.Scanner s): base(s) {;}"); } /* emit the various tables */ emit_production_table(cout); do_action_table(cout, action_table, compact_reduces); do_reduce_table(cout, reduce_table); /* instance of the action encapsulation class */ cout.WriteLine(" /** Instance of action encapsulation class. */"); cout.WriteLine(" protected " + pre("actions") + " action_obj;"); cout.WriteLine(); /* action object initializer */ cout.WriteLine(" /** Action encapsulation object initializer. */"); cout.WriteLine(" protected override void init_actions()"); cout.WriteLine(" {"); cout.WriteLine(" action_obj = new " + pre("actions") + "(this);"); cout.WriteLine(" }"); cout.WriteLine(); /* access to action code */ cout.WriteLine(" /** Invoke a user supplied parse action. */"); cout.WriteLine(" public override TUVienna.CS_CUP.Runtime.Symbol do_action("); cout.WriteLine(" int act_num,"); cout.WriteLine(" TUVienna.CS_CUP.Runtime.lr_parser parser,"); cout.WriteLine(" System.Collections.Stack xstack1,"); cout.WriteLine(" int top)"); cout.WriteLine(" {"); cout.WriteLine(" mStack CUP_parser_stack= new mStack(xstack1);"); cout.WriteLine(" /* call code in generated class */"); cout.WriteLine(" return action_obj." + pre("do_action(") + "act_num, parser, stack, top);"); cout.WriteLine(" }"); cout.WriteLine(""); /* method to tell the parser about the start state */ cout.WriteLine(" /** Indicates start state. */"); cout.WriteLine(" public override int start_state() {return " + start_st + ";}"); /* method to indicate start production */ cout.WriteLine(" /** Indicates start production. */"); cout.WriteLine(" public override int start_production() {return " + start_production.index() + ";}"); cout.WriteLine(); /* methods to indicate EOF and error symbol indexes */ cout.WriteLine(" /** <code>EOF</code> Symbol index. */"); cout.WriteLine(" public override int EOF_sym() {return " + terminal.EOF.index() + ";}"); cout.WriteLine(); cout.WriteLine(" /** <code>error</code> Symbol index. */"); cout.WriteLine(" public override int error_sym() {return " + terminal.error.index() + ";}"); cout.WriteLine(); /* user supplied code for user_init() */ if (init_code != null) { cout.WriteLine(); cout.WriteLine(" /** User initialization code. */"); cout.WriteLine(" public override void user_init() "); cout.WriteLine(" {"); cout.WriteLine(init_code); cout.WriteLine(" }"); } /* user supplied code for scan */ if (scan_code != null) { cout.WriteLine(); cout.WriteLine(" /** Scan to get the next Symbol. */"); cout.WriteLine(" public override TUVienna.CS_CUP.Runtime.Symbol scan()"); cout.WriteLine(" {"); cout.WriteLine(scan_code); cout.WriteLine(" }"); } /* user supplied code */ if (parser_code != null) { cout.WriteLine(); cout.WriteLine(parser_code); } /* end of class */ cout.WriteLine("}"); /* put out the action code class */ emit_action_code(cout, start_prod); if (package_name != null) { cout.WriteLine("}"); } parser_time = DateTime.Now.Ticks - start_time; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Build an LALR viable prefix recognition machine given a start * production. This method operates by first building a start state * from the start production (based on a single item with the dot at * the beginning and EOF as expected lookahead). Then for each state * it attempts to extend the machine by creating transitions out of * the state to new or existing states. When considering extension * from a state we make a transition on each symbol that appears before * the dot in some item. For example, if we have the items: <pre> * [A ::= a b * X c, {d,e}] * [B ::= a b * X d, {a,b}] * </pre> * in some state, then we would be making a transition under X to a new * state. This new state would be formed by a "kernel" of items * corresponding to moving the dot past the X. In this case: <pre> * [A ::= a b X * c, {d,e}] * [B ::= a b X * Y, {a,b}] * </pre> * The full state would then be formed by "closing" this kernel Set of * items so that it included items that represented productions of things * the parser was now looking for. In this case we would items * corresponding to productions of Y, since various forms of Y are expected * next when in this state (see lalr_item_set.compute_closure() for details * on closure). <p> * * The process of building the viable prefix recognizer terminates when no * new states can be added. However, in order to build a smaller number of * states (i.e., corresponding to LALR rather than canonical LR) the state * building process does not maintain full loookaheads in all items. * Consequently, after the machine is built, we go back and propagate * lookaheads through the constructed machine using a call to * propagate_all_lookaheads(). This makes use of propagation links * constructed during the closure and transition process. * * @param start_prod the start production of the grammar * @see java_cup.lalr_item_set#compute_closure * @see java_cup.lalr_state#propagate_all_lookaheads */ public static lalr_state build_machine(production start_prod) { 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; IEnumerator i, s, fix; /* sanity check */ if (start_prod == null) throw new internal_error( "Attempt to build viable prefix recognizer using a null production"); /* build item with dot at front of start production and EOF lookahead */ start_items = new lalr_item_set(); itm = new lalr_item(start_prod); itm.lookahead().add(terminal.EOF); start_items.add(itm); /* create copy the item Set to form the kernel */ kernel = new lalr_item_set(start_items); /* create the closure from that item Set */ start_items.compute_closure(); /* build a state out of that item Set and put it in our work Set */ start_state = new lalr_state(start_items); work_stack.Push(start_state); /* enter the state using the kernel as the key */ _all_kernels.Add(kernel, start_state); /* continue looking at new states until we have no more work to do */ while (work_stack.Count!=0) { /* remove a state from the work Set */ st = (lalr_state)work_stack.Pop(); /* gather up all the symbols that appear before dots */ outgoing = new symbol_set(); i = st.items().all(); while ( i.MoveNext() ) { itm = (lalr_item)i.Current; /* add the symbol before the dot (if any) to our collection */ sym = itm.symbol_after_dot(); if (sym != null) outgoing.add(sym); } /* now create a transition out for each individual symbol */ s = outgoing.all(); while ( s.MoveNext()) { sym = (symbol)s.Current; /* will be keeping the Set of items with propagate links */ linked_items = new lalr_item_set(); /* gather up shifted versions of all the items that have this symbol before the dot */ new_items = new lalr_item_set(); i = st.items().all(); while ( i.MoveNext()) { itm = (lalr_item)i.Current; /* if this is the symbol we are working on now, add to Set */ sym2 = itm.symbol_after_dot(); if (sym.Equals(sym2)) { /* add to the kernel of the new state */ new_items.add(itm.shift()); /* remember that itm has propagate link to it */ linked_items.add(itm); } } /* use new items as state kernel */ kernel = new lalr_item_set(new_items); /* have we seen this one already? */ new_st = (lalr_state)_all_kernels[kernel]; /* if we haven't, build a new state out of the item Set */ if (new_st == null) { /* compute closure of the kernel for the full item Set */ new_items.compute_closure(); /* build the new state */ new_st = new lalr_state(new_items); /* add the new state to our work Set */ work_stack.Push(new_st); /* put it in our kernel table */ _all_kernels.Add(kernel, new_st); } /* otherwise relink propagation to items in existing state */ else { /* walk through the items that have links to the new state */ fix = linked_items.all(); while ( fix.MoveNext() ) { fix_itm = (lalr_item)fix.Current; /* look at each propagate link out of that item */ for (int l =0; l < fix_itm.propagate_items().Count; l++) { /* pull out item linked to in the new state */ new_itm =(lalr_item) fix_itm.propagate_items().ToArray()[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.set_propagate_item(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; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Constructor with default position and empty lookahead Set. * @param prod the production for the item. */ public lalr_item(production prod) : this(prod, 0, new terminal_set()) { }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Equality comparison. */ public bool Equals(production other) { if (other == null) return false; return other._index == _index; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Constructor with default position and empty lookahead Set. * @param prod the production for the item. */ public lalr_item(production prod) : this(prod,0,new terminal_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 bool fix_with_precedence( production p, int term_index, parse_action_row table_row, parse_action act) { terminal term = terminal.find(term_index); /* if the production has a precedence number, it can be fixed */ if (p.precedence_num() > assoc.no_prec) { /* if production precedes terminal, put reduce in table */ if (p.precedence_num() > term.precedence_num()) { table_row.under_term[term_index] = insert_reduce(table_row.under_term[term_index], act); return(true); } /* if terminal precedes rule, put shift in table */ else if (p.precedence_num() < term.precedence_num()) { table_row.under_term[term_index] = insert_shift(table_row.under_term[term_index], act); return(true); } else /* they are == precedence */ /* equal precedences have equal sides, so only need to * look at one: if it is right, put shift in table */ { if (term.precedence_side() == assoc.right) { table_row.under_term[term_index] = insert_shift(table_row.under_term[term_index], act); return(true); } /* if it is left, put reduce in table */ else if (term.precedence_side() == assoc.left) { table_row.under_term[term_index] = insert_reduce(table_row.under_term[term_index], act); return(true); } /* if it is nonassoc, we're not allowed to have two nonassocs * of equal precedence in a row, so put in NONASSOC */ else if (term.precedence_side() == assoc.nonassoc) { table_row.under_term[term_index] = new nonassoc_action(); return(true); } else { /* something really went wrong */ throw new internal_error("Unable to resolve conflict correctly"); } } } /* check if terminal has precedence, if so, shift, since * rule does not have precedence */ else if (term.precedence_num() > assoc.no_prec) { table_row.under_term[term_index] = insert_shift(table_row.under_term[term_index], act); return(true); } /* otherwise, neither the rule nor the terminal has a precedence, * so it can't be fixed. */ return(false); }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Fill in the parse table entries for this state. There are two * parse tables that encode the viable prefix recognition machine, an * action table and a reduce-goto table. The rows in each table * correspond to states of the machine. The columns of the action table * are indexed by terminal symbols and correspond to either transitions * out of the state (shift entries) or reductions from the state to some * previous state saved on the stack (reduce entries). All entries in the * action table that are not shifts or reduces, represent errors. The * reduce-goto table is indexed by non terminals and represents transitions * out of a state on that non-terminal.<p> * Conflicts occur if more than one action needs to go in one entry of the * action table (this cannot happen with the reduce-goto table). Conflicts * are resolved by always shifting for shift/reduce conflicts and choosing * the lowest numbered production (hence the one that appeared first in * the specification) in reduce/reduce conflicts. All conflicts are * reported and if more conflicts are detected than were declared by the * user, code generation is aborted. * * @param act_table the action table to put entries in. * @param reduce_table the reduce-goto table to put entries in. */ public void build_table_entries( parse_action_table act_table, parse_reduce_table reduce_table) { parse_action_row our_act_row; parse_reduce_row our_red_row; lalr_item itm; parse_action act, other_act; symbol sym; terminal_set conflict_set = new terminal_set(); /* pull out our rows from the tables */ our_act_row = act_table.under_state[index()]; our_red_row = reduce_table.under_state[index()]; /* consider each item in our state */ IEnumerator i = items().all(); while (i.MoveNext()) { itm = (lalr_item)i.Current; /* if its completed (dot at end) then reduce under the lookahead */ if (itm.dot_at_end()) { act = new reduce_action(itm.the_production()); /* consider each lookahead symbol */ for (int t = 0; t < terminal.number(); t++) { /* skip over the ones not in the lookahead */ if (!itm.lookahead().contains(t)) { continue; } /* if we don't already have an action put this one in */ if (our_act_row.under_term[t].kind() == parse_action.ERROR) { our_act_row.under_term[t] = act; } else { /* we now have at least one conflict */ terminal term = terminal.find(t); other_act = our_act_row.under_term[t]; /* if the other act was not a shift */ if ((other_act.kind() != parse_action.SHIFT) && (other_act.kind() != parse_action.NONASSOC)) { /* if we have lower index hence priority, replace it*/ if (itm.the_production().index() < ((reduce_action)other_act).reduce_with().index()) { /* replace the action */ our_act_row.under_term[t] = act; } } else { /* Check precedences,see if problem is correctable */ if (fix_with_precedence(itm.the_production(), t, our_act_row, act)) { term = null; } } if (term != null) { conflict_set.add(term); } } } } } /* consider each outgoing transition */ for (lalr_transition trans = transitions(); trans != null; trans = trans.next()) { /* if its on an terminal add a shift entry */ sym = trans.on_symbol(); if (!sym.is_non_term()) { act = new shift_action(trans.to_state()); /* if we don't already have an action put this one in */ if (our_act_row.under_term[sym.index()].kind() == parse_action.ERROR) { our_act_row.under_term[sym.index()] = act; } else { /* we now have at least one conflict */ production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with(); /* shift always wins */ if (!fix_with_precedence(p, sym.index(), our_act_row, act)) { our_act_row.under_term[sym.index()] = act; conflict_set.add(terminal.find(sym.index())); } } } else { /* for non terminals add an entry to the reduce-goto table */ our_red_row.under_non_term[sym.index()] = trans.to_state(); } } /* if we end up with conflict(s), report them */ if (!conflict_set.empty()) { report_conflicts(conflict_set); } }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Build an LALR viable prefix recognition machine given a start * production. This method operates by first building a start state * from the start production (based on a single item with the dot at * the beginning and EOF as expected lookahead). Then for each state * it attempts to extend the machine by creating transitions out of * the state to new or existing states. When considering extension * from a state we make a transition on each symbol that appears before * the dot in some item. For example, if we have the items: <pre> * [A ::= a b * X c, {d,e}] * [B ::= a b * X d, {a,b}] * </pre> * in some state, then we would be making a transition under X to a new * state. This new state would be formed by a "kernel" of items * corresponding to moving the dot past the X. In this case: <pre> * [A ::= a b X * c, {d,e}] * [B ::= a b X * Y, {a,b}] * </pre> * The full state would then be formed by "closing" this kernel Set of * items so that it included items that represented productions of things * the parser was now looking for. In this case we would items * corresponding to productions of Y, since various forms of Y are expected * next when in this state (see lalr_item_set.compute_closure() for details * on closure). <p> * * The process of building the viable prefix recognizer terminates when no * new states can be added. However, in order to build a smaller number of * states (i.e., corresponding to LALR rather than canonical LR) the state * building process does not maintain full loookaheads in all items. * Consequently, after the machine is built, we go back and propagate * lookaheads through the constructed machine using a call to * propagate_all_lookaheads(). This makes use of propagation links * constructed during the closure and transition process. * * @param start_prod the start production of the grammar * @see java_cup.lalr_item_set#compute_closure * @see java_cup.lalr_state#propagate_all_lookaheads */ public static lalr_state build_machine(production start_prod) { 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; IEnumerator i, s, fix; /* sanity check */ if (start_prod == null) { throw new internal_error( "Attempt to build viable prefix recognizer using a null production"); } /* build item with dot at front of start production and EOF lookahead */ start_items = new lalr_item_set(); itm = new lalr_item(start_prod); itm.lookahead().add(terminal.EOF); start_items.add(itm); /* create copy the item Set to form the kernel */ kernel = new lalr_item_set(start_items); /* create the closure from that item Set */ start_items.compute_closure(); /* build a state out of that item Set and put it in our work Set */ start_state = new lalr_state(start_items); work_stack.Push(start_state); /* enter the state using the kernel as the key */ _all_kernels.Add(kernel, start_state); /* continue looking at new states until we have no more work to do */ while (work_stack.Count != 0) { /* remove a state from the work Set */ st = (lalr_state)work_stack.Pop(); /* gather up all the symbols that appear before dots */ outgoing = new symbol_set(); i = st.items().all(); while (i.MoveNext()) { itm = (lalr_item)i.Current; /* add the symbol before the dot (if any) to our collection */ sym = itm.symbol_after_dot(); if (sym != null) { outgoing.add(sym); } } /* now create a transition out for each individual symbol */ s = outgoing.all(); while (s.MoveNext()) { sym = (symbol)s.Current; /* will be keeping the Set of items with propagate links */ linked_items = new lalr_item_set(); /* gather up shifted versions of all the items that have this * symbol before the dot */ new_items = new lalr_item_set(); i = st.items().all(); while (i.MoveNext()) { itm = (lalr_item)i.Current; /* if this is the symbol we are working on now, add to Set */ sym2 = itm.symbol_after_dot(); if (sym.Equals(sym2)) { /* add to the kernel of the new state */ new_items.add(itm.shift()); /* remember that itm has propagate link to it */ linked_items.add(itm); } } /* use new items as state kernel */ kernel = new lalr_item_set(new_items); /* have we seen this one already? */ new_st = (lalr_state)_all_kernels[kernel]; /* if we haven't, build a new state out of the item Set */ if (new_st == null) { /* compute closure of the kernel for the full item Set */ new_items.compute_closure(); /* build the new state */ new_st = new lalr_state(new_items); /* add the new state to our work Set */ work_stack.Push(new_st); /* put it in our kernel table */ _all_kernels.Add(kernel, new_st); } /* otherwise relink propagation to items in existing state */ else { /* walk through the items that have links to the new state */ fix = linked_items.all(); while (fix.MoveNext()) { fix_itm = (lalr_item)fix.Current; /* look at each propagate link out of that item */ for (int l = 0; l < fix_itm.propagate_items().Count; l++) { /* pull out item linked to in the new state */ new_itm = (lalr_item)fix_itm.propagate_items().ToArray()[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.set_propagate_item(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); }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** 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 bool fix_with_precedence( production p, int term_index, parse_action_row table_row, parse_action act) { terminal term = terminal.find(term_index); /* if the production has a precedence number, it can be fixed */ if (p.precedence_num() > assoc.no_prec) { /* if production precedes terminal, put reduce in table */ if (p.precedence_num() > term.precedence_num()) { table_row.under_term[term_index] = insert_reduce(table_row.under_term[term_index],act); return true; } /* if terminal precedes rule, put shift in table */ else if (p.precedence_num() < term.precedence_num()) { table_row.under_term[term_index] = insert_shift(table_row.under_term[term_index],act); return true; } else { /* they are == precedence */ /* equal precedences have equal sides, so only need to look at one: if it is right, put shift in table */ if (term.precedence_side() == assoc.right) { table_row.under_term[term_index] = insert_shift(table_row.under_term[term_index],act); return true; } /* if it is left, put reduce in table */ else if (term.precedence_side() == assoc.left) { table_row.under_term[term_index] = insert_reduce(table_row.under_term[term_index],act); return true; } /* if it is nonassoc, we're not allowed to have two nonassocs of equal precedence in a row, so put in NONASSOC */ else if (term.precedence_side() == assoc.nonassoc) { table_row.under_term[term_index] = new nonassoc_action(); return true; } else { /* something really went wrong */ throw new internal_error("Unable to resolve conflict correctly"); } } } /* check if terminal has precedence, if so, shift, since rule does not have precedence */ else if (term.precedence_num() > assoc.no_prec) { table_row.under_term[term_index] = insert_shift(table_row.under_term[term_index],act); return true; } /* otherwise, neither the rule nor the terminal has a precedence, so it can't be fixed. */ return false; }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** Add a production to our Set of productions. */ public void add_production(production prod) { /* 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.Add(prod,prod); }
/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** 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) : this(prod,0,look) { // this(prod,0,look); }
/*-----------------------------------------------------------*/ /*--- 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) : base(prod, pos) { _lookahead = look; _propagate_items = new Stack(); needs_propagation = true; }
/*-----------------------------------------------------------*/ /*--- 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) : base(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) : this(prod, 0, look) { // this(prod,0,look); }