/*
* This file is part of Petascope.
*
* Petascope is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Petascope is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Petascope. If not, see .
*
* For more information please see
* or contact Peter Baumann via .
*
* Copyright 2009 Jacobs University Bremen, Peter Baumann.
*/
package java_cup;
import java.util.BitSet;
/** A set of terminals implemented as a bitset.
*/
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;
}
/*-----------------------------------------------------------*/
}