Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: java_cup/lalr_item.java


1   package java_cup;
2   
3   import java.util.Stack;
4   import java.util.Enumeration;
5   
6   /** This class represents an LALR item. Each LALR item consists of 
7    *  a production, a "dot" at a position within that production, and
8    *  a set of lookahead symbols (terminal).  (The first two of these parts
9    *  are provide by the super class).  An item is designed to represent a 
10   *  configuration that the parser may be in.  For example, an item of the 
11   *  form: <pre>
12   *    [A ::= B * C d E  , {a,b,c}]
13   *  </pre>
14   *  indicates that the parser is in the middle of parsing the production <pre>
15   *    A ::= B C d E
16   *  </pre>
17   *  that B has already been parsed, and that we will expect to see a lookahead 
18   *  of either a, b, or c once the complete RHS of this production has been 
19   *  found.<p>
20   *
21   *  Items may initially be missing some items from their lookahead sets.  
22   *  Links are maintained from each item to the set of items that would need 
23   *  to be updated if symbols are added to its lookahead set.  During 
24   *  "lookahead propagation", we add symbols to various lookahead sets and 
25   *  propagate these changes across these dependency links as needed. 
26   *  
27   * @see     java_cup.lalr_item_set
28   * @see     java_cup.lalr_state
29   * @version last updated: 11/25/95
30   * @author  Scott Hudson
31   */
32  public class lalr_item extends lr_item_core {
33  
34    /*-----------------------------------------------------------*/
35    /*--- Constructor(s) ----------------------------------------*/
36    /*-----------------------------------------------------------*/
37  
38    /** Full constructor. 
39     * @param prod the production for the item.
40     * @param pos  the position of the "dot" within the production.
41     * @param look the set of lookahead symbols.
42     */
43    public lalr_item(production prod, int pos, terminal_set look) 
44      throws internal_error
45      {
46        super(prod, pos);
47        _lookahead = look;
48        _propagate_items = new Stack();
49        needs_propagation = true;
50      }
51  
52    /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
53  
54    /** Constructor with default position (dot at start). 
55     * @param prod the production for the item.
56     * @param look the set of lookahead symbols.
57     */
58    public lalr_item(production prod, terminal_set look) throws internal_error
59      {
60        this(prod,0,look);
61      }
62  
63    /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
64  
65    /** Constructor with default position and empty lookahead set. 
66     * @param prod the production for the item.
67     */
68    public lalr_item(production prod) throws internal_error
69      {
70        this(prod,0,new terminal_set());
71      }
72  
73    /*-----------------------------------------------------------*/
74    /*--- (Access to) Instance Variables ------------------------*/
75    /*-----------------------------------------------------------*/
76  
77    /** The lookahead symbols of the item. */
78    protected terminal_set _lookahead;
79  
80    /** The lookahead symbols of the item. */
81    public terminal_set lookahead() {return _lookahead;}
82  
83    /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
84  
85    /** Links to items that the lookahead needs to be propagated to. */
86    protected Stack _propagate_items; 
87  
88    /** Links to items that the lookahead needs to be propagated to */
89    public Stack propagate_items() {return _propagate_items;}
90  
91    /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
92  
93    /** Flag to indicate that this item needs to propagate its lookahead 
94     *  (whether it has changed or not). 
95     */
96    protected boolean needs_propagation;
97  
98    /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
99  
100   /** Add a new item to the set of items we propagate to. */
101   public void add_propagate(lalr_item prop_to)
102     {
103       _propagate_items.push(prop_to);
104       needs_propagation = true;
105     }
106 
107   /*-----------------------------------------------------------*/
108   /*--- General Methods ---------------------------------------*/
109   /*-----------------------------------------------------------*/
110 
111   /** Propagate incoming lookaheads through this item to others need to 
112    *  be changed.
113    * @params incoming symbols to potentially be added to lookahead of this item.
114    */
115   public void propagate_lookaheads(terminal_set incoming) throws internal_error
116     {
117       boolean change = false;
118 
119       /* if we don't need to propagate, then bail out now */
120       if (!needs_propagation && (incoming == null || incoming.empty()))
121   return;
122 
123       /* if we have null incoming, treat as an empty set */
124       if (incoming != null)
125   {
126     /* add the incoming to the lookahead of this item */
127     change = lookahead().add(incoming);
128   }
129 
130       /* if we changed or need it anyway, propagate across our links */
131       if (change || needs_propagation)
132   {
133           /* don't need to propagate again */
134           needs_propagation = false;
135 
136     /* propagate our lookahead into each item we are linked to */
137     for (int i = 0; i < propagate_items().size(); i++)
138       ((lalr_item)propagate_items().elementAt(i))
139             .propagate_lookaheads(lookahead());
140   }
141     }
142 
143   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
144 
145   /** Produce the new lalr_item that results from shifting the dot one position
146    *  to the right. 
147    */
148   public lalr_item shift() throws internal_error
149     {
150       lalr_item result;
151 
152       /* can't shift if we have dot already at the end */
153       if (dot_at_end())
154   throw new internal_error("Attempt to shift past end of an lalr_item");
155 
156       /* create the new item w/ the dot shifted by one */
157       result = new lalr_item(the_production(), dot_pos()+1, 
158               new terminal_set(lookahead()));
159 
160       /* change in our lookahead needs to be propagated to this item */
161       add_propagate(result);
162 
163       return result;
164     }
165 
166   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
167 
168   /** Calculate lookahead representing symbols that could appear after the
169    *   symbol that the dot is currently in front of.  Note: this routine must
170    *   not be invoked before first sets and nullability has been calculated
171    *   for all non terminals. 
172    */ 
173   public terminal_set calc_lookahead(terminal_set lookahead_after) 
174     throws internal_error
175     {
176       terminal_set    result;
177       int             pos;
178       production_part part;
179       symbol          sym;
180 
181       /* sanity check */
182       if (dot_at_end())
183   throw new internal_error(
184     "Attempt to calculate a lookahead set with a completed item");
185 
186       /* start with an empty result */
187       result = new terminal_set();
188 
189       /* consider all nullable symbols after the one to the right of the dot */
190       for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++) 
191   {
192      part = the_production().rhs(pos);
193 
194      /* consider what kind of production part it is -- skip actions */ 
195      if (!part.is_action())
196        {
197          sym = ((symbol_part)part).the_symbol();
198 
199          /* if its a terminal add it in and we are done */
200          if (!sym.is_non_term())
201      {
202        result.add((terminal)sym);
203        return result;
204      }
205          else
206      {
207        /* otherwise add in first set of the non terminal */
208        result.add(((non_terminal)sym).first_set());
209 
210        /* if its nullable we continue adding, if not, we are done */
211        if (!((non_terminal)sym).nullable())
212          return result;
213      }
214        }
215   }
216 
217       /* if we get here everything past the dot was nullable 
218          we add in the lookahead for after the production and we are done */
219       result.add(lookahead_after);
220       return result;
221     }
222 
223   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
224 
225   /** Determine if everything from the symbol one beyond the dot all the 
226    *  way to the  end of the right hand side is nullable.  This would indicate
227    *  that the lookahead of this item must be included in the lookaheads of
228    *  all items produced as a closure of this item.  Note: this routine should 
229    *  not be invoked until after first sets and nullability have been 
230    *  calculated for all non terminals. 
231    */
232   public boolean lookahead_visible() throws internal_error
233     {
234       production_part part;
235       symbol          sym;
236 
237       /* if the dot is at the end, we have a problem, but the cleanest thing
238    to do is just return true. */
239       if (dot_at_end()) return true;
240 
241       /* walk down the rhs and bail if we get a non-nullable symbol */
242       for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
243   {
244     part = the_production().rhs(pos);
245 
246     /* skip actions */
247     if (!part.is_action())
248       {
249         sym = ((symbol_part)part).the_symbol();
250 
251         /* if its a terminal we fail */
252         if (!sym.is_non_term()) return false;
253 
254         /* if its not nullable we fail */
255         if (!((non_terminal)sym).nullable()) return false;
256       }
257   }
258 
259       /* if we get here its all nullable */
260       return true;
261     }
262 
263   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
264 
265   /** Equality comparison -- here we only require the cores to be equal since
266    *   we need to do sets of items based only on core equality (ignoring 
267    *   lookahead sets). 
268    */
269   public boolean equals(lalr_item other)
270     {
271       if (other == null) return false;
272       return super.equals(other);
273     }
274 
275   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
276 
277   /** Generic equality comparison. */
278   public boolean equals(Object other)
279     {
280       if (!(other instanceof lalr_item)) 
281   return false;
282       else
283   return equals((lalr_item)other);
284     }
285 
286   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
287 
288   /** Return a hash code -- here we only hash the core since we only test core
289    *  matching in LALR items. 
290    */
291   public int hashCode()
292     {
293       return super.hashCode();
294     }
295 
296   /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
297 
298   /** Convert to string. */
299   public String toString()
300     {
301       String result = "";
302 
303       // additional output for debugging:
304       // result += "(" + obj_hash() + ")"; 
305       result += "[";
306       result += super.toString();
307       result += ", ";
308       if (lookahead() != null)
309   {
310     result += "{";
311     for (int t = 0; t < terminal.number(); t++)
312       if (lookahead().contains(t))
313         result += terminal.find(t).name() + " ";
314     result += "}";
315   }
316       else
317   result += "NULL LOOKAHEAD!!";
318       result += "]";
319 
320       // additional output for debugging:
321       // result += " -> ";
322       // for (int i = 0; i<propagate_items().size(); i++)
323       //   result+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
324       //
325       // if (needs_propagation) result += " NP";
326 
327       return result;
328     }
329     /*-----------------------------------------------------------*/
330 }