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
*/
@SuppressWarnings (
{ "all", "unchecked" } )
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 table_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;
}
/*-----------------------------------------------------------*/
}