1. package com.sun.java_cup.internal;
  2. import java.util.Stack;
  3. import java.util.Enumeration;
  4. /** This class represents an LALR item. Each LALR item consists of
  5. * a production, a "dot" at a position within that production, and
  6. * a set of lookahead symbols (terminal). (The first two of these parts
  7. * are provide by the super class). An item is designed to represent a
  8. * configuration that the parser may be in. For example, an item of the
  9. * form: <pre>
  10. * [A ::= B * C d E , {a,b,c}]
  11. * </pre>
  12. * indicates that the parser is in the middle of parsing the production <pre>
  13. * A ::= B C d E
  14. * </pre>
  15. * that B has already been parsed, and that we will expect to see a lookahead
  16. * of either a, b, or c once the complete RHS of this production has been
  17. * found.<p>
  18. *
  19. * Items may initially be missing some items from their lookahead sets.
  20. * Links are maintained from each item to the set of items that would need
  21. * to be updated if symbols are added to its lookahead set. During
  22. * "lookahead propagation", we add symbols to various lookahead sets and
  23. * propagate these changes across these dependency links as needed.
  24. *
  25. * @see com.sun.java_cup.internal.lalr_item_set
  26. * @see com.sun.java_cup.internal.lalr_state
  27. * @version last updated: 11/25/95
  28. * @author Scott Hudson
  29. */
  30. public class lalr_item extends lr_item_core {
  31. /*-----------------------------------------------------------*/
  32. /*--- Constructor(s) ----------------------------------------*/
  33. /*-----------------------------------------------------------*/
  34. /** Full constructor.
  35. * @param prod the production for the item.
  36. * @param pos the position of the "dot" within the production.
  37. * @param look the set of lookahead symbols.
  38. */
  39. public lalr_item(production prod, int pos, terminal_set look)
  40. throws internal_error
  41. {
  42. super(prod, pos);
  43. _lookahead = look;
  44. _propagate_items = new Stack();
  45. needs_propagation = true;
  46. }
  47. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  48. /** Constructor with default position (dot at start).
  49. * @param prod the production for the item.
  50. * @param look the set of lookahead symbols.
  51. */
  52. public lalr_item(production prod, terminal_set look) throws internal_error
  53. {
  54. this(prod,0,look);
  55. }
  56. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  57. /** Constructor with default position and empty lookahead set.
  58. * @param prod the production for the item.
  59. */
  60. public lalr_item(production prod) throws internal_error
  61. {
  62. this(prod,0,new terminal_set());
  63. }
  64. /*-----------------------------------------------------------*/
  65. /*--- (Access to) Instance Variables ------------------------*/
  66. /*-----------------------------------------------------------*/
  67. /** The lookahead symbols of the item. */
  68. protected terminal_set _lookahead;
  69. /** The lookahead symbols of the item. */
  70. public terminal_set lookahead() {return _lookahead;}
  71. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  72. /** Links to items that the lookahead needs to be propagated to. */
  73. protected Stack _propagate_items;
  74. /** Links to items that the lookahead needs to be propagated to */
  75. public Stack propagate_items() {return _propagate_items;}
  76. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  77. /** Flag to indicate that this item needs to propagate its lookahead
  78. * (whether it has changed or not).
  79. */
  80. protected boolean needs_propagation;
  81. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  82. /** Add a new item to the set of items we propagate to. */
  83. public void add_propagate(lalr_item prop_to)
  84. {
  85. _propagate_items.push(prop_to);
  86. needs_propagation = true;
  87. }
  88. /*-----------------------------------------------------------*/
  89. /*--- General Methods ---------------------------------------*/
  90. /*-----------------------------------------------------------*/
  91. /** Propagate incoming lookaheads through this item to others need to
  92. * be changed.
  93. * @params incoming symbols to potentially be added to lookahead of this item.
  94. */
  95. public void propagate_lookaheads(terminal_set incoming) throws internal_error
  96. {
  97. boolean change = false;
  98. /* if we don't need to propagate, then bail out now */
  99. if (!needs_propagation && (incoming == null || incoming.empty()))
  100. return;
  101. /* if we have null incoming, treat as an empty set */
  102. if (incoming != null)
  103. {
  104. /* add the incoming to the lookahead of this item */
  105. change = lookahead().add(incoming);
  106. }
  107. /* if we changed or need it anyway, propagate across our links */
  108. if (change || needs_propagation)
  109. {
  110. /* don't need to propagate again */
  111. needs_propagation = false;
  112. /* propagate our lookahead into each item we are linked to */
  113. for (int i = 0; i < propagate_items().size(); i++)
  114. ((lalr_item)propagate_items().elementAt(i))
  115. .propagate_lookaheads(lookahead());
  116. }
  117. }
  118. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  119. /** Produce the new lalr_item that results from shifting the dot one position
  120. * to the right.
  121. */
  122. public lalr_item shift() throws internal_error
  123. {
  124. lalr_item result;
  125. /* can't shift if we have dot already at the end */
  126. if (dot_at_end())
  127. throw new internal_error("Attempt to shift past end of an lalr_item");
  128. /* create the new item w/ the dot shifted by one */
  129. result = new lalr_item(the_production(), dot_pos()+1,
  130. new terminal_set(lookahead()));
  131. /* change in our lookahead needs to be propagated to this item */
  132. add_propagate(result);
  133. return result;
  134. }
  135. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  136. /** Calculate lookahead representing symbols that could appear after the
  137. * symbol that the dot is currently in front of. Note: this routine must
  138. * not be invoked before first sets and nullability has been calculated
  139. * for all non terminals.
  140. */
  141. public terminal_set calc_lookahead(terminal_set lookahead_after)
  142. throws internal_error
  143. {
  144. terminal_set result;
  145. int pos;
  146. production_part part;
  147. symbol sym;
  148. /* sanity check */
  149. if (dot_at_end())
  150. throw new internal_error(
  151. "Attempt to calculate a lookahead set with a completed item");
  152. /* start with an empty result */
  153. result = new terminal_set();
  154. /* consider all nullable symbols after the one to the right of the dot */
  155. for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++)
  156. {
  157. part = the_production().rhs(pos);
  158. /* consider what kind of production part it is -- skip actions */
  159. if (!part.is_action())
  160. {
  161. sym = ((symbol_part)part).the_symbol();
  162. /* if its a terminal add it in and we are done */
  163. if (!sym.is_non_term())
  164. {
  165. result.add((terminal)sym);
  166. return result;
  167. }
  168. else
  169. {
  170. /* otherwise add in first set of the non terminal */
  171. result.add(((non_terminal)sym).first_set());
  172. /* if its nullable we continue adding, if not, we are done */
  173. if (!((non_terminal)sym).nullable())
  174. return result;
  175. }
  176. }
  177. }
  178. /* if we get here everything past the dot was nullable
  179. we add in the lookahead for after the production and we are done */
  180. result.add(lookahead_after);
  181. return result;
  182. }
  183. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  184. /** Determine if everything from the symbol one beyond the dot all the
  185. * way to the end of the right hand side is nullable. This would indicate
  186. * that the lookahead of this item must be included in the lookaheads of
  187. * all items produced as a closure of this item. Note: this routine should
  188. * not be invoked until after first sets and nullability have been
  189. * calculated for all non terminals.
  190. */
  191. public boolean lookahead_visible() throws internal_error
  192. {
  193. production_part part;
  194. symbol sym;
  195. /* if the dot is at the end, we have a problem, but the cleanest thing
  196. to do is just return true. */
  197. if (dot_at_end()) return true;
  198. /* walk down the rhs and bail if we get a non-nullable symbol */
  199. for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
  200. {
  201. part = the_production().rhs(pos);
  202. /* skip actions */
  203. if (!part.is_action())
  204. {
  205. sym = ((symbol_part)part).the_symbol();
  206. /* if its a terminal we fail */
  207. if (!sym.is_non_term()) return false;
  208. /* if its not nullable we fail */
  209. if (!((non_terminal)sym).nullable()) return false;
  210. }
  211. }
  212. /* if we get here its all nullable */
  213. return true;
  214. }
  215. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  216. /** Equality comparison -- here we only require the cores to be equal since
  217. * we need to do sets of items based only on core equality (ignoring
  218. * lookahead sets).
  219. */
  220. public boolean equals(lalr_item other)
  221. {
  222. if (other == null) return false;
  223. return super.equals(other);
  224. }
  225. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  226. /** Generic equality comparison. */
  227. public boolean equals(Object other)
  228. {
  229. if (!(other instanceof lalr_item))
  230. return false;
  231. else
  232. return equals((lalr_item)other);
  233. }
  234. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  235. /** Return a hash code -- here we only hash the core since we only test core
  236. * matching in LALR items.
  237. */
  238. public int hashCode()
  239. {
  240. return super.hashCode();
  241. }
  242. /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  243. /** Convert to string. */
  244. public String toString()
  245. {
  246. String result = "";
  247. // additional output for debugging:
  248. // result += "(" + obj_hash() + ")";
  249. result += "[";
  250. result += super.toString();
  251. result += ", ";
  252. if (lookahead() != null)
  253. {
  254. result += "{";
  255. for (int t = 0; t < terminal.number(); t++)
  256. if (lookahead().contains(t))
  257. result += terminal.find(t).name() + " ";
  258. result += "}";
  259. }
  260. else
  261. result += "NULL LOOKAHEAD!!";
  262. result += "]";
  263. // additional output for debugging:
  264. // result += " -> ";
  265. // for (int i = 0; i<propagate_items().size(); i++)
  266. // result+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
  267. //
  268. // if (needs_propagation) result += " NP";
  269. return result;
  270. }
  271. /*-----------------------------------------------------------*/
  272. }