Source code: java_cup/lr_item_core.java
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 /** Return the hash code that object would have provided for us so we have
204 * a (nearly) unique id for debugging.
205 */
206 protected int obj_hash()
207 {
208 return super.hashCode();
209 }
210
211 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
212
213 /** Convert to a string (separated out from toString() so we can call it
214 * from subclass that overrides toString()).
215 */
216 public String to_simple_string() throws internal_error
217 {
218 String result;
219 production_part part;
220
221 if (_the_production.lhs() != null &&
222 _the_production.lhs().the_symbol() != null &&
223 _the_production.lhs().the_symbol().name() != null)
224 result = _the_production.lhs().the_symbol().name();
225 else
226 result = "$$NULL$$";
227
228 result += " ::= ";
229
230 for (int i = 0; i<_the_production.rhs_length(); i++)
231 {
232 /* do we need the dot before this one? */
233 if (i == _dot_pos)
234 result += "(*) ";
235
236 /* print the name of the part */
237 if (_the_production.rhs(i) == null)
238 {
239 result += "$$NULL$$ ";
240 }
241 else
242 {
243 part = _the_production.rhs(i);
244 if (part == null)
245 result += "$$NULL$$ ";
246 else if (part.is_action())
247 result += "{ACTION} ";
248 else if (((symbol_part)part).the_symbol() != null &&
249 ((symbol_part)part).the_symbol().name() != null)
250 result += ((symbol_part)part).the_symbol().name() + " ";
251 else
252 result += "$$NULL$$ ";
253 }
254 }
255
256 /* put the dot after if needed */
257 if (_dot_pos == _the_production.rhs_length())
258 result += "(*) ";
259
260 return result;
261 }
262
263 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
264
265 /** Convert to a string */
266 public String toString()
267 {
268 /* can't throw here since super class doesn't, so we crash instead */
269 try {
270 return to_simple_string();
271 } catch(internal_error e) {
272 e.crash();
273 return null;
274 }
275 }
276
277 /*-----------------------------------------------------------*/
278
279 }
280