package java_cup; /** * The "core" of an LR item. This includes a production and the position of a * marker (the "dot") within the production. Typically item cores are written * using a production with an embedded "dot" to indicate their position. For * example: * * <pre> * A ::= B * C d E * </pre> * * This represents a point in a parse where the parser is trying to match the * given production, and has succeeded in matching everything before the "dot" * (and hence is expecting to see the symbols after the dot next). See * lalr_item, lalr_item_set, and lalr_start for full details on the meaning and * use of items. * * @see java_cup.lalr_item * @see java_cup.lalr_item_set * @see java_cup.lalr_state * @version last updated: 11/25/95 * @author Scott Hudson */ @SuppressWarnings ( { "all" } ) public class lr_item_core { /*-----------------------------------------------------------*/ /*--- Constructor(s) ----------------------------------------*/ /*-----------------------------------------------------------*/ /** * Full constructor. * * @param prod production this item uses. * @param pos position of the "dot" within the item. */ public lr_item_core ( production prod, int pos ) throws internal_error { symbol after_dot = null; production_part part; if ( prod == null ) throw new internal_error ( "Attempt to create an lr_item_core with a null production" ); _the_production = prod; if ( pos < 0 || pos > _the_production.rhs_length () ) throw new internal_error ( "Attempt to create an lr_item_core with a bad dot position" ); _dot_pos = pos; /* compute and cache hash code now */ _core_hash_cache = 13 * _the_production.hashCode () + pos; /* cache the symbol after the dot */ if ( _dot_pos < _the_production.rhs_length () ) { part = _the_production.rhs ( _dot_pos ); if ( !part.is_action () ) _symbol_after_dot = ( ( symbol_part ) part ).the_symbol (); } } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Constructor for dot at start of right hand side. * * @param prod production this item uses. */ public lr_item_core ( production prod ) throws internal_error { this ( prod, 0 ); } /*-----------------------------------------------------------*/ /*--- (Access to) Instance Variables ------------------------*/ /*-----------------------------------------------------------*/ /** The production for the item. */ protected production _the_production; /** The production for the item. */ public production the_production () { return _the_production; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * The position of the "dot" -- this indicates the part of the production that * the marker is before, so 0 indicates a dot at the beginning of the RHS. */ protected int _dot_pos; /** * The position of the "dot" -- this indicates the part of the production that * the marker is before, so 0 indicates a dot at the beginning of the RHS. */ public int dot_pos () { return _dot_pos; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Cache of the hash code. */ protected int _core_hash_cache; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Cache of symbol after the dot. */ protected symbol _symbol_after_dot = null; /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Is the dot at the end of the production? */ public boolean dot_at_end () { return _dot_pos >= _the_production.rhs_length (); } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Return the symbol after the dot. If there is no symbol after the dot we * return null. */ public symbol symbol_after_dot () { /* use the cached symbol */ return _symbol_after_dot; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Determine if we have a dot before a non terminal, and if so which one * (return null or the non terminal). */ public non_terminal dot_before_nt () { symbol sym; /* get the symbol after the dot */ sym = symbol_after_dot (); /* if it exists and is a non terminal, return it */ if ( sym != null && sym.is_non_term () ) return ( non_terminal ) sym; else return null; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Produce a new lr_item_core that results from shifting the dot one position * to the right. */ public lr_item_core shift_core () throws internal_error { if ( dot_at_end () ) throw new internal_error ( "Attempt to shift past end of an lr_item_core" ); return new lr_item_core ( _the_production, _dot_pos + 1 ); } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Equality comparison for the core only. This is separate out because we need * separate access in a super class. */ public boolean core_equals ( lr_item_core other ) { return other != null && _the_production.equals ( other._the_production ) && _dot_pos == other._dot_pos; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Equality comparison. */ public boolean equals ( lr_item_core other ) { return core_equals ( other ); } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Generic equality comparison. */ public boolean equals ( Object other ) { if ( ! ( other instanceof lr_item_core ) ) return false; else return equals ( ( lr_item_core ) other ); } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Hash code for the core (separated so we keep non overridden version). */ public int core_hashCode () { return _core_hash_cache; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Hash code for the item. */ public int hashCode () { return _core_hash_cache; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Return the hash code that object would have provided for us so we have a * (nearly) unique id for debugging. */ protected int obj_hash () { return super.hashCode (); } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** * Convert to a string (separated out from toString() so we can call it from * subclass that overrides toString()). */ public String to_simple_string () throws internal_error { String result; production_part part; if ( _the_production.lhs () != null && _the_production.lhs ().the_symbol () != null && _the_production.lhs ().the_symbol ().name () != null ) result = _the_production.lhs ().the_symbol ().name (); else result = "$$NULL$$"; result += " ::= "; for ( int i = 0 ; i < _the_production.rhs_length () ; i++ ) { /* do we need the dot before this one? */ if ( i == _dot_pos ) result += "(*) "; /* print the name of the part */ if ( _the_production.rhs ( i ) == null ) { result += "$$NULL$$ "; } else { part = _the_production.rhs ( i ); if ( part == null ) result += "$$NULL$$ "; else if ( part.is_action () ) result += "{ACTION} "; else if ( ( ( symbol_part ) part ).the_symbol () != null && ( ( symbol_part ) part ).the_symbol ().name () != null ) result += ( ( symbol_part ) part ).the_symbol ().name () + " "; else result += "$$NULL$$ "; } } /* put the dot after if needed */ if ( _dot_pos == _the_production.rhs_length () ) result += "(*) "; return result; } /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ /** Convert to a string */ public String toString () { /* can't throw here since super class doesn't, so we crash instead */ try { return to_simple_string (); } catch ( internal_error e ) { e.crash (); return null; } } /*-----------------------------------------------------------*/ }