1
2package java_cup;
3
4import java.util.Enumeration;
5import 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 */
14public 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