Logo Search packages:      
Sourcecode: jasmin-sable version File versions  Download package

lr_item_core.java

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
*/

00023 public class lr_item_core {
   
  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Full constructor.
   * @param prod production this item uses.
   * @param pos  position of the "dot" within the item.
   */
00033   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.
   */
00067   public lr_item_core(production prod) throws internal_error
    {
      this(prod,0);
    }

  /*-----------------------------------------------------------*/
  /*--- (Access to) Instance Variables ------------------------*/
  /*-----------------------------------------------------------*/

  /** The production for the item. */
00077   protected production _the_production;

  /** The production for the item. */
00080   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.
   */
00088   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.
   */
00094   public int dot_pos() {return _dot_pos;}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Cache of the hash code. */
00099   protected int _core_hash_cache;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Cache of symbol after the dot. */
00104   protected symbol _symbol_after_dot = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Is the dot at the end of the production? */
00109   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. */
00118   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). 
   */
00129   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. 
   */
00148   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. 
   */
00162   public boolean core_equals(lr_item_core other)
    {
      return other != null && 
           _the_production.equals(other._the_production) && 
           _dot_pos == other._dot_pos;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Equality comparison. */
00172   public boolean equals(lr_item_core other) {return core_equals(other);}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Generic equality comparison. */
00177   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). */
00188   public int core_hashCode()
    {
      return _core_hash_cache;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Hash code for the item. */
00196   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.
   */
00206   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()).
   */
00216   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 */
00266   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;
      }
    }

  /*-----------------------------------------------------------*/

}
   

Generated by  Doxygen 1.6.0   Back to index