| |
| 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; |
| } |
| |
| /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ |
| |
| /** 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; |
| } |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| }; |
| |