diff options
Diffstat (limited to 'src/syntaxParser/java_cup/lalr_state.java')
| -rw-r--r-- | src/syntaxParser/java_cup/lalr_state.java | 884 |
1 files changed, 884 insertions, 0 deletions
diff --git a/src/syntaxParser/java_cup/lalr_state.java b/src/syntaxParser/java_cup/lalr_state.java new file mode 100644 index 0000000..5298e87 --- /dev/null +++ b/src/syntaxParser/java_cup/lalr_state.java @@ -0,0 +1,884 @@ + +package java_cup; + +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Stack; + +/** This class represents a state in the LALR viable prefix recognition machine. + * A state consists of an LALR item set and a set of transitions to other + * states under terminal and non-terminal symbols. Each state represents + * a potential configuration of the parser. If the item set of a state + * includes an item such as: <pre> + * [A ::= B * C d E , {a,b,c}] + * </pre> + * this indicates that when the parser is in this state it is currently + * looking for an A of the given form, has already seen the B, and would + * expect to see an a, b, or c after this sequence is complete. Note that + * the parser is normally looking for several things at once (represented + * by several items). In our example above, the state would also include + * items such as: <pre> + * [C ::= * X e Z, {d}] + * [X ::= * f, {e}] + * </pre> + * to indicate that it was currently looking for a C followed by a d (which + * would be reduced into a C, matching the first symbol in our production + * above), and the terminal f followed by e.<p> + * + * At runtime, the parser uses a viable prefix recognition machine made up + * of these states to parse. The parser has two operations, shift and reduce. + * In a shift, it consumes one Symbol and makes a transition to a new state. + * This corresponds to "moving the dot past" a terminal in one or more items + * in the state (these new shifted items will then be found in the state at + * the end of the transition). For a reduce operation, the parser is + * signifying that it is recognizing the RHS of some production. To do this + * it first "backs up" by popping a stack of previously saved states. It + * pops off the same number of states as are found in the RHS of the + * production. This leaves the machine in the same state is was in when the + * parser first attempted to find the RHS. From this state it makes a + * transition based on the non-terminal on the LHS of the production. This + * corresponds to placing the parse in a configuration equivalent to having + * replaced all the symbols from the the input corresponding to the RHS with + * the symbol on the LHS. + * + * @see java_cup.lalr_item + * @see java_cup.lalr_item_set + * @see java_cup.lalr_transition + * @version last updated: 7/3/96 + * @author Frank Flannery + * + */ + +public class lalr_state { + /*-----------------------------------------------------------*/ + /*--- Constructor(s) ----------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Constructor for building a state from a set of items. + * @param itms the set of items that makes up this state. + */ + public lalr_state(lalr_item_set itms) throws internal_error + { + /* don't allow null or duplicate item sets */ + if (itms == null) + throw new internal_error( + "Attempt to construct an LALR state from a null item set"); + + if (find_state(itms) != null) + throw new internal_error( + "Attempt to construct a duplicate LALR state"); + + /* assign a unique index */ + _index = next_index++; + + /* store the items */ + _items = itms; + + /* add to the global collection, keyed with its item set */ + _all.put(_items,this); + } + + /*-----------------------------------------------------------*/ + /*--- (Access to) Static (Class) Variables ------------------*/ + /*-----------------------------------------------------------*/ + + /** Collection of all states. */ + protected static Hashtable _all = new Hashtable(); + + /** Collection of all states. */ + public static Enumeration all() {return _all.elements();} + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Indicate total number of states there are. */ + public static int number() {return _all.size();} + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Hash table to find states by their kernels (i.e, the original, + * unclosed, set of items -- which uniquely define the state). This table + * stores state objects using (a copy of) their kernel item sets as keys. + */ + protected static Hashtable _all_kernels = new Hashtable(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Find and return state with a given a kernel item set (or null if not + * found). The kernel item set is the subset of items that were used to + * originally create the state. These items are formed by "shifting the + * dot" within items of other states that have a transition to this one. + * The remaining elements of this state's item set are added during closure. + * @param itms the kernel set of the state we are looking for. + */ + public static lalr_state find_state(lalr_item_set itms) + { + if (itms == null) + return null; + else + return (lalr_state)_all.get(itms); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Static counter for assigning unique state indexes. */ + protected static int next_index = 0; + + /*-----------------------------------------------------------*/ + /*--- (Access to) Instance Variables ------------------------*/ + /*-----------------------------------------------------------*/ + + /** The item set for this state. */ + protected lalr_item_set _items; + + /** The item set for this state. */ + public lalr_item_set items() {return _items;} + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** List of transitions out of this state. */ + protected lalr_transition _transitions = null; + + /** List of transitions out of this state. */ + public lalr_transition transitions() {return _transitions;} + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Index of this state in the parse tables */ + protected int _index; + + /** Index of this state in the parse tables */ + public int index() {return _index;} + + /*-----------------------------------------------------------*/ + /*--- Static Methods ----------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Helper routine for debugging -- produces a dump of the given state + * onto System.out. + */ + protected static void dump_state(lalr_state st) throws internal_error + { + lalr_item_set itms; + lalr_item itm; + production_part part; + + if (st == null) + { + System.out.println("NULL lalr_state"); + return; + } + + System.out.println("lalr_state [" + st.index() + "] {"); + itms = st.items(); + for (Enumeration e = itms.all(); e.hasMoreElements(); ) + { + itm = (lalr_item)e.nextElement(); + System.out.print(" ["); + System.out.print(itm.the_production().lhs().the_symbol().name()); + System.out.print(" ::= "); + for (int i = 0; i<itm.the_production().rhs_length(); i++) + { + if (i == itm.dot_pos()) System.out.print("(*) "); + part = itm.the_production().rhs(i); + if (part.is_action()) + System.out.print("{action} "); + else + System.out.print(((symbol_part)part).the_symbol().name() + " "); + } + if (itm.dot_at_end()) System.out.print("(*) "); + System.out.println("]"); + } + System.out.println("}"); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Propagate lookahead sets through the constructed viable prefix + * recognizer. When the machine is constructed, each item that results + in the creation of another such that its lookahead is included in the + other's will have a propagate link set up for it. This allows additions + to the lookahead of one item to be included in other items that it + was used to directly or indirectly create. + */ + protected static void propagate_all_lookaheads() throws internal_error + { + /* iterate across all states */ + for (Enumeration st = all(); st.hasMoreElements(); ) + { + /* propagate lookaheads out of that state */ + ((lalr_state)st.nextElement()).propagate_lookaheads(); + } + } + + /*-----------------------------------------------------------*/ + /*--- General Methods ---------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Add a transition out of this state to another. + * @param on_sym the symbol the transition is under. + * @param to_st the state the transition goes to. + */ + public void add_transition(symbol on_sym, lalr_state to_st) + throws internal_error + { + lalr_transition trans; + + /* create a new transition object and put it in our list */ + trans = new lalr_transition(on_sym, to_st, _transitions); + _transitions = trans; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** 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) + throws internal_error + { + lalr_state start_state; + lalr_item_set start_items; + lalr_item_set new_items; + lalr_item_set linked_items; + lalr_item_set kernel; + Stack work_stack = new Stack(); + lalr_state st, new_st; + symbol_set outgoing; + lalr_item itm, new_itm, existing, fix_itm; + symbol sym, sym2; + Enumeration i, s, fix; + + /* 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.put(kernel, start_state); + + /* continue looking at new states until we have no more work to do */ + while (!work_stack.empty()) + { + /* 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(); + for (i = st.items().all(); i.hasMoreElements(); ) + { + itm = (lalr_item)i.nextElement(); + + /* 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 */ + for (s = outgoing.all(); s.hasMoreElements(); ) + { + sym = (symbol)s.nextElement(); + + /* 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(); + for (i = st.items().all(); i.hasMoreElements();) + { + itm = (lalr_item)i.nextElement(); + + /* 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.get(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.put(kernel, new_st); + } + /* otherwise relink propagation to items in existing state */ + else + { + /* walk through the items that have links to the new state */ + for (fix = linked_items.all(); fix.hasMoreElements(); ) + { + fix_itm = (lalr_item)fix.nextElement(); + + /* look at each propagate link out of that item */ + for (int l =0; l < fix_itm.propagate_items().size(); l++) + { + /* pull out item linked to in the new state */ + new_itm = + (lalr_item)fix_itm.propagate_items().elementAt(l); + + /* find corresponding item in the existing state */ + existing = new_st.items().find(new_itm); + + /* fix up the item so it points to the existing set */ + if (existing != null) + fix_itm.propagate_items().setElementAt(existing ,l); + } + } + } + + /* add a transition from current state to that state */ + st.add_transition(sym, new_st); + } + } + + /* all done building states */ + + /* propagate complete lookahead sets throughout the states */ + propagate_all_lookaheads(); + + return start_state; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Propagate lookahead sets out of this state. This recursively + * propagates to all items that have propagation links from some item + * in this state. + */ + protected void propagate_lookaheads() throws internal_error + { + /* recursively propagate out from each item in the state */ + for (Enumeration itm = items().all(); itm.hasMoreElements(); ) + ((lalr_item)itm.nextElement()).propagate_lookaheads(null); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Fill in the parse table entries for this state. There are two + * parse tables that encode the viable prefix recognition machine, an + * action table and a reduce-goto table. The rows in each table + * correspond to states of the machine. The columns of the action table + * are indexed by terminal symbols and correspond to either transitions + * out of the state (shift entries) or reductions from the state to some + * previous state saved on the stack (reduce entries). All entries in the + * action table that are not shifts or reduces, represent errors. The + * reduce-goto table is indexed by non terminals and represents transitions + * out of a state on that non-terminal.<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) + throws internal_error + { + parse_action_row our_act_row; + parse_reduce_row our_red_row; + lalr_item itm; + parse_action act, other_act; + symbol sym; + terminal_set conflict_set = new terminal_set(); + + /* 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 */ + for (Enumeration i = items().all(); i.hasMoreElements(); ) + { + itm = (lalr_item)i.nextElement(); + + + /* 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); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + + /** Procedure that attempts to fix a shift/reduce error by using + * precedences. --frankf 6/26/96 + * + * if a production (also called rule) or the lookahead terminal + * has a precedence, then the table can be fixed. if the rule + * has greater precedence than the terminal, a reduce by that rule + * in inserted in the table. If the terminal has a higher precedence, + * it is shifted. if they have equal precedence, then the associativity + * of the precedence is used to determine what to put in the table: + * if the precedence is left associative, the action is to reduce. + * if the precedence is right associative, the action is to shift. + * if the precedence is non associative, then it is a syntax error. + * + * @param p the production + * @param term_index the index of the lokahead terminal + * @param parse_action_row a row of the action table + * @param act the rule in conflict with the table entry + */ + + protected boolean fix_with_precedence( + production p, + int term_index, + parse_action_row table_row, + parse_action act) + + throws internal_error { + + terminal term = terminal.find(term_index); + + /* if the production has a precedence number, it can be fixed */ + if (p.precedence_num() > assoc.no_prec) { + + /* if 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; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + + /* given two actions, and an action type, return the + action of that action type. give an error if they are of + the same action, because that should never have tried + to be fixed + + */ + protected parse_action insert_action( + parse_action a1, + parse_action a2, + int act_type) + throws internal_error + { + if ((a1.kind() == act_type) && (a2.kind() == act_type)) { + throw new internal_error("Conflict resolution of bogus actions"); + } else if (a1.kind() == act_type) { + return a1; + } else if (a2.kind() == act_type) { + return a2; + } else { + throw new internal_error("Conflict resolution of bogus actions"); + } + } + + /* find the shift in the two actions */ + protected parse_action insert_shift( + parse_action a1, + parse_action a2) + throws internal_error + { + return insert_action(a1, a2, parse_action.SHIFT); + } + + /* find the reduce in the two actions */ + protected parse_action insert_reduce( + parse_action a1, + parse_action a2) + throws internal_error + { + return insert_action(a1, a2, parse_action.REDUCE); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Produce warning messages for all conflicts found in this state. */ + protected void report_conflicts(terminal_set conflict_set) + throws internal_error + { + lalr_item itm, compare; + symbol shift_sym; + + boolean after_itm; + + /* consider each element */ + for (Enumeration itms = items().all(); itms.hasMoreElements(); ) + { + itm = (lalr_item)itms.nextElement(); + + /* clear the S/R conflict set for this item */ + + /* if it results in a reduce, it could be a conflict */ + if (itm.dot_at_end()) + { + /* not yet after itm */ + after_itm = false; + + /* compare this item against all others looking for conflicts */ + for (Enumeration comps = items().all(); comps.hasMoreElements(); ) + { + compare = (lalr_item)comps.nextElement(); + + /* if this is the item, next one is after it */ + if (itm == compare) after_itm = true; + + /* only look at it if its not the same item */ + if (itm != compare) + { + /* is it a reduce */ + if (compare.dot_at_end()) + { + /* only look at reduces after itm */ + if (after_itm) + /* does the comparison item conflict? */ + if (compare.lookahead().intersects(itm.lookahead())) + /* report a reduce/reduce conflict */ + report_reduce_reduce(itm, compare); + } + } + } + /* report S/R conflicts under all the symbols we conflict under */ + for (int t = 0; t < terminal.number(); t++) + if (conflict_set.contains(t)) + report_shift_reduce(itm,t); + } + } + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Produce a warning message for one reduce/reduce conflict. + * + * @param itm1 first item in conflict. + * @param itm2 second item in conflict. + */ + protected void report_reduce_reduce(lalr_item itm1, lalr_item itm2) + throws internal_error + { + boolean comma_flag = false; + + System.err.println("*** Reduce/Reduce conflict found in state #"+index()); + System.err.print (" between "); + System.err.println(itm1.to_simple_string()); + System.err.print (" and "); + System.err.println(itm2.to_simple_string()); + System.err.print(" under symbols: {" ); + for (int t = 0; t < terminal.number(); t++) + { + if (itm1.lookahead().contains(t) && itm2.lookahead().contains(t)) + { + if (comma_flag) System.err.print(", "); else comma_flag = true; + System.err.print(terminal.find(t).name()); + } + } + System.err.println("}"); + System.err.print(" Resolved in favor of "); + if (itm1.the_production().index() < itm2.the_production().index()) + System.err.println("the first production.\n"); + else + System.err.println("the second production.\n"); + + /* count the conflict */ + emit.num_conflicts++; + lexer.warning_count++; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Produce a warning message for one shift/reduce conflict. + * + * @param red_itm the item with the reduce. + * @param conflict_sym the index of the symbol conflict occurs under. + */ + protected void report_shift_reduce( + lalr_item red_itm, + int conflict_sym) + throws internal_error + { + lalr_item itm; + symbol shift_sym; + + /* emit top part of message including the reduce item */ + System.err.println("*** Shift/Reduce conflict found in state #"+index()); + System.err.print (" between "); + System.err.println(red_itm.to_simple_string()); + + /* find and report on all items that shift under our conflict symbol */ + for (Enumeration itms = items().all(); itms.hasMoreElements(); ) + { + itm = (lalr_item)itms.nextElement(); + + /* only look if its not the same item and not a reduce */ + if (itm != red_itm && !itm.dot_at_end()) + { + /* is it a shift on our conflicting terminal */ + shift_sym = itm.symbol_after_dot(); + if (!shift_sym.is_non_term() && shift_sym.index() == conflict_sym) + { + /* yes, report on it */ + System.err.println(" and " + itm.to_simple_string()); + } + } + } + System.err.println(" under symbol "+ terminal.find(conflict_sym).name()); + System.err.println(" Resolved in favor of shifting.\n"); + + /* count the conflict */ + emit.num_conflicts++; + lexer.warning_count++; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Equality comparison. */ + public boolean equals(lalr_state other) + { + /* we are equal if our item sets are equal */ + return other != null && items().equals(other.items()); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Generic equality comparison. */ + public boolean equals(Object other) + { + if (!(other instanceof lalr_state)) + return false; + else + return equals((lalr_state)other); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Produce a hash code. */ + public int hashCode() + { + /* just use the item set hash code */ + return items().hashCode(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Convert to a string. */ + public String toString() + { + String result; + lalr_transition tr; + + /* dump the item set */ + result = "lalr_state [" + index() + "]: " + _items + "\n"; + + /* do the transitions */ + for (tr = transitions(); tr != null; tr = tr.next()) + { + result += tr; + result += "\n"; + } + + return result; + } + + /*-----------------------------------------------------------*/ +} |
