go back to storing engines in lists

This commit is contained in:
Sven M. Hallberg 2013-06-22 18:16:41 +02:00
parent 67681a119a
commit 66809ceeda

View file

@ -1,7 +1,7 @@
#include <assert.h> #include <assert.h>
#include "lr.h" #include "lr.h"
static bool glr_step(HParseResult **result, HLREngine **engines, static bool glr_step(HParseResult **result, HSlist *engines,
HLREngine *engine, const HLRAction *action); HLREngine *engine, const HLRAction *action);
@ -73,7 +73,7 @@ static inline HLREngine *respawn(HLREngine *eng, HSlist *stack)
} }
static HLREngine * static HLREngine *
demerge(HParseResult **result, HLREngine **engines, demerge(HParseResult **result, HSlist *engines,
HLREngine *engine, const HLRAction *action, size_t depth) HLREngine *engine, const HLRAction *action, size_t depth)
{ {
// no-op on engines that are not merged // no-op on engines that are not merged
@ -126,7 +126,7 @@ HLREngine *fork_engine(const HLREngine *engine)
} }
static const HLRAction * static const HLRAction *
handle_conflict(HParseResult **result, HLREngine **engines, handle_conflict(HParseResult **result, HSlist *engines,
const HLREngine *engine, const HSlist *branches) const HLREngine *engine, const HSlist *branches)
{ {
// there should be at least two conflicting actions // there should be at least two conflicting actions
@ -149,7 +149,7 @@ handle_conflict(HParseResult **result, HLREngine **engines,
/* GLR driver */ /* GLR driver */
static bool glr_step(HParseResult **result, HLREngine **engines, static bool glr_step(HParseResult **result, HSlist *engines,
HLREngine *engine, const HLRAction *action) HLREngine *engine, const HLRAction *action)
{ {
// handle forks and demerges (~> spawn engines) // handle forks and demerges (~> spawn engines)
@ -167,11 +167,17 @@ static bool glr_step(HParseResult **result, HLREngine **engines,
bool run = h_lrengine_step(engine, action); bool run = h_lrengine_step(engine, action);
if(run) { if(run) {
// store engine in the array, merge if necessary // store engine in the list, merge if necessary
if(engines[engine->state] == NULL) HSlistNode *x;
engines[engine->state] = engine; for(x=engines->head; x; x=x->next) {
else HLREngine *eng = x->elem;
engines[engine->state] = lrengine_merge(engines[engine->state], engine); if(eng->state == engine->state) {
x->elem = lrengine_merge(eng, engine);
break;
}
}
if(!x) // no merge happened
h_slist_push(engines, engine);
} else if(engine->state == HLR_SUCCESS) { } else if(engine->state == HLR_SUCCESS) {
// save the result // save the result
*result = h_lrengine_result(engine); *result = h_lrengine_result(engine);
@ -189,40 +195,27 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
HArena *arena = h_new_arena(mm__, 0); // will hold the results HArena *arena = h_new_arena(mm__, 0); // will hold the results
HArena *tarena = h_new_arena(mm__, 0); // tmp, deleted after parse HArena *tarena = h_new_arena(mm__, 0); // tmp, deleted after parse
// allocate engine arrays (can hold one engine per state) // allocate engine lists (will hold one engine per state)
// these are swapped each iteration // these are swapped each iteration
HLREngine **engines = h_arena_malloc(tarena, table->nrows * sizeof(HLREngine *)); HSlist *engines = h_slist_new(tarena);
HLREngine **engback = h_arena_malloc(tarena, table->nrows * sizeof(HLREngine *)); HSlist *engback = h_slist_new(tarena);
assert(table->nrows > 0);
for(size_t i=0; i<table->nrows; i++) {
engines[i] = NULL;
engback[i] = NULL;
}
// create initial engine // create initial engine
engines[0] = h_lrengine_new(arena, tarena, table, stream); h_slist_push(engines, h_lrengine_new(arena, tarena, table, stream));
assert(engines[0]->state == 0);
HParseResult *result = NULL; HParseResult *result = NULL;
size_t engines_left = 1; while(result == NULL && !h_slist_empty(engines)) {
while(engines_left && result == NULL) { assert(h_slist_empty(engback));
engines_left = 0;
for(size_t i=0; i<table->nrows; i++) {
HLREngine *engine = engines[i];
if(engine == NULL)
continue;
engines[i] = NULL; // cleared for next iteration
// step all engines // step all engines
bool run = glr_step(&result, engback, engine, h_lrengine_action(engine)); while(!h_slist_empty(engines)) {
if(run) HLREngine *engine = h_slist_pop(engines);
engines_left++; const HLRAction *action = h_lrengine_action(engine);
glr_step(&result, engback, engine, action);
} }
// swap the arrays // swap the lists
HLREngine **tmp = engines; HSlist *tmp = engines;
engines = engback; engines = engback;
engback = tmp; engback = tmp;
} }