1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
|
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;
}
}
/*-----------------------------------------------------------*/
}
|