package java_cup ;
import java.util.BitSet ;
/**
* A set of terminals implemented as a bitset.
*
* @version last updated: 11/25/95
* @author Scott Hudson
*/
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 ;
}
/*-----------------------------------------------------------*/
}