| |
| package java_cup; |
| |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| 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 token 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: 11/25/95 |
| * @author Scott Hudson |
| * |
| */ |
| |
| 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; |
| boolean conflicted = false; |
| |
| /* 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 */ |
| conflicted = true; |
| |
| other_act = our_act_row.under_term[t]; |
| |
| /* if the other act was not a shift */ |
| if (other_act.kind() != parse_action.SHIFT) |
| { |
| /* 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; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /* 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 */ |
| conflicted = true; |
| |
| /* shift always wins */ |
| our_act_row.under_term[sym.index()] = act; |
| } |
| } |
| 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 (conflicted) |
| report_conflicts(); |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Produce warning messages for all conflicts found in this state. */ |
| protected void report_conflicts() |
| throws internal_error |
| { |
| lalr_item itm, compare; |
| symbol shift_sym; |
| terminal_set conflict_set; |
| 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 */ |
| conflict_set = new terminal_set(); |
| |
| /* 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); |
| } |
| /* must be a shift on a terminal or non-terminal */ |
| else |
| { |
| /* is it a shift on a terminal */ |
| shift_sym = compare.symbol_after_dot(); |
| if (!shift_sym.is_non_term()) |
| { |
| /* does the terminal conflict with our item */ |
| if (itm.lookahead().contains((terminal)shift_sym)) |
| /* remember the terminal symbol in conflict */ |
| conflict_set.add((terminal)shift_sym); |
| } |
| } |
| } |
| } |
| /* 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; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| }; |