Source code: java_cup/symbol_set.java
1
2 package java_cup;
3
4 import java.util.Hashtable;
5 import java.util.Enumeration;
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