diff --git a/src/backends/glr.c b/src/backends/glr.c index 34a56335881b1abbda27f15011a3d4842c8cd5a3..353d0e6433100357287e40487299aa8327baad07 100644 --- a/src/backends/glr.c +++ b/src/backends/glr.c @@ -1,7 +1,7 @@ #include <assert.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); @@ -73,7 +73,7 @@ static inline HLREngine *respawn(HLREngine *eng, HSlist *stack) } static HLREngine * -demerge(HParseResult **result, HLREngine **engines, +demerge(HParseResult **result, HSlist *engines, HLREngine *engine, const HLRAction *action, size_t depth) { // no-op on engines that are not merged @@ -126,7 +126,7 @@ HLREngine *fork_engine(const HLREngine *engine) } static const HLRAction * -handle_conflict(HParseResult **result, HLREngine **engines, +handle_conflict(HParseResult **result, HSlist *engines, const HLREngine *engine, const HSlist *branches) { // there should be at least two conflicting actions @@ -149,7 +149,7 @@ handle_conflict(HParseResult **result, HLREngine **engines, /* GLR driver */ -static bool glr_step(HParseResult **result, HLREngine **engines, +static bool glr_step(HParseResult **result, HSlist *engines, HLREngine *engine, const HLRAction *action) { // 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); if(run) { - // store engine in the array, merge if necessary - if(engines[engine->state] == NULL) - engines[engine->state] = engine; - else - engines[engine->state] = lrengine_merge(engines[engine->state], engine); + // store engine in the list, merge if necessary + HSlistNode *x; + for(x=engines->head; x; x=x->next) { + HLREngine *eng = x->elem; + 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) { // save the result *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 *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 - HLREngine **engines = h_arena_malloc(tarena, table->nrows * sizeof(HLREngine *)); - HLREngine **engback = h_arena_malloc(tarena, table->nrows * sizeof(HLREngine *)); - - assert(table->nrows > 0); - for(size_t i=0; i<table->nrows; i++) { - engines[i] = NULL; - engback[i] = NULL; - } + HSlist *engines = h_slist_new(tarena); + HSlist *engback = h_slist_new(tarena); // create initial engine - engines[0] = h_lrengine_new(arena, tarena, table, stream); - assert(engines[0]->state == 0); + h_slist_push(engines, h_lrengine_new(arena, tarena, table, stream)); HParseResult *result = NULL; - size_t engines_left = 1; - while(engines_left && result == NULL) { - 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 - bool run = glr_step(&result, engback, engine, h_lrengine_action(engine)); - if(run) - engines_left++; + while(result == NULL && !h_slist_empty(engines)) { + assert(h_slist_empty(engback)); + + // step all engines + while(!h_slist_empty(engines)) { + HLREngine *engine = h_slist_pop(engines); + const HLRAction *action = h_lrengine_action(engine); + glr_step(&result, engback, engine, action); } - // swap the arrays - HLREngine **tmp = engines; + // swap the lists + HSlist *tmp = engines; engines = engback; engback = tmp; }