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