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