in util/src/main/java/java_cup/lalr_state.java [286:428]
public static lalr_state build_machine(production start_prod)
throws internal_error
{
lalr_state start_state;
lalr_item_set start_items;
lalr_item_set new_items;
lalr_item_set linked_items;
lalr_item_set kernel;
Stack <lalr_state> work_stack = new Stack <lalr_state> ();
lalr_state st, new_st;
symbol_set outgoing;
lalr_item itm, new_itm, existing, fix_itm;
symbol sym, sym2;
Enumeration i, s, fix;
/* sanity check */
if (start_prod == null)
throw new internal_error(
"Attempt to build viable prefix recognizer using a null production");
/* build item with dot at front of start production and EOF lookahead */
start_items = new lalr_item_set();
itm = new lalr_item(start_prod);
itm.lookahead().add(terminal.EOF);
start_items.add(itm);
/* create copy the item set to form the kernel */
kernel = new lalr_item_set(start_items);
/* create the closure from that item set */
start_items.compute_closure();
/* build a state out of that item set and put it in our work set */
start_state = new lalr_state(start_items);
work_stack.push(start_state);
/* enter the state using the kernel as the key */
_all_kernels.put(kernel, start_state);
/* continue looking at new states until we have no more work to do */
while (!work_stack.empty())
{
/* remove a state from the work set */
st = (lalr_state)work_stack.pop();
/* gather up all the symbols that appear before dots */
outgoing = new symbol_set();
for (i = st.items().all(); i.hasMoreElements(); )
{
itm = (lalr_item)i.nextElement();
/* add the symbol before the dot (if any) to our collection */
sym = itm.symbol_after_dot();
if (sym != null) outgoing.add(sym);
}
/* now create a transition out for each individual symbol */
for (s = outgoing.all(); s.hasMoreElements(); )
{
sym = (symbol)s.nextElement();
/* will be keeping the set of items with propagate links */
linked_items = new lalr_item_set();
/* gather up shifted versions of all the items that have this
symbol before the dot */
new_items = new lalr_item_set();
for (i = st.items().all(); i.hasMoreElements();)
{
itm = (lalr_item)i.nextElement();
/* if this is the symbol we are working on now, add to set */
sym2 = itm.symbol_after_dot();
if (sym.equals(sym2))
{
/* add to the kernel of the new state */
new_items.add(itm.shift());
/* remember that itm has propagate link to it */
linked_items.add(itm);
}
}
/* use new items as state kernel */
kernel = new lalr_item_set(new_items);
/* have we seen this one already? */
new_st = (lalr_state)_all_kernels.get(kernel);
/* if we haven't, build a new state out of the item set */
if (new_st == null)
{
/* compute closure of the kernel for the full item set */
new_items.compute_closure();
/* build the new state */
new_st = new lalr_state(new_items);
/* add the new state to our work set */
work_stack.push(new_st);
/* put it in our kernel table */
_all_kernels.put(kernel, new_st);
}
/* otherwise relink propagation to items in existing state */
else
{
/* walk through the items that have links to the new state */
for (fix = linked_items.all(); fix.hasMoreElements(); )
{
fix_itm = (lalr_item)fix.nextElement();
/* look at each propagate link out of that item */
for (int l =0; l < fix_itm.propagate_items().size(); l++)
{
/* pull out item linked to in the new state */
new_itm =
(lalr_item)fix_itm.propagate_items().elementAt(l);
/* find corresponding item in the existing state */
existing = new_st.items().find(new_itm);
/* fix up the item so it points to the existing set */
if (existing != null)
fix_itm.propagate_items().setElementAt(existing ,l);
}
}
}
/* add a transition from current state to that state */
st.add_transition(sym, new_st);
}
}
/* all done building states */
/* propagate complete lookahead sets throughout the states */
propagate_all_lookaheads();
return start_state;
}