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 */ 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 ; } } /*-----------------------------------------------------------*/ }