lin
2025-08-21 57113df3a0e2be01232281fad9a5f2c060567981
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
 
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;
      }
    }
 
  /*-----------------------------------------------------------*/
 
};