--- /dev/null
+
+package java_cup;
+
+/** The "core" of an LR item. This includes a production and the position
+ * of a marker (the "dot") within the production. Typically item cores
+ * are written using a production with an embedded "dot" to indicate their
+ * position. For example: <pre>
+ * A ::= B * C d E
+ * </pre>
+ * This represents a point in a parse where the parser is trying to match
+ * the given production, and has succeeded in matching everything before the
+ * "dot" (and hence is expecting to see the symbols after the dot next). See
+ * lalr_item, lalr_item_set, and lalr_start for full details on the meaning
+ * and use of items.
+ *
+ * @see java_cup.lalr_item
+ * @see java_cup.lalr_item_set
+ * @see java_cup.lalr_state
+ * @version last updated: 11/25/95
+ * @author Scott Hudson
+*/
+
+public class lr_item_core {
+
+ /*-----------------------------------------------------------*/
+ /*--- Constructor(s) ----------------------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** Full constructor.
+ * @param prod production this item uses.
+ * @param pos position of the "dot" within the item.
+ */
+ public lr_item_core(production prod, int pos) throws internal_error
+ {
+ symbol after_dot = null;
+ production_part part;
+
+ if (prod == null)
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a null production");
+
+ _the_production = prod;
+
+ if (pos < 0 || pos > _the_production.rhs_length())
+ throw new internal_error(
+ "Attempt to create an lr_item_core with a bad dot position");
+
+ _dot_pos = pos;
+
+ /* compute and cache hash code now */
+ _core_hash_cache = 13*_the_production.hashCode() + pos;
+
+ /* cache the symbol after the dot */
+ if (_dot_pos < _the_production.rhs_length())
+ {
+ part = _the_production.rhs(_dot_pos);
+ if (!part.is_action())
+ _symbol_after_dot = ((symbol_part)part).the_symbol();
+ }
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Constructor for dot at start of right hand side.
+ * @param prod production this item uses.
+ */
+ public lr_item_core(production prod) throws internal_error
+ {
+ this(prod,0);
+ }
+
+ /*-----------------------------------------------------------*/
+ /*--- (Access to) Instance Variables ------------------------*/
+ /*-----------------------------------------------------------*/
+
+ /** The production for the item. */
+ protected production _the_production;
+
+ /** The production for the item. */
+ public production the_production() {return _the_production;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ protected int _dot_pos;
+
+ /** The position of the "dot" -- this indicates the part of the production
+ * that the marker is before, so 0 indicates a dot at the beginning of
+ * the RHS.
+ */
+ public int dot_pos() {return _dot_pos;}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of the hash code. */
+ protected int _core_hash_cache;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Cache of symbol after the dot. */
+ protected symbol _symbol_after_dot = null;
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Is the dot at the end of the production? */
+ public boolean dot_at_end()
+ {
+ return _dot_pos >= _the_production.rhs_length();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the symbol after the dot. If there is no symbol after the dot
+ * we return null. */
+ public symbol symbol_after_dot()
+ {
+ /* use the cached symbol */
+ return _symbol_after_dot;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Determine if we have a dot before a non terminal, and if so which one
+ * (return null or the non terminal).
+ */
+ public non_terminal dot_before_nt()
+ {
+ symbol sym;
+
+ /* get the symbol after the dot */
+ sym = symbol_after_dot();
+
+ /* if it exists and is a non terminal, return it */
+ if (sym != null && sym.is_non_term())
+ return (non_terminal)sym;
+ else
+ return null;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Produce a new lr_item_core that results from shifting the dot one
+ * position to the right.
+ */
+ public lr_item_core shift_core() throws internal_error
+ {
+ if (dot_at_end())
+ throw new internal_error(
+ "Attempt to shift past end of an lr_item_core");
+
+ return new lr_item_core(_the_production, _dot_pos+1);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison for the core only. This is separate out because we
+ * need separate access in a super class.
+ */
+ public boolean core_equals(lr_item_core other)
+ {
+ return other != null &&
+ _the_production.equals(other._the_production) &&
+ _dot_pos == other._dot_pos;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Equality comparison. */
+ public boolean equals(lr_item_core other) {return core_equals(other);}
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Generic equality comparison. */
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof lr_item_core))
+ return false;
+ else
+ return equals((lr_item_core)other);
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the core (separated so we keep non overridden version). */
+ public int core_hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Hash code for the item. */
+ public int hashCode()
+ {
+ return _core_hash_cache;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Return the hash code that object would have provided for us so we have
+ * a (nearly) unique id for debugging.
+ */
+ protected int obj_hash()
+ {
+ return super.hashCode();
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string (separated out from toString() so we can call it
+ * from subclass that overrides toString()).
+ */
+ public String to_simple_string() throws internal_error
+ {
+ String result;
+ production_part part;
+
+ if (_the_production.lhs() != null &&
+ _the_production.lhs().the_symbol() != null &&
+ _the_production.lhs().the_symbol().name() != null)
+ result = _the_production.lhs().the_symbol().name();
+ else
+ result = "$$NULL$$";
+
+ result += " ::= ";
+
+ for (int i = 0; i<_the_production.rhs_length(); i++)
+ {
+ /* do we need the dot before this one? */
+ if (i == _dot_pos)
+ result += "(*) ";
+
+ /* print the name of the part */
+ if (_the_production.rhs(i) == null)
+ {
+ result += "$$NULL$$ ";
+ }
+ else
+ {
+ part = _the_production.rhs(i);
+ if (part == null)
+ result += "$$NULL$$ ";
+ else if (part.is_action())
+ result += "{ACTION} ";
+ else if (((symbol_part)part).the_symbol() != null &&
+ ((symbol_part)part).the_symbol().name() != null)
+ result += ((symbol_part)part).the_symbol().name() + " ";
+ else
+ result += "$$NULL$$ ";
+ }
+ }
+
+ /* put the dot after if needed */
+ if (_dot_pos == _the_production.rhs_length())
+ result += "(*) ";
+
+ return result;
+ }
+
+ /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
+
+ /** Convert to a string */
+ public String toString()
+ {
+ /* can't throw here since super class doesn't, so we crash instead */
+ try {
+ return to_simple_string();
+ } catch(internal_error e) {
+ e.crash();
+ return null;
+ }
+ }
+
+ /*-----------------------------------------------------------*/
+
+}
+