package java_cup;
import java.util.BitSet;
/**
* A set of terminals implemented as a bitset.
*
* @version last updated: 11/25/95
* @author Scott Hudson
*/
@SuppressWarnings (
{ "all" } )
public class terminal_set
{
/*-----------------------------------------------------------*/
/*--- Constructor(s) ----------------------------------------*/
/*-----------------------------------------------------------*/
/** Constructor for an empty set. */
public terminal_set ()
{
/* allocate the bitset at what is probably the right size */
_elements = new BitSet ( terminal.number () );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Constructor for cloning from another set.
*
* @param other the set we are cloning from.
*/
public terminal_set ( terminal_set other ) throws internal_error
{
not_null ( other );
_elements = ( BitSet ) other._elements.clone ();
}
/*-----------------------------------------------------------*/
/*--- (Access to) Static (Class) Variables ------------------*/
/*-----------------------------------------------------------*/
/** Constant for the empty set. */
public static final terminal_set EMPTY = new terminal_set ();
/*-----------------------------------------------------------*/
/*--- (Access to) Instance Variables ------------------------*/
/*-----------------------------------------------------------*/
/** Bitset to implement the actual set. */
protected BitSet _elements;
/*-----------------------------------------------------------*/
/*--- General Methods ----------------------------------------*/
/*-----------------------------------------------------------*/
/**
* Helper function to test for a null object and throw an exception if one is
* found.
*
* @param obj the object we are testing.
*/
protected void not_null ( Object obj ) throws internal_error
{
if ( obj == null )
throw new internal_error ( "Null object used in set operation" );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Determine if the set is empty. */
public boolean empty ()
{
return equals ( EMPTY );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Determine if the set contains a particular terminal.
*
* @param sym the terminal symbol we are looking for.
*/
public boolean contains ( terminal sym ) throws internal_error
{
not_null ( sym );
return _elements.get ( sym.index () );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Given its index determine if the set contains a particular terminal.
*
* @param indx the index of the terminal in question.
*/
public boolean contains ( int indx )
{
return _elements.get ( indx );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Determine if this set is an (improper) subset of another.
*
* @param other the set we are testing against.
*/
public boolean is_subset_of ( terminal_set other ) throws internal_error
{
not_null ( other );
/* make a copy of the other set */
BitSet copy_other = ( BitSet ) other._elements.clone ();
/* and or in */
copy_other.or ( _elements );
/* if it hasn't changed, we were a subset */
return copy_other.equals ( other._elements );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Determine if this set is an (improper) superset of another.
*
* @param other the set we are testing against.
*/
public boolean is_superset_of ( terminal_set other ) throws internal_error
{
not_null ( other );
return other.is_subset_of ( this );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Add a single terminal to the set.
*
* @param sym the terminal being added.
* @return true if this changes the set.
*/
public boolean add ( terminal sym ) throws internal_error
{
boolean result;
not_null ( sym );
/* see if we already have this */
result = _elements.get ( sym.index () );
/* if not we add it */
if ( !result )
_elements.set ( sym.index () );
return result;
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Remove a terminal if it is in the set.
*
* @param sym the terminal being removed.
*/
public void remove ( terminal sym ) throws internal_error
{
not_null ( sym );
_elements.clear ( sym.index () );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Add (union) in a complete set.
*
* @param other the set being added.
* @return true if this changes the set.
*/
public boolean add ( terminal_set other ) throws internal_error
{
not_null ( other );
/* make a copy */
BitSet copy = ( BitSet ) _elements.clone ();
/* or in the other set */
_elements.or ( other._elements );
/* changed if we are not the same as the copy */
return !_elements.equals ( copy );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/**
* Determine if this set intersects another.
*
* @param other the other set in question.
*/
public boolean intersects ( terminal_set other ) throws internal_error
{
not_null ( other );
/* make a copy of the other set */
BitSet copy = ( BitSet ) other._elements.clone ();
/* xor out our values */
copy.xor ( this._elements );
/* see if its different */
return !copy.equals ( other._elements );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Equality comparison. */
public boolean equals ( terminal_set other )
{
if ( other == null )
return false;
else
return _elements.equals ( other._elements );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Generic equality comparison. */
public boolean equals ( Object other )
{
if ( ! ( other instanceof terminal_set ) )
return false;
else
return equals ( ( terminal_set ) other );
}
/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
/** Convert to string. */
public String toString ()
{
String result;
boolean comma_flag;
result = "{";
comma_flag = false;
for ( int t = 0 ; t < terminal.number () ; t++ )
{
if ( _elements.get ( t ) )
{
if ( comma_flag )
result += ", ";
else
comma_flag = true;
result += terminal.find ( t ).name ();
}
}
result += "}";
return result;
}
/*-----------------------------------------------------------*/
}