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 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 ( ) ; } // Hm Added clear to clear all static fields public static void clear ( ) { _all.clear ( ) ; _all_kernels.clear ( ) ; next_index = 0 ; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** 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 ; String message = "*** Reduce/Reduce conflict found in state #" + index ( ) + "\n" + " between " + itm1.to_simple_string ( ) + "\n" + " and " + itm2.to_simple_string ( ) + "\n" + " under symbols: {" ; for ( int t = 0 ; t < terminal.number ( ) ; t ++ ) { if ( itm1.lookahead ( ).contains ( t ) && itm2.lookahead ( ).contains ( t ) ) { if ( comma_flag ) message += ( ", " ) ; else comma_flag = true ; message += ( terminal.find ( t ).name ( ) ) ; } } message += "}\n Resolved in favor of " ; if ( itm1.the_production ( ).index ( ) < itm2.the_production ( ).index ( ) ) message += "the first production.\n" ; else message += "the second production.\n" ; /* count the conflict */ emit.num_conflicts ++ ; ErrorManager.getManager ( ).emit_warning ( message ) ; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * 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 */ String message = "*** Shift/Reduce conflict found in state #" + index ( ) + "\n" + " between " + red_itm.to_simple_string ( ) + "\n" ; /* 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 */ message += " and " + itm.to_simple_string ( ) + "\n" ; } } } message += " under symbol " + terminal.find ( conflict_sym ).name ( ) + "\n" + " Resolved in favor of shifting.\n" ; /* count the conflict */ emit.num_conflicts ++ ; ErrorManager.getManager ( ).emit_warning ( message ) ; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** 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 ; } /*-----------------------------------------------------------*/ }