Home | History | Annotate | Download | only in java_cup
      1 
      2 package java_cup;
      3 
      4 /** The "core" of an LR item.  This includes a production and the position
      5  *  of a marker (the "dot") within the production.  Typically item cores
      6  *  are written using a production with an embedded "dot" to indicate their
      7  *  position.  For example: <pre>
      8  *     A ::= B * C d E
      9  *  </pre>
     10  *  This represents a point in a parse where the parser is trying to match
     11  *  the given production, and has succeeded in matching everything before the
     12  *  "dot" (and hence is expecting to see the symbols after the dot next).  See
     13  *  lalr_item, lalr_item_set, and lalr_start for full details on the meaning
     14  *  and use of items.
     15  *
     16  * @see     java_cup.lalr_item
     17  * @see     java_cup.lalr_item_set
     18  * @see     java_cup.lalr_state
     19  * @version last updated: 11/25/95
     20  * @author  Scott Hudson
     21 */
     22 
     23 public class lr_item_core {
     24 
     25   /*-----------------------------------------------------------*/
     26   /*--- Constructor(s) ----------------------------------------*/
     27   /*-----------------------------------------------------------*/
     28 
     29   /** Full constructor.
     30    * @param prod production this item uses.
     31    * @param pos  position of the "dot" within the item.
     32    */
     33   public lr_item_core(production prod, int pos) throws internal_error
     34     {
     35       symbol          after_dot = null;
     36       production_part part;
     37 
     38       if (prod == null)
     39     throw new internal_error(
     40       "Attempt to create an lr_item_core with a null production");
     41 
     42       _the_production = prod;
     43 
     44       if (pos < 0 || pos > _the_production.rhs_length())
     45     throw new internal_error(
     46       "Attempt to create an lr_item_core with a bad dot position");
     47 
     48       _dot_pos = pos;
     49 
     50       /* compute and cache hash code now */
     51       _core_hash_cache = 13*_the_production.hashCode() + pos;
     52 
     53       /* cache the symbol after the dot */
     54       if (_dot_pos < _the_production.rhs_length())
     55     {
     56       part = _the_production.rhs(_dot_pos);
     57       if (!part.is_action())
     58         _symbol_after_dot = ((symbol_part)part).the_symbol();
     59     }
     60     }
     61 
     62   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
     63 
     64   /** Constructor for dot at start of right hand side.
     65    * @param prod production this item uses.
     66    */
     67   public lr_item_core(production prod) throws internal_error
     68     {
     69       this(prod,0);
     70     }
     71 
     72   /*-----------------------------------------------------------*/
     73   /*--- (Access to) Instance Variables ------------------------*/
     74   /*-----------------------------------------------------------*/
     75 
     76   /** The production for the item. */
     77   protected production _the_production;
     78 
     79   /** The production for the item. */
     80   public production the_production() {return _the_production;}
     81 
     82   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
     83 
     84   /** The position of the "dot" -- this indicates the part of the production
     85    *  that the marker is before, so 0 indicates a dot at the beginning of
     86    *  the RHS.
     87    */
     88   protected int _dot_pos;
     89 
     90   /** The position of the "dot" -- this indicates the part of the production
     91    *  that the marker is before, so 0 indicates a dot at the beginning of
     92    *  the RHS.
     93    */
     94   public int dot_pos() {return _dot_pos;}
     95 
     96   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
     97 
     98   /** Cache of the hash code. */
     99   protected int _core_hash_cache;
    100 
    101   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    102 
    103   /** Cache of symbol after the dot. */
    104   protected symbol _symbol_after_dot = null;
    105 
    106   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    107 
    108   /** Is the dot at the end of the production? */
    109   public boolean dot_at_end()
    110     {
    111        return _dot_pos >= _the_production.rhs_length();
    112     }
    113 
    114   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    115 
    116   /** Return the symbol after the dot.  If there is no symbol after the dot
    117    *  we return null. */
    118   public symbol symbol_after_dot()
    119     {
    120       /* use the cached symbol */
    121       return _symbol_after_dot;
    122     }
    123 
    124   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    125 
    126   /** Determine if we have a dot before a non terminal, and if so which one
    127    *  (return null or the non terminal).
    128    */
    129   public non_terminal dot_before_nt()
    130     {
    131       symbol sym;
    132 
    133       /* get the symbol after the dot */
    134       sym = symbol_after_dot();
    135 
    136       /* if it exists and is a non terminal, return it */
    137       if (sym != null && sym.is_non_term())
    138     return (non_terminal)sym;
    139       else
    140     return null;
    141     }
    142 
    143   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    144 
    145   /** Produce a new lr_item_core that results from shifting the dot one
    146    *  position to the right.
    147    */
    148   public lr_item_core shift_core() throws internal_error
    149     {
    150       if (dot_at_end())
    151     throw new internal_error(
    152       "Attempt to shift past end of an lr_item_core");
    153 
    154       return new lr_item_core(_the_production, _dot_pos+1);
    155     }
    156 
    157   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    158 
    159   /** Equality comparison for the core only.  This is separate out because we
    160    *  need separate access in a super class.
    161    */
    162   public boolean core_equals(lr_item_core other)
    163     {
    164       return other != null &&
    165          _the_production.equals(other._the_production) &&
    166          _dot_pos == other._dot_pos;
    167     }
    168 
    169   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    170 
    171   /** Equality comparison. */
    172   public boolean equals(lr_item_core other) {return core_equals(other);}
    173 
    174   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    175 
    176   /** Generic equality comparison. */
    177   public boolean equals(Object other)
    178     {
    179       if (!(other instanceof lr_item_core))
    180     return false;
    181       else
    182     return equals((lr_item_core)other);
    183     }
    184 
    185   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    186 
    187   /** Hash code for the core (separated so we keep non overridden version). */
    188   public int core_hashCode()
    189     {
    190       return _core_hash_cache;
    191     }
    192 
    193   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    194 
    195   /** Hash code for the item. */
    196   public int hashCode()
    197     {
    198       return _core_hash_cache;
    199     }
    200 
    201   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    202 
    203   /** Convert to a string (separated out from toString() so we can call it
    204    *  from subclass that overrides toString()).
    205    */
    206   public String to_simple_string() throws internal_error
    207     {
    208       String result;
    209       production_part part;
    210 
    211       if (_the_production.lhs() != null &&
    212       _the_production.lhs().the_symbol() != null &&
    213       _the_production.lhs().the_symbol().name() != null)
    214     result = _the_production.lhs().the_symbol().name();
    215       else
    216     result = "$$NULL$$";
    217 
    218       result += " ::= ";
    219 
    220       for (int i = 0; i<_the_production.rhs_length(); i++)
    221     {
    222       /* do we need the dot before this one? */
    223       if (i == _dot_pos)
    224         result += "(*) ";
    225 
    226       /* print the name of the part */
    227       if (_the_production.rhs(i) == null)
    228         {
    229           result += "$$NULL$$ ";
    230         }
    231       else
    232         {
    233           part = _the_production.rhs(i);
    234           if (part == null)
    235         result += "$$NULL$$ ";
    236           else if (part.is_action())
    237         result += "{ACTION} ";
    238           else if (((symbol_part)part).the_symbol() != null &&
    239                        ((symbol_part)part).the_symbol().name() != null)
    240         result += ((symbol_part)part).the_symbol().name() + " ";
    241           else
    242         result += "$$NULL$$ ";
    243         }
    244     }
    245 
    246       /* put the dot after if needed */
    247       if (_dot_pos == _the_production.rhs_length())
    248     result += "(*) ";
    249 
    250       return result;
    251     }
    252 
    253   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
    254 
    255   /** Convert to a string */
    256   public String toString()
    257     {
    258       /* can't throw here since super class doesn't, so we crash instead */
    259       try {
    260         return to_simple_string();
    261       } catch(internal_error e) {
    262     e.crash();
    263     return null;
    264       }
    265     }
    266 
    267   /*-----------------------------------------------------------*/
    268 
    269 };
    270 
    271