| |
| package java_cup; |
| |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| |
| /** This class represents a set of symbols and provides a series of |
| * set operations to manipulate them. |
| * |
| * @see java_cup.symbol |
| * @version last updated: 11/25/95 |
| * @author Scott Hudson |
| */ |
| public class symbol_set { |
| |
| /*-----------------------------------------------------------*/ |
| /*--- Constructor(s) ----------------------------------------*/ |
| /*-----------------------------------------------------------*/ |
| |
| /** Constructor for an empty set. */ |
| public symbol_set() { }; |
| |
| /** Constructor for cloning from another set. |
| * @param other the set we are cloning from. |
| */ |
| public symbol_set(symbol_set other) throws internal_error |
| { |
| not_null(other); |
| _all = (Hashtable)other._all.clone(); |
| }; |
| |
| /*-----------------------------------------------------------*/ |
| /*--- (Access to) Instance Variables ------------------------*/ |
| /*-----------------------------------------------------------*/ |
| |
| /** A hash table to hold the set. Symbols are keyed using their name string. |
| */ |
| protected Hashtable _all = new Hashtable(11); |
| |
| /** Access to all elements of the set. */ |
| public Enumeration all() {return _all.elements();}; |
| |
| /** size of the set */ |
| public int size() {return _all.size();}; |
| |
| /*-----------------------------------------------------------*/ |
| /*--- (Access to) Instance Variables ------------------------*/ |
| /*-----------------------------------------------------------*/ |
| |
| /** 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 contains a particular symbol. |
| * @param sym the symbol we are looking for. |
| */ |
| public boolean contains(symbol sym) {return _all.containsKey(sym.name());}; |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Determine if this set is an (improper) subset of another. |
| * @param other the set we are testing against. |
| */ |
| public boolean is_subset_of(symbol_set other) throws internal_error |
| { |
| not_null(other); |
| |
| /* walk down our set and make sure every element is in the other */ |
| for (Enumeration e = all(); e.hasMoreElements(); ) |
| if (!other.contains((symbol)e.nextElement())) |
| return false; |
| |
| /* they were all there */ |
| return true; |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Determine if this set is an (improper) superset of another. |
| * @param other the set we are are testing against. |
| */ |
| public boolean is_superset_of(symbol_set other) throws internal_error |
| { |
| not_null(other); |
| return other.is_subset_of(this); |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Add a single symbol to the set. |
| * @param sym the symbol we are adding. |
| * @return true if this changes the set. |
| */ |
| public boolean add(symbol sym) throws internal_error |
| { |
| Object previous; |
| |
| not_null(sym); |
| |
| /* put the object in */ |
| previous = _all.put(sym.name(),sym); |
| |
| /* if we had a previous, this is no change */ |
| return previous == null; |
| }; |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Remove a single symbol if it is in the set. |
| * @param sym the symbol we are removing. |
| */ |
| public void remove(symbol sym) throws internal_error |
| { |
| not_null(sym); |
| _all.remove(sym.name()); |
| }; |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Add (union) in a complete set. |
| * @param other the set we are adding in. |
| * @return true if this changes the set. |
| */ |
| public boolean add(symbol_set other) throws internal_error |
| { |
| boolean result = false; |
| |
| not_null(other); |
| |
| /* walk down the other set and do the adds individually */ |
| for (Enumeration e = other.all(); e.hasMoreElements(); ) |
| result = add((symbol)e.nextElement()) || result; |
| |
| return result; |
| }; |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Remove (set subtract) a complete set. |
| * @param other the set we are removing. |
| */ |
| public void remove(symbol_set other) throws internal_error |
| { |
| not_null(other); |
| |
| /* walk down the other set and do the removes individually */ |
| for (Enumeration e = other.all(); e.hasMoreElements(); ) |
| remove((symbol)e.nextElement()); |
| }; |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Equality comparison. */ |
| public boolean equals(symbol_set other) |
| { |
| if (other == null || other.size() != size()) return false; |
| |
| /* once we know they are the same size, then improper subset does test */ |
| try { |
| return is_subset_of(other); |
| } catch (internal_error e) { |
| /* can't throw the error (because super class doesn't), so we crash */ |
| e.crash(); |
| return false; |
| } |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Generic equality comparison. */ |
| public boolean equals(Object other) |
| { |
| if (!(other instanceof symbol_set)) |
| return false; |
| else |
| return equals((symbol_set)other); |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Compute a hash code. */ |
| public int hashCode() |
| { |
| int result = 0; |
| int cnt; |
| Enumeration e; |
| |
| /* hash together codes from at most first 5 elements */ |
| for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++) |
| result ^= ((symbol)e.nextElement()).hashCode(); |
| |
| return result; |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** Convert to a string. */ |
| public String toString() |
| { |
| String result; |
| boolean comma_flag; |
| |
| result = "{"; |
| comma_flag = false; |
| for (Enumeration e = all(); e.hasMoreElements(); ) |
| { |
| if (comma_flag) |
| result += ", "; |
| else |
| comma_flag = true; |
| |
| result += ((symbol)e.nextElement()).name(); |
| } |
| result += "}"; |
| |
| return result; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| }; |
| |
| |