1 2 package java_cup; 3 4 import java.util.Enumeration; 5 import java.util.Hashtable; 6 7 /** This class represents a set of symbols and provides a series of 8 * set operations to manipulate them. 9 * 10 * @see java_cup.symbol 11 * @version last updated: 11/25/95 12 * @author Scott Hudson 13 */ 14 public class symbol_set { 15 16 /*-----------------------------------------------------------*/ 17 /*--- Constructor(s) ----------------------------------------*/ 18 /*-----------------------------------------------------------*/ 19 20 /** Constructor for an empty set. */ 21 public symbol_set() { }; 22 23 /** Constructor for cloning from another set. 24 * @param other the set we are cloning from. 25 */ 26 public symbol_set(symbol_set other) throws internal_error 27 { 28 not_null(other); 29 _all = (Hashtable)other._all.clone(); 30 }; 31 32 /*-----------------------------------------------------------*/ 33 /*--- (Access to) Instance Variables ------------------------*/ 34 /*-----------------------------------------------------------*/ 35 36 /** A hash table to hold the set. Symbols are keyed using their name string. 37 */ 38 protected Hashtable _all = new Hashtable(11); 39 40 /** Access to all elements of the set. */ 41 public Enumeration all() {return _all.elements();}; 42 43 /** size of the set */ 44 public int size() {return _all.size();}; 45 46 /*-----------------------------------------------------------*/ 47 /*--- (Access to) Instance Variables ------------------------*/ 48 /*-----------------------------------------------------------*/ 49 50 /** Helper function to test for a null object and throw an exception 51 * if one is found. 52 * @param obj the object we are testing. 53 */ 54 protected void not_null(Object obj) throws internal_error 55 { 56 if (obj == null) 57 throw new internal_error("Null object used in set operation"); 58 } 59 60 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 61 62 /** Determine if the set contains a particular symbol. 63 * @param sym the symbol we are looking for. 64 */ 65 public boolean contains(symbol sym) {return _all.containsKey(sym.name());}; 66 67 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 68 69 /** Determine if this set is an (improper) subset of another. 70 * @param other the set we are testing against. 71 */ 72 public boolean is_subset_of(symbol_set other) throws internal_error 73 { 74 not_null(other); 75 76 /* walk down our set and make sure every element is in the other */ 77 for (Enumeration e = all(); e.hasMoreElements(); ) 78 if (!other.contains((symbol)e.nextElement())) 79 return false; 80 81 /* they were all there */ 82 return true; 83 } 84 85 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 86 87 /** Determine if this set is an (improper) superset of another. 88 * @param other the set we are are testing against. 89 */ 90 public boolean is_superset_of(symbol_set other) throws internal_error 91 { 92 not_null(other); 93 return other.is_subset_of(this); 94 } 95 96 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 97 98 /** Add a single symbol to the set. 99 * @param sym the symbol we are adding. 100 * @return true if this changes the set. 101 */ 102 public boolean add(symbol sym) throws internal_error 103 { 104 Object previous; 105 106 not_null(sym); 107 108 /* put the object in */ 109 previous = _all.put(sym.name(),sym); 110 111 /* if we had a previous, this is no change */ 112 return previous == null; 113 }; 114 115 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 116 117 /** Remove a single symbol if it is in the set. 118 * @param sym the symbol we are removing. 119 */ 120 public void remove(symbol sym) throws internal_error 121 { 122 not_null(sym); 123 _all.remove(sym.name()); 124 }; 125 126 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 127 128 /** Add (union) in a complete set. 129 * @param other the set we are adding in. 130 * @return true if this changes the set. 131 */ 132 public boolean add(symbol_set other) throws internal_error 133 { 134 boolean result = false; 135 136 not_null(other); 137 138 /* walk down the other set and do the adds individually */ 139 for (Enumeration e = other.all(); e.hasMoreElements(); ) 140 result = add((symbol)e.nextElement()) || result; 141 142 return result; 143 }; 144 145 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 146 147 /** Remove (set subtract) a complete set. 148 * @param other the set we are removing. 149 */ 150 public void remove(symbol_set other) throws internal_error 151 { 152 not_null(other); 153 154 /* walk down the other set and do the removes individually */ 155 for (Enumeration e = other.all(); e.hasMoreElements(); ) 156 remove((symbol)e.nextElement()); 157 }; 158 159 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 160 161 /** Equality comparison. */ 162 public boolean equals(symbol_set other) 163 { 164 if (other == null || other.size() != size()) return false; 165 166 /* once we know they are the same size, then improper subset does test */ 167 try { 168 return is_subset_of(other); 169 } catch (internal_error e) { 170 /* can't throw the error (because super class doesn't), so we crash */ 171 e.crash(); 172 return false; 173 } 174 } 175 176 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 177 178 /** Generic equality comparison. */ 179 public boolean equals(Object other) 180 { 181 if (!(other instanceof symbol_set)) 182 return false; 183 else 184 return equals((symbol_set)other); 185 } 186 187 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 188 189 /** Compute a hash code. */ 190 public int hashCode() 191 { 192 int result = 0; 193 int cnt; 194 Enumeration e; 195 196 /* hash together codes from at most first 5 elements */ 197 for (e = all(), cnt=0 ; e.hasMoreElements() && cnt<5; cnt++) 198 result ^= ((symbol)e.nextElement()).hashCode(); 199 200 return result; 201 } 202 203 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ 204 205 /** Convert to a string. */ 206 public String toString() 207 { 208 String result; 209 boolean comma_flag; 210 211 result = "{"; 212 comma_flag = false; 213 for (Enumeration e = all(); e.hasMoreElements(); ) 214 { 215 if (comma_flag) 216 result += ", "; 217 else 218 comma_flag = true; 219 220 result += ((symbol)e.nextElement()).name(); 221 } 222 result += "}"; 223 224 return result; 225 } 226 227 /*-----------------------------------------------------------*/ 228 229 }; 230 231 232