1. package com.sun.java_cup.internal;
  2. /** The "core" of an LR item. This includes a production and the position
  3. * of a marker (the "dot") within the production. Typically item cores
  4. * are written using a production with an embedded "dot" to indicate their
  5. * position. For example: <pre>
  6. * A ::= B * C d E
  7. * </pre>
  8. * This represents a point in a parse where the parser is trying to match
  9. * the given production, and has succeeded in matching everything before the
  10. * "dot" (and hence is expecting to see the symbols after the dot next). See
  11. * lalr_item, lalr_item_set, and lalr_start for full details on the meaning
  12. * and use of items.
  13. *
  14. * @see com.sun.java_cup.internal.lalr_item
  15. * @see com.sun.java_cup.internal.lalr_item_set
  16. * @see com.sun.java_cup.internal.lalr_state
  17. * @version last updated: 11/25/95
  18. * @author Scott Hudson
  19. */
  20. public class lr_item_core {
  21. /*-----------------------------------------------------------*/
  22. /*--- Constructor(s) ----------------------------------------*/
  23. /*-----------------------------------------------------------*/
  24. /** Full constructor.
  25. * @param prod production this item uses.
  26. * @param pos position of the "dot" within the item.
  27. */
  28. public lr_item_core(production prod, int pos) throws internal_error
  29. {
  30. symbol after_dot = null;
  31. production_part part;
  32. if (prod == null)
  33. throw new internal_error(
  34. "Attempt to create an lr_item_core with a null production");
  35. _the_production = prod;
  36. if (pos < 0 || pos > _the_production.rhs_length())
  37. throw new internal_error(
  38. "Attempt to create an lr_item_core with a bad dot position");
  39. _dot_pos = pos;
  40. /* compute and cache hash code now */
  41. _core_hash_cache = 13*_the_production.hashCode() + pos;
  42. /* cache the symbol after the dot */
  43. if (_dot_pos < _the_production.rhs_length())
  44. {
  45. part = _the_production.rhs(_dot_pos);
  46. if (!part.is_action())
  47. _symbol_after_dot = ((symbol_part)part).the_symbol();
  48. }
  49. }
  50. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  51. /** Constructor for dot at start of right hand side.
  52. * @param prod production this item uses.
  53. */
  54. public lr_item_core(production prod) throws internal_error
  55. {
  56. this(prod,0);
  57. }
  58. /*-----------------------------------------------------------*/
  59. /*--- (Access to) Instance Variables ------------------------*/
  60. /*-----------------------------------------------------------*/
  61. /** The production for the item. */
  62. protected production _the_production;
  63. /** The production for the item. */
  64. public production the_production() {return _the_production;}
  65. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  66. /** The position of the "dot" -- this indicates the part of the production
  67. * that the marker is before, so 0 indicates a dot at the beginning of
  68. * the RHS.
  69. */
  70. protected int _dot_pos;
  71. /** The position of the "dot" -- this indicates the part of the production
  72. * that the marker is before, so 0 indicates a dot at the beginning of
  73. * the RHS.
  74. */
  75. public int dot_pos() {return _dot_pos;}
  76. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  77. /** Cache of the hash code. */
  78. protected int _core_hash_cache;
  79. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  80. /** Cache of symbol after the dot. */
  81. protected symbol _symbol_after_dot = null;
  82. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  83. /** Is the dot at the end of the production? */
  84. public boolean dot_at_end()
  85. {
  86. return _dot_pos >= _the_production.rhs_length();
  87. }
  88. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  89. /** Return the symbol after the dot. If there is no symbol after the dot
  90. * we return null. */
  91. public symbol symbol_after_dot()
  92. {
  93. /* use the cached symbol */
  94. return _symbol_after_dot;
  95. }
  96. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  97. /** Determine if we have a dot before a non terminal, and if so which one
  98. * (return null or the non terminal).
  99. */
  100. public non_terminal dot_before_nt()
  101. {
  102. symbol sym;
  103. /* get the symbol after the dot */
  104. sym = symbol_after_dot();
  105. /* if it exists and is a non terminal, return it */
  106. if (sym != null && sym.is_non_term())
  107. return (non_terminal)sym;
  108. else
  109. return null;
  110. }
  111. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  112. /** Produce a new lr_item_core that results from shifting the dot one
  113. * position to the right.
  114. */
  115. public lr_item_core shift_core() throws internal_error
  116. {
  117. if (dot_at_end())
  118. throw new internal_error(
  119. "Attempt to shift past end of an lr_item_core");
  120. return new lr_item_core(_the_production, _dot_pos+1);
  121. }
  122. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  123. /** Equality comparison for the core only. This is separate out because we
  124. * need separate access in a super class.
  125. */
  126. public boolean core_equals(lr_item_core other)
  127. {
  128. return other != null &&
  129. _the_production.equals(other._the_production) &&
  130. _dot_pos == other._dot_pos;
  131. }
  132. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  133. /** Equality comparison. */
  134. public boolean equals(lr_item_core other) {return core_equals(other);}
  135. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  136. /** Generic equality comparison. */
  137. public boolean equals(Object other)
  138. {
  139. if (!(other instanceof lr_item_core))
  140. return false;
  141. else
  142. return equals((lr_item_core)other);
  143. }
  144. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  145. /** Hash code for the core (separated so we keep non overridden version). */
  146. public int core_hashCode()
  147. {
  148. return _core_hash_cache;
  149. }
  150. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  151. /** Hash code for the item. */
  152. public int hashCode()
  153. {
  154. return _core_hash_cache;
  155. }
  156. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  157. /** Return the hash code that object would have provided for us so we have
  158. * a (nearly) unique id for debugging.
  159. */
  160. protected int obj_hash()
  161. {
  162. return super.hashCode();
  163. }
  164. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  165. /** Convert to a string (separated out from toString() so we can call it
  166. * from subclass that overrides toString()).
  167. */
  168. public String to_simple_string() throws internal_error
  169. {
  170. String result;
  171. production_part part;
  172. if (_the_production.lhs() != null &&
  173. _the_production.lhs().the_symbol() != null &&
  174. _the_production.lhs().the_symbol().name() != null)
  175. result = _the_production.lhs().the_symbol().name();
  176. else
  177. result = "$$NULL$$";
  178. result += " ::= ";
  179. for (int i = 0; i<_the_production.rhs_length(); i++)
  180. {
  181. /* do we need the dot before this one? */
  182. if (i == _dot_pos)
  183. result += "(*) ";
  184. /* print the name of the part */
  185. if (_the_production.rhs(i) == null)
  186. {
  187. result += "$$NULL$$ ";
  188. }
  189. else
  190. {
  191. part = _the_production.rhs(i);
  192. if (part == null)
  193. result += "$$NULL$$ ";
  194. else if (part.is_action())
  195. result += "{ACTION} ";
  196. else if (((symbol_part)part).the_symbol() != null &&
  197. ((symbol_part)part).the_symbol().name() != null)
  198. result += ((symbol_part)part).the_symbol().name() + " ";
  199. else
  200. result += "$$NULL$$ ";
  201. }
  202. }
  203. /* put the dot after if needed */
  204. if (_dot_pos == _the_production.rhs_length())
  205. result += "(*) ";
  206. return result;
  207. }
  208. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  209. /** Convert to a string */
  210. public String toString()
  211. {
  212. /* can't throw here since super class doesn't, so we crash instead */
  213. try {
  214. return to_simple_string();
  215. } catch(internal_error e) {
  216. e.crash();
  217. return null;
  218. }
  219. }
  220. /*-----------------------------------------------------------*/
  221. }