diff --git a/src/counterexample.c b/src/counterexample.c index 6201d9f3..d5dca5e3 100644 --- a/src/counterexample.c +++ b/src/counterexample.c @@ -196,7 +196,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym) // add each production to the search bitset_iterator biter; state_item_number sin; - bitset sib = si_prods_lookup (node->si); + bitset sib = silast->prods; BITSET_FOR_EACH (biter, sib, sin, 0) { // ignore productions already in the path @@ -208,7 +208,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym) // for nullable nonterminals, add its goto to the search if (nullable[sym - ntokens]) { - si_bfs_node *next = si_bfs_new (si_trans[node->si], node); + si_bfs_node *next = si_bfs_new (silast->trans, node); gl_list_add_last (queue, next); } } @@ -304,7 +304,8 @@ complete_diverging_example (symbol_number conflict_sym, // go through each symbol after the dot in the current rule, and // add each symbol to its derivation. for (state_item_number nsi = si - state_items; - !item_number_is_rule_number (*i); ++i, nsi = si_trans[nsi]) + !item_number_is_rule_number (*i); + ++i, nsi = state_items[nsi].trans) { // if the item is a reduction, we could skip to the wrong rule // by starting at i + 1, so this continue is necessary @@ -433,7 +434,7 @@ nonunifying_shift_path (gl_list_t reduce_path, state_item *shift_conflict) // if the current state-item is a production item, // its reverse production items get added to the queue. // Otherwise, look for a reverse transition to the target state. - bitset rsi = si_revs[sis->si]; + bitset rsi = search_si->revs; bitset_iterator biter; state_item_number sin; BITSET_FOR_EACH (biter, rsi, sin, 0) diff --git a/src/lssi.c b/src/lssi.c index 293daafb..406a5ebb 100644 --- a/src/lssi.c +++ b/src/lssi.c @@ -132,7 +132,7 @@ eligible_state_items (state_item *target) continue; bitset_set (result, si - state_items); // search all reverse edges. - bitset rsi = si_revs[si - state_items]; + bitset rsi = si->revs; bitset_iterator biter; state_item_number sin; BITSET_FOR_EACH (biter, rsi, sin, 0) @@ -175,13 +175,13 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym) finished = true; break; } + state_item *si = state_items + last; // Transitions don't change follow_L - if (si_trans[last] >= 0) + if (si->trans >= 0) { - state_item_number nextSI = si_trans[last]; - if (bitset_test (eligible, nextSI)) + if (bitset_test (eligible, si->trans)) { - lssi *next = new_lssi (nextSI, n, n->lookahead, false); + lssi *next = new_lssi (si->trans, n, n->lookahead, false); append_lssi (next, visited, queue); } } @@ -192,13 +192,11 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym) // if the symbol is not nullable, follow_L is its FIRSTS set // if the symbol is nullable, follow_L is its FIRSTS set unioned with // this logic applied to the next symbol in the rule - bitset p = si_prods_lookup (last); - if (p) + if (si->prods) { - state_item si = state_items[last]; // Compute follow_L as above bitset lookahead = bitset_create (nsyms, BITSET_FIXED); - item_number *pos = si.item + 1; + item_number *pos = si->item + 1; for (; !item_number_is_rule_number (*pos); ++pos) { item_number it = *pos; @@ -221,7 +219,7 @@ shortest_path_from_start (state_item_number target, symbol_number next_sym) // Try all possible production steps within this parser state. bitset_iterator biter; state_item_number nextSI; - BITSET_FOR_EACH (biter, p, nextSI, 0) + BITSET_FOR_EACH (biter, si->prods, nextSI, 0) { if (!bitset_test (eligible, nextSI)) continue; @@ -320,7 +318,7 @@ lssi_reverse_production (const state_item *si, bitset lookahead) // compatible with the lookahead. bitset_iterator biter; state_item_number sin; - BITSET_FOR_EACH (biter, si_revs[si - state_items], sin, 0) + BITSET_FOR_EACH (biter, si->revs, sin, 0) { state_item *prevsi = state_items + sin; if (!production_allowed (prevsi, si)) diff --git a/src/parse-simulation.c b/src/parse-simulation.c index f77ef4a7..0dc9a1dd 100644 --- a/src/parse-simulation.c +++ b/src/parse-simulation.c @@ -408,8 +408,8 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list) { parse_state *current_ps = ps; state_item_number prev_sin = si - state_items; - for (state_item_number sin = si_trans[prev_sin]; - sin != -1; prev_sin = sin, sin = si_trans[sin]) + for (state_item_number sin = si->trans; sin != -1; + prev_sin = sin, sin = state_items[sin].trans) { state_item *psi = state_items + prev_sin; symbol_number sp = item_number_as_symbol_number (*psi->item); @@ -432,7 +432,7 @@ simulate_transition (parse_state *ps) // Transition on the same next symbol, taking nullable // symbols into account. gl_list_t result = parse_state_list_new (); - state_item_number si_next = si_trans[si - state_items]; + state_item_number si_next = si->trans; // check for disabled transition, shouldn't happen // as any state_items that lead to these should be // disabled. @@ -471,12 +471,11 @@ simulate_production (parse_state *ps, symbol_number compat_sym) { gl_list_t result = parse_state_list_new (); const state_item *si = parse_state_tail (ps); - bitset prod = si_prods_lookup (si - state_items); - if (prod) + if (si->prods) { bitset_iterator biter; state_item_number sin; - BITSET_FOR_EACH (biter, prod, sin, 0) + BITSET_FOR_EACH (biter, si->prods, sin, 0) { // Take production step only if lhs is not nullable and // if first rhs symbol is compatible with compat_sym @@ -523,7 +522,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set) if (s_size != rule_len + 1) { state_item *tail = (state_item *) new_root->state_items.tail_elt; - ps_si_append (new_root, state_items + si_trans[tail - state_items]); + ps_si_append (new_root, state_items + tail->trans); parse_state_list_append (result, new_root); } else @@ -553,7 +552,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set) copy = copy_parse_state (false, copy); struct si_chunk *sis = ©->state_items; const state_item *tail = sis->tail_elt; - ps_si_append (copy, state_items + si_trans[tail - state_items]); + ps_si_append (copy, state_items + tail->trans); parse_state_list_append (result, copy); nullable_closure (copy, (state_item *) sis->tail_elt, result); } @@ -568,12 +567,11 @@ parser_prepend (parse_state *ps) { gl_list_t result = parse_state_list_new (); const state_item *head = ps->state_items.head_elt; - bitset prev = si_revs[head - state_items]; symbol_number prepend_sym = item_number_as_symbol_number (*(head->item - 1)); bitset_iterator biter; state_item_number sin; - BITSET_FOR_EACH (biter, prev, sin, 0) + BITSET_FOR_EACH (biter, head->revs, sin, 0) { parse_state *copy = copy_parse_state (true, ps); ps_si_prepend (copy, state_items + sin); diff --git a/src/state-item.c b/src/state-item.c index 62d2d210..2af5400e 100644 --- a/src/state-item.c +++ b/src/state-item.c @@ -35,10 +35,6 @@ size_t nstate_items; state_item_number *state_item_map; state_item *state_items; -state_item_number *si_trans; -bitsetv si_revs; -Hash_table *si_prods; - // hash functions for index -> bitset hash maps typedef struct { @@ -96,14 +92,6 @@ hash_pair_insert (Hash_table *tab, int key, bitset val) assert (res == hp); } -static void -hash_pair_remove (Hash_table *tab, int key) -{ - hash_pair probe; - probe.key = key; - hash_delete (tab, &probe); -} - /* A state_item from a state's id and the offset of the item within the state. */ state_item * @@ -118,7 +106,9 @@ state_item_set (state_item_number sidx, const state *s, item_number off) state_items[sidx].state = s; state_items[sidx].item = &ritem[off]; state_items[sidx].lookahead = NULL; - si_trans[sidx] = -1; + state_items[sidx].trans = -1; + state_items[sidx].prods = NULL; + state_items[sidx].revs = bitset_create (nstate_items, BITSET_SPARSE); } /** @@ -144,8 +134,6 @@ init_state_items (void) } state_item_map = xnmalloc (nstates + 1, sizeof (state_item_number)); state_items = xnmalloc (nstate_items, sizeof (state_item)); - si_trans = xnmalloc (nstate_items, sizeof (state_item_number)); - si_revs = bitsetv_create (nstate_items, nstate_items, BITSET_SPARSE); state_item_number sidx = 0; for (int i = 0; i < nstates; ++i) { @@ -240,8 +228,8 @@ init_trans (void) state_item_number dstSI = state_item_index_lookup (dst->number, k); - si_trans[j] = dstSI; - bitset_set (si_revs[dstSI], j); + state_items[j].trans = dstSI; + bitset_set (state_items[dstSI].revs, j); break; } } @@ -250,16 +238,9 @@ init_trans (void) } } -bitset -si_prods_lookup (state_item_number si) -{ - return hash_pair_lookup (si_prods, si); -} - static void init_prods (void) { - si_prods = hash_pair_table_create (nstate_items); for (int i = 0; i < nstates; ++i) { state *s = states[i]; @@ -299,13 +280,13 @@ init_prods (void) bitset copy = bitset_create (nstate_items, BITSET_SPARSE); bitset_copy (copy, lb); // update prods. - hash_pair_insert (si_prods, j, copy); + state_items[j].prods = copy; // update revs. bitset_iterator biter; state_item_number prod; BITSET_FOR_EACH (biter, copy, prod, 0) - bitset_set (si_revs[prod], j); + bitset_set (state_items[prod].revs, j); } } hash_free (closure_map); @@ -340,7 +321,7 @@ gen_lookaheads (void) prev->lookahead = lookahead; if (SI_TRANSITION (prev)) { - bitset rsi = si_revs[prev - state_items]; + bitset rsi = state_items[prev - state_items].revs; bitset_iterator biter; state_item_number sin; BITSET_FOR_EACH (biter, rsi, sin, 0) @@ -400,8 +381,11 @@ init_firsts (void) static inline void disable_state_item (state_item_number sin) { - si_trans[sin] = -2; - hash_pair_remove (si_prods, sin); + state_item *si = state_items + sin; + si->trans = -2; + bitset_free (si->revs); + if (si->prods) + bitset_free (si->prods); } /* @@ -414,10 +398,10 @@ prune_disabled_paths (void) for (int i = nstate_items - 1; i >= 0; --i) { state_item *si = state_items + i; - if (si_trans[i] == -1 && item_number_is_symbol_number (*si->item)) + if (si->trans == -1 && item_number_is_symbol_number (*si->item)) { // disable the transitions out of i - for (state_item_number j = si_trans[i]; j != -1; j = si_trans[j]) + for (state_item_number j = si->trans; j != -1; j = state_items[j].trans) disable_state_item (j); gl_list_t queue = @@ -432,9 +416,8 @@ prune_disabled_paths (void) const state_item *prev = gl_list_get_at (queue, 0); gl_list_remove_at (queue, 0); state_item_number prev_num = prev - state_items; - disable_state_item (prev_num); - bitset rsi = si_revs[prev_num]; + bitset rsi = prev->revs; bitset_iterator biter; state_item_number sin; BITSET_FOR_EACH (biter, rsi, sin, 0) @@ -443,11 +426,12 @@ prune_disabled_paths (void) gl_list_add_first (queue, &state_items[sin]); else { - bitset p = si_prods_lookup (sin); + bitset p = state_items[sin].prods; if (p) bitset_reset (p, prev_num); } } + disable_state_item (prev_num); } gl_list_free (queue); } @@ -463,7 +447,7 @@ print_state_item (const state_item *si, FILE *out) } /** - * Report set counts and the state_item graph if trace is enabled + * Report the state_item graph */ static void state_items_report (void) @@ -474,15 +458,16 @@ state_items_report (void) printf ("State %d:\n", i); for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) { - item_print (state_items[j].item, NULL, stdout); + state_item *si = state_items + j; + item_print (si->item, NULL, stdout); puts (""); - if (si_trans[j] >= 0) + if (si->trans >= 0) { fputs (" -> ", stdout); - print_state_item (state_items + si_trans[j], stdout); + print_state_item (state_items + si->trans, stdout); } - bitset sets[2] = { si_prods_lookup (j), si_revs[j] }; + bitset sets[2] = { si->prods, si->revs }; const char *txt[2] = { " => ", " <- " }; for (int seti = 0; seti < 2; ++seti) { @@ -533,9 +518,14 @@ state_items_init (void) void state_items_free (void) { - hash_free (si_prods); - bitsetv_free (si_revs); - free (si_trans); + for (int i = 0; i < nstate_items; ++i) + if (!SI_DISABLED(i)) + { + state_item *si = state_items + i; + if (si->prods) + bitset_free (si->prods); + bitset_free (si->revs); + } free (state_items); bitsetv_free (firsts); } diff --git a/src/state-item.h b/src/state-item.h index 3b98132d..3e606b6e 100644 --- a/src/state-item.h +++ b/src/state-item.h @@ -42,20 +42,18 @@ There are two type of edges in this graph transitions and productions. Transitions are the same as transitions from the parser except edges are only between items from the same - rule. These are stored as an array "si_trans" (as most items will - have transitions) which are indexed the same way as state_items. + rule. Productions are edges from items with a nonterminal after the dot to the production of that nonterminal in the same state. These edges are - stored as a hash map "si_prods" from a state_item to a set of what productions - it goes from/to + stored as a bitset in a state-item. - The inverses of these edges are stored in an array of bitsets, - "si_revs." A state-item that begins with a dot will have reverse + The inverses of these edges are stored in a bitset in the state-item, + "revs." A state-item that begins with a dot will have reverse production edges, and all others will have reverse transition edges. */ -# define SI_DISABLED(sin) (si_trans[sin] == -2) +# define SI_DISABLED(sin) (state_items[sin].trans == -2) # define SI_PRODUCTION(si) ((si) == state_items || *((si)->item - 1) < 0) # define SI_TRANSITION(si) ((si) != state_items && *((si)->item - 1) >= 0) @@ -65,6 +63,9 @@ typedef struct { const state *state; item_number *item; + state_item_number trans; + bitset prods; + bitset revs; bitset lookahead; } state_item; @@ -77,10 +78,6 @@ extern state_item_number *state_item_map; /** Array mapping state_item_numbers to state_items */ extern state_item *state_items; -/** state-item graph edges */ -extern state_item_number *si_trans; -extern bitsetv si_revs; - state_item *state_item_lookup (state_number s, state_item_number off); static inline state_item_number @@ -89,8 +86,6 @@ state_item_index_lookup (state_number s, state_item_number off) return state_item_map[s] + off; } -bitset si_prods_lookup (state_item_number si); - void state_items_init (void); void print_state_item (const state_item *si, FILE *out); void state_items_free (void);