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:
 *     A ::= B * C d E
 *  
* 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; } /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ /** 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; } } /*-----------------------------------------------------------*/ };