cex: replace state-item data structures

* src/state-item.h: Add trans, prods, and revs edges to state-item
struct.
(si_trans, si_revs, si_prods_lookup): Remove.
* src/state-item.c, src/lssi.c, src/parse-simulation.c,
* src/counterexample.c: Update state-item API usage accordingly.
This commit is contained in:
Vincent Imbimbo
2020-05-21 22:13:17 -04:00
committed by Akim Demaille
parent c19af5cbb4
commit 99260caef9
5 changed files with 62 additions and 80 deletions

View File

@@ -196,7 +196,7 @@ expand_to_conflict (state_item_number start, symbol_number conflict_sym)
// add each production to the search // add each production to the search
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; state_item_number sin;
bitset sib = si_prods_lookup (node->si); bitset sib = silast->prods;
BITSET_FOR_EACH (biter, sib, sin, 0) BITSET_FOR_EACH (biter, sib, sin, 0)
{ {
// ignore productions already in the path // 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 // for nullable nonterminals, add its goto to the search
if (nullable[sym - ntokens]) 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); 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 // go through each symbol after the dot in the current rule, and
// add each symbol to its derivation. // add each symbol to its derivation.
for (state_item_number nsi = si - state_items; 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 // if the item is a reduction, we could skip to the wrong rule
// by starting at i + 1, so this continue is necessary // 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, // if the current state-item is a production item,
// its reverse production items get added to the queue. // its reverse production items get added to the queue.
// Otherwise, look for a reverse transition to the target state. // Otherwise, look for a reverse transition to the target state.
bitset rsi = si_revs[sis->si]; bitset rsi = search_si->revs;
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, rsi, sin, 0) BITSET_FOR_EACH (biter, rsi, sin, 0)

View File

@@ -132,7 +132,7 @@ eligible_state_items (state_item *target)
continue; continue;
bitset_set (result, si - state_items); bitset_set (result, si - state_items);
// search all reverse edges. // search all reverse edges.
bitset rsi = si_revs[si - state_items]; bitset rsi = si->revs;
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, rsi, sin, 0) 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; finished = true;
break; break;
} }
state_item *si = state_items + last;
// Transitions don't change follow_L // 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, si->trans))
if (bitset_test (eligible, nextSI))
{ {
lssi *next = new_lssi (nextSI, n, n->lookahead, false); lssi *next = new_lssi (si->trans, n, n->lookahead, false);
append_lssi (next, visited, queue); 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 not nullable, follow_L is its FIRSTS set
// if the symbol is nullable, follow_L is its FIRSTS set unioned with // if the symbol is nullable, follow_L is its FIRSTS set unioned with
// this logic applied to the next symbol in the rule // this logic applied to the next symbol in the rule
bitset p = si_prods_lookup (last); if (si->prods)
if (p)
{ {
state_item si = state_items[last];
// Compute follow_L as above // Compute follow_L as above
bitset lookahead = bitset_create (nsyms, BITSET_FIXED); 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) for (; !item_number_is_rule_number (*pos); ++pos)
{ {
item_number it = *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. // Try all possible production steps within this parser state.
bitset_iterator biter; bitset_iterator biter;
state_item_number nextSI; state_item_number nextSI;
BITSET_FOR_EACH (biter, p, nextSI, 0) BITSET_FOR_EACH (biter, si->prods, nextSI, 0)
{ {
if (!bitset_test (eligible, nextSI)) if (!bitset_test (eligible, nextSI))
continue; continue;
@@ -320,7 +318,7 @@ lssi_reverse_production (const state_item *si, bitset lookahead)
// compatible with the lookahead. // compatible with the lookahead.
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; 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; state_item *prevsi = state_items + sin;
if (!production_allowed (prevsi, si)) if (!production_allowed (prevsi, si))

View File

@@ -408,8 +408,8 @@ nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list)
{ {
parse_state *current_ps = ps; parse_state *current_ps = ps;
state_item_number prev_sin = si - state_items; state_item_number prev_sin = si - state_items;
for (state_item_number sin = si_trans[prev_sin]; for (state_item_number sin = si->trans; sin != -1;
sin != -1; prev_sin = sin, sin = si_trans[sin]) prev_sin = sin, sin = state_items[sin].trans)
{ {
state_item *psi = state_items + prev_sin; state_item *psi = state_items + prev_sin;
symbol_number sp = item_number_as_symbol_number (*psi->item); 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 // Transition on the same next symbol, taking nullable
// symbols into account. // symbols into account.
gl_list_t result = parse_state_list_new (); 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 // check for disabled transition, shouldn't happen
// as any state_items that lead to these should be // as any state_items that lead to these should be
// disabled. // disabled.
@@ -471,12 +471,11 @@ simulate_production (parse_state *ps, symbol_number compat_sym)
{ {
gl_list_t result = parse_state_list_new (); gl_list_t result = parse_state_list_new ();
const state_item *si = parse_state_tail (ps); const state_item *si = parse_state_tail (ps);
bitset prod = si_prods_lookup (si - state_items); if (si->prods)
if (prod)
{ {
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; 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 // Take production step only if lhs is not nullable and
// if first rhs symbol is compatible with compat_sym // 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) if (s_size != rule_len + 1)
{ {
state_item *tail = (state_item *) new_root->state_items.tail_elt; 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); parse_state_list_append (result, new_root);
} }
else else
@@ -553,7 +552,7 @@ simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set)
copy = copy_parse_state (false, copy); copy = copy_parse_state (false, copy);
struct si_chunk *sis = &copy->state_items; struct si_chunk *sis = &copy->state_items;
const state_item *tail = sis->tail_elt; 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); parse_state_list_append (result, copy);
nullable_closure (copy, (state_item *) sis->tail_elt, result); 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 (); gl_list_t result = parse_state_list_new ();
const state_item *head = ps->state_items.head_elt; const state_item *head = ps->state_items.head_elt;
bitset prev = si_revs[head - state_items];
symbol_number prepend_sym = symbol_number prepend_sym =
item_number_as_symbol_number (*(head->item - 1)); item_number_as_symbol_number (*(head->item - 1));
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; 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); parse_state *copy = copy_parse_state (true, ps);
ps_si_prepend (copy, state_items + sin); ps_si_prepend (copy, state_items + sin);

View File

@@ -35,10 +35,6 @@ size_t nstate_items;
state_item_number *state_item_map; state_item_number *state_item_map;
state_item *state_items; state_item *state_items;
state_item_number *si_trans;
bitsetv si_revs;
Hash_table *si_prods;
// hash functions for index -> bitset hash maps // hash functions for index -> bitset hash maps
typedef struct typedef struct
{ {
@@ -96,14 +92,6 @@ hash_pair_insert (Hash_table *tab, int key, bitset val)
assert (res == hp); 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 /* A state_item from a state's id and the offset of the item within
the state. */ the state. */
state_item * 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].state = s;
state_items[sidx].item = &ritem[off]; state_items[sidx].item = &ritem[off];
state_items[sidx].lookahead = NULL; 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_item_map = xnmalloc (nstates + 1, sizeof (state_item_number));
state_items = xnmalloc (nstate_items, sizeof (state_item)); 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; state_item_number sidx = 0;
for (int i = 0; i < nstates; ++i) for (int i = 0; i < nstates; ++i)
{ {
@@ -240,8 +228,8 @@ init_trans (void)
state_item_number dstSI = state_item_number dstSI =
state_item_index_lookup (dst->number, k); state_item_index_lookup (dst->number, k);
si_trans[j] = dstSI; state_items[j].trans = dstSI;
bitset_set (si_revs[dstSI], j); bitset_set (state_items[dstSI].revs, j);
break; 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 static void
init_prods (void) init_prods (void)
{ {
si_prods = hash_pair_table_create (nstate_items);
for (int i = 0; i < nstates; ++i) for (int i = 0; i < nstates; ++i)
{ {
state *s = states[i]; state *s = states[i];
@@ -299,13 +280,13 @@ init_prods (void)
bitset copy = bitset_create (nstate_items, BITSET_SPARSE); bitset copy = bitset_create (nstate_items, BITSET_SPARSE);
bitset_copy (copy, lb); bitset_copy (copy, lb);
// update prods. // update prods.
hash_pair_insert (si_prods, j, copy); state_items[j].prods = copy;
// update revs. // update revs.
bitset_iterator biter; bitset_iterator biter;
state_item_number prod; state_item_number prod;
BITSET_FOR_EACH (biter, copy, prod, 0) BITSET_FOR_EACH (biter, copy, prod, 0)
bitset_set (si_revs[prod], j); bitset_set (state_items[prod].revs, j);
} }
} }
hash_free (closure_map); hash_free (closure_map);
@@ -340,7 +321,7 @@ gen_lookaheads (void)
prev->lookahead = lookahead; prev->lookahead = lookahead;
if (SI_TRANSITION (prev)) if (SI_TRANSITION (prev))
{ {
bitset rsi = si_revs[prev - state_items]; bitset rsi = state_items[prev - state_items].revs;
bitset_iterator biter; bitset_iterator biter;
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, rsi, sin, 0) BITSET_FOR_EACH (biter, rsi, sin, 0)
@@ -400,8 +381,11 @@ init_firsts (void)
static inline void static inline void
disable_state_item (state_item_number sin) disable_state_item (state_item_number sin)
{ {
si_trans[sin] = -2; state_item *si = state_items + sin;
hash_pair_remove (si_prods, 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) for (int i = nstate_items - 1; i >= 0; --i)
{ {
state_item *si = state_items + 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 // 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); disable_state_item (j);
gl_list_t queue = gl_list_t queue =
@@ -432,9 +416,8 @@ prune_disabled_paths (void)
const state_item *prev = gl_list_get_at (queue, 0); const state_item *prev = gl_list_get_at (queue, 0);
gl_list_remove_at (queue, 0); gl_list_remove_at (queue, 0);
state_item_number prev_num = prev - state_items; 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; bitset_iterator biter;
state_item_number sin; state_item_number sin;
BITSET_FOR_EACH (biter, rsi, sin, 0) BITSET_FOR_EACH (biter, rsi, sin, 0)
@@ -443,11 +426,12 @@ prune_disabled_paths (void)
gl_list_add_first (queue, &state_items[sin]); gl_list_add_first (queue, &state_items[sin]);
else else
{ {
bitset p = si_prods_lookup (sin); bitset p = state_items[sin].prods;
if (p) if (p)
bitset_reset (p, prev_num); bitset_reset (p, prev_num);
} }
} }
disable_state_item (prev_num);
} }
gl_list_free (queue); 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 static void
state_items_report (void) state_items_report (void)
@@ -474,15 +458,16 @@ state_items_report (void)
printf ("State %d:\n", i); printf ("State %d:\n", i);
for (int j = state_item_map[i]; j < state_item_map[i + 1]; ++j) 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 (""); puts ("");
if (si_trans[j] >= 0) if (si->trans >= 0)
{ {
fputs (" -> ", stdout); 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] = { " => ", " <- " }; const char *txt[2] = { " => ", " <- " };
for (int seti = 0; seti < 2; ++seti) for (int seti = 0; seti < 2; ++seti)
{ {
@@ -533,9 +518,14 @@ state_items_init (void)
void void
state_items_free (void) state_items_free (void)
{ {
hash_free (si_prods); for (int i = 0; i < nstate_items; ++i)
bitsetv_free (si_revs); if (!SI_DISABLED(i))
free (si_trans); {
state_item *si = state_items + i;
if (si->prods)
bitset_free (si->prods);
bitset_free (si->revs);
}
free (state_items); free (state_items);
bitsetv_free (firsts); bitsetv_free (firsts);
} }

View File

@@ -42,20 +42,18 @@
There are two type of edges in this graph transitions and There are two type of edges in this graph transitions and
productions. Transitions are the same as transitions from the productions. Transitions are the same as transitions from the
parser except edges are only between items from the same parser except edges are only between items from the same
rule. These are stored as an array "si_trans" (as most items will rule.
have transitions) which are indexed the same way as state_items.
Productions are edges from items with a nonterminal after the dot to Productions are edges from items with a nonterminal after the dot to
the production of that nonterminal in the same state. These edges are 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 stored as a bitset in a state-item.
it goes from/to
The inverses of these edges are stored in an array of bitsets, The inverses of these edges are stored in a bitset in the state-item,
"si_revs." A state-item that begins with a dot will have reverse "revs." A state-item that begins with a dot will have reverse
production edges, and all others will have reverse transition production edges, and all others will have reverse transition
edges. */ 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_PRODUCTION(si) ((si) == state_items || *((si)->item - 1) < 0)
# define SI_TRANSITION(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; const state *state;
item_number *item; item_number *item;
state_item_number trans;
bitset prods;
bitset revs;
bitset lookahead; bitset lookahead;
} state_item; } state_item;
@@ -77,10 +78,6 @@ extern state_item_number *state_item_map;
/** Array mapping state_item_numbers to state_items */ /** Array mapping state_item_numbers to state_items */
extern state_item *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); state_item *state_item_lookup (state_number s, state_item_number off);
static inline state_item_number 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; return state_item_map[s] + off;
} }
bitset si_prods_lookup (state_item_number si);
void state_items_init (void); void state_items_init (void);
void print_state_item (const state_item *si, FILE *out); void print_state_item (const state_item *si, FILE *out);
void state_items_free (void); void state_items_free (void);