refactor hashtable iterations to use H_FOREACH
This commit is contained in:
parent
e56f052255
commit
9a96314931
1 changed files with 68 additions and 112 deletions
|
|
@ -61,6 +61,27 @@ typedef struct HLREnhGrammar_ {
|
||||||
} HLREnhGrammar;
|
} HLREnhGrammar;
|
||||||
|
|
||||||
|
|
||||||
|
// XXX move to internal.h or something
|
||||||
|
// XXX replace other hashtable iterations with this
|
||||||
|
#define H_FOREACH_(HT) { \
|
||||||
|
const HHashTable *ht__ = HT; \
|
||||||
|
for(size_t i__=0; i__ < ht__->capacity; i__++) { \
|
||||||
|
for(HHashTableEntry *hte__ = &ht__->contents[i__]; \
|
||||||
|
hte__; \
|
||||||
|
hte__ = hte__->next) { \
|
||||||
|
if(hte__->key == NULL) continue;
|
||||||
|
|
||||||
|
#define H_FOREACH_KEY(HT, KEYVAR) H_FOREACH_(HT) \
|
||||||
|
const KEYVAR = hte__->key;
|
||||||
|
|
||||||
|
#define H_FOREACH(HT, KEYVAR, VALVAR) H_FOREACH_KEY(HT, KEYVAR) \
|
||||||
|
VALVAR = hte__->value;
|
||||||
|
|
||||||
|
#define H_END_FOREACH \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
// compare symbols - terminals by value, others by pointer
|
// compare symbols - terminals by value, others by pointer
|
||||||
static bool eq_symbol(const void *p, const void *q)
|
static bool eq_symbol(const void *p, const void *q)
|
||||||
{
|
{
|
||||||
|
|
@ -117,15 +138,9 @@ static HHashValue hash_lalr_itemset(const void *p)
|
||||||
{
|
{
|
||||||
HHashValue hash = 0;
|
HHashValue hash = 0;
|
||||||
|
|
||||||
const HHashTable *ht = p;
|
H_FOREACH_KEY((const HHashSet *)p, HLRItem *item)
|
||||||
for(size_t i=0; i < ht->capacity; i++) {
|
hash += hash_lalr_item(item);
|
||||||
for(HHashTableEntry *hte = &ht->contents[i]; hte; hte = hte->next) {
|
H_END_FOREACH
|
||||||
if(hte->key == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
hash += hash_lalr_item(hte->key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
@ -179,27 +194,6 @@ void h_lrtable_free(HLRTable *table)
|
||||||
h_free(table);
|
h_free(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX replace other hashtable iterations with this
|
|
||||||
// XXX move to internal.h or something
|
|
||||||
#define H_FOREACH_(HT) { \
|
|
||||||
const HHashTable *ht__ = HT; \
|
|
||||||
for(size_t i__=0; i__ < ht__->capacity; i__++) { \
|
|
||||||
for(HHashTableEntry *hte__ = &ht__->contents[i__]; \
|
|
||||||
hte__; \
|
|
||||||
hte__ = hte__->next) { \
|
|
||||||
if(hte__->key == NULL) continue;
|
|
||||||
|
|
||||||
#define H_FOREACH_KEY(HT, KEYVAR) H_FOREACH_(HT) \
|
|
||||||
const KEYVAR = hte__->key;
|
|
||||||
|
|
||||||
#define H_FOREACH(HT, KEYVAR, VALVAR) H_FOREACH_KEY(HT, KEYVAR) \
|
|
||||||
VALVAR = hte__->value;
|
|
||||||
|
|
||||||
#define H_END_FOREACH \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Constructing the characteristic automaton (handle recognizer) */
|
/* Constructing the characteristic automaton (handle recognizer) */
|
||||||
|
|
@ -220,18 +214,11 @@ static HHashSet *closure(HCFGrammar *g, const HHashSet *items)
|
||||||
HHashSet *ret = h_lrstate_new(arena);
|
HHashSet *ret = h_lrstate_new(arena);
|
||||||
HSlist *work = h_slist_new(arena);
|
HSlist *work = h_slist_new(arena);
|
||||||
|
|
||||||
// iterate over items - initialize work list with them
|
// initialize work list with items
|
||||||
const HHashTable *ht = items;
|
H_FOREACH_KEY(items, HLRItem *item)
|
||||||
for(size_t i=0; i < ht->capacity; i++) {
|
|
||||||
for(HHashTableEntry *hte = &ht->contents[i]; hte; hte = hte->next) {
|
|
||||||
if(hte->key == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const HLRItem *item = hte->key;
|
|
||||||
h_hashset_put(ret, item);
|
h_hashset_put(ret, item);
|
||||||
h_slist_push(work, (void *)item);
|
h_slist_push(work, (void *)item);
|
||||||
}
|
H_END_FOREACH
|
||||||
}
|
|
||||||
|
|
||||||
while(!h_slist_empty(work)) {
|
while(!h_slist_empty(work)) {
|
||||||
const HLRItem *item = h_slist_pop(work);
|
const HLRItem *item = h_slist_pop(work);
|
||||||
|
|
@ -322,75 +309,52 @@ HLRDFA *h_lr0_dfa(HCFGrammar *g)
|
||||||
HHashTable *neighbors = h_hashtable_new(arena, eq_symbol, hash_symbol);
|
HHashTable *neighbors = h_hashtable_new(arena, eq_symbol, hash_symbol);
|
||||||
|
|
||||||
// iterate over closure and generate neighboring sets
|
// iterate over closure and generate neighboring sets
|
||||||
const HHashTable *ht = closure(g, state);
|
H_FOREACH_KEY(closure(g, state), HLRItem *item)
|
||||||
for(size_t i=0; i < ht->capacity; i++) {
|
HCFChoice *sym = item->rhs[item->mark]; // symbol after mark
|
||||||
for(HHashTableEntry *hte = &ht->contents[i]; hte; hte = hte->next) {
|
|
||||||
if(hte->key == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const HLRItem *item = hte->key;
|
if(sym != NULL) { // mark was not at the end
|
||||||
HCFChoice *sym = item->rhs[item->mark]; // symbol after mark
|
// find or create prospective neighbor set
|
||||||
|
HLRState *neighbor = h_hashtable_get(neighbors, sym);
|
||||||
if(sym != NULL) { // mark was not at the end
|
if(neighbor == NULL) {
|
||||||
// find or create prospective neighbor set
|
neighbor = h_lrstate_new(arena);
|
||||||
HLRState *neighbor = h_hashtable_get(neighbors, sym);
|
h_hashtable_put(neighbors, sym, neighbor);
|
||||||
if(neighbor == NULL) {
|
|
||||||
neighbor = h_lrstate_new(arena);
|
|
||||||
h_hashtable_put(neighbors, sym, neighbor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...and add the advanced item to it
|
|
||||||
h_hashset_put(neighbor, advance_mark(arena, item));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ...and add the advanced item to it
|
||||||
|
h_hashset_put(neighbor, advance_mark(arena, item));
|
||||||
}
|
}
|
||||||
}
|
H_END_FOREACH
|
||||||
|
|
||||||
// merge neighbor sets into the set of existing states
|
// merge neighbor sets into the set of existing states
|
||||||
ht = neighbors;
|
H_FOREACH(neighbors, HCFChoice *symbol, HLRState *neighbor)
|
||||||
for(size_t i=0; i < ht->capacity; i++) {
|
// look up existing state, allocate new if not found
|
||||||
for(HHashTableEntry *hte = &ht->contents[i]; hte; hte = hte->next) {
|
size_t neighbor_idx;
|
||||||
if(hte->key == NULL)
|
if(!h_hashset_present(states, neighbor)) {
|
||||||
continue;
|
neighbor_idx = states->used;
|
||||||
|
h_hashtable_put(states, neighbor, (void *)(uintptr_t)neighbor_idx);
|
||||||
const HCFChoice *symbol = hte->key;
|
h_slist_push(work, neighbor);
|
||||||
HLRState *neighbor = hte->value;
|
h_slist_push(work, (void *)(uintptr_t)neighbor_idx);
|
||||||
|
} else {
|
||||||
// look up existing state, allocate new if not found
|
neighbor_idx = (uintptr_t)h_hashtable_get(states, neighbor);
|
||||||
size_t neighbor_idx;
|
|
||||||
if(!h_hashset_present(states, neighbor)) {
|
|
||||||
neighbor_idx = states->used;
|
|
||||||
h_hashtable_put(states, neighbor, (void *)(uintptr_t)neighbor_idx);
|
|
||||||
h_slist_push(work, neighbor);
|
|
||||||
h_slist_push(work, (void *)(uintptr_t)neighbor_idx);
|
|
||||||
} else {
|
|
||||||
neighbor_idx = (uintptr_t)h_hashtable_get(states, neighbor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add transition "state --symbol--> neighbor"
|
|
||||||
HLRTransition *t = h_arena_malloc(arena, sizeof(HLRTransition));
|
|
||||||
t->from = state_idx;
|
|
||||||
t->to = neighbor_idx;
|
|
||||||
t->symbol = symbol;
|
|
||||||
h_slist_push(transitions, t);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// add transition "state --symbol--> neighbor"
|
||||||
|
HLRTransition *t = h_arena_malloc(arena, sizeof(HLRTransition));
|
||||||
|
t->from = state_idx;
|
||||||
|
t->to = neighbor_idx;
|
||||||
|
t->symbol = symbol;
|
||||||
|
h_slist_push(transitions, t);
|
||||||
|
H_END_FOREACH
|
||||||
} // end while(work)
|
} // end while(work)
|
||||||
|
|
||||||
// fill DFA struct
|
// fill DFA struct
|
||||||
HLRDFA *dfa = h_arena_malloc(arena, sizeof(HLRDFA));
|
HLRDFA *dfa = h_arena_malloc(arena, sizeof(HLRDFA));
|
||||||
dfa->nstates = states->used;
|
dfa->nstates = states->used;
|
||||||
dfa->states = h_arena_malloc(arena, dfa->nstates*sizeof(HLRState *));
|
dfa->states = h_arena_malloc(arena, dfa->nstates*sizeof(HLRState *));
|
||||||
for(size_t i=0; i < states->capacity; i++) {
|
H_FOREACH(states, HLRState *state, void *v)
|
||||||
for(HHashTableEntry *hte = &states->contents[i]; hte; hte = hte->next) {
|
size_t idx = (uintptr_t)v;
|
||||||
if(hte->key == NULL)
|
dfa->states[idx] = state;
|
||||||
continue;
|
H_END_FOREACH
|
||||||
|
|
||||||
const HLRState *state = hte->key;
|
|
||||||
size_t idx = (uintptr_t)hte->value;
|
|
||||||
|
|
||||||
dfa->states[idx] = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dfa->transitions = transitions;
|
dfa->transitions = transitions;
|
||||||
|
|
||||||
return dfa;
|
return dfa;
|
||||||
|
|
@ -911,21 +875,13 @@ void h_pprint_lrstate(FILE *f, const HCFGrammar *g,
|
||||||
const HLRState *state, unsigned int indent)
|
const HLRState *state, unsigned int indent)
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
const HHashTable *ht = state;
|
H_FOREACH_KEY(state, HLRItem *item)
|
||||||
for(size_t i=0; i < ht->capacity; i++) {
|
if(!first)
|
||||||
for(HHashTableEntry *hte = &ht->contents[i]; hte; hte = hte->next) {
|
for(unsigned int i=0; i<indent; i++) fputc(' ', f);
|
||||||
if(hte->key == NULL)
|
first = false;
|
||||||
continue;
|
h_pprint_lritem(f, g, item);
|
||||||
|
fputc('\n', f);
|
||||||
const HLRItem *item = hte->key;
|
H_END_FOREACH
|
||||||
|
|
||||||
if(!first)
|
|
||||||
for(unsigned int i=0; i<indent; i++) fputc(' ', f);
|
|
||||||
first = false;
|
|
||||||
h_pprint_lritem(f, g, item);
|
|
||||||
fputc('\n', f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pprint_transition(FILE *f, const HCFGrammar *g, const HLRTransition *t)
|
static void pprint_transition(FILE *f, const HCFGrammar *g, const HLRTransition *t)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue