refactor hashtable iterations to use H_FOREACH

This commit is contained in:
Sven M. Hallberg 2013-06-15 19:06:10 +02:00
parent e56f052255
commit 9a96314931

View file

@ -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)