From 23afea4b4e6fa00262c0b0cfbd958fa3e9e44093 Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" <pesco@khjk.org> Date: Sat, 22 Jun 2013 14:21:19 +0200 Subject: [PATCH] add demerge code path (untested) --- src/backends/glr.c | 55 +++++++++++++++++++++++++++++++++++++++------- src/backends/lr.c | 1 + src/backends/lr.h | 3 ++- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/backends/glr.c b/src/backends/glr.c index 2978e62d..411171b7 100644 --- a/src/backends/glr.c +++ b/src/backends/glr.c @@ -70,15 +70,54 @@ static const HLRAction *handle_conflict(HSlist *engines, const HLREngine *engine return branches->head->elem; } -static HLREngine *handle_demerge(HSlist *engines, HLREngine *engine, - const HLRAction *reduce) +static HSlist *demerge_stack(HSlistNode *bottom, HSlistNode *mp, HSlist *stack) { - return engine; // XXX + HArena *arena = stack->arena; + + HSlist *ret = h_slist_new(arena); + + // copy the stack from the top + HSlistNode **y = &ret->head; + for(HSlistNode *x=stack->head; x && x!=mp; x=x->next) { + HSlistNode *node = h_arena_malloc(arena, sizeof(HSlistNode)); + node->elem = x->elem; + node->next = NULL; + *y = node; + y = &node->next; + } + *y = bottom; // attach the ancestor stack + + return ret; +} - for(size_t i=0; i<reduce->production.length; i++) { - // XXX if stack hits bottom, demerge +static void demerge(HSlist *engines, HLREngine *engine, + const HLRAction *action, size_t depth) +{ + // no-op on engines that are not merged + if(!engine->merged) + return; + + HSlistNode *p = engine->stack->head; + for(size_t i=0; i<depth; i++) { + // if stack hits mergepoint, respawn ancestor + if(p == engine->mp) { + HLREngine *eng = engine->merged; + eng->stack = demerge_stack(eng->stack->head, engine->mp, engine->stack); + demerge(engines, eng, action, depth-i); + + // call step and stow on restored ancestor + h_lrengine_step(eng, action); + stow_engine(engines, eng); + break; + } + p = p->next; } - // XXX call step and stow on the newly-created engines +} + +static inline void +handle_demerge(HSlist *engines, HLREngine *engine, const HLRAction *reduce) +{ + demerge(engines, engine, reduce, reduce->production.length); } HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream) @@ -119,8 +158,8 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* // fork engine on conflicts action = handle_conflict(engines, engine, action->branches); } else if(action->type == HLR_REDUCE) { - // demerge as needed to ensure that stacks are deep enough - engine = handle_demerge(engines, engine, action); + // demerge/respawn as needed + handle_demerge(engines, engine, action); } } diff --git a/src/backends/lr.c b/src/backends/lr.c index bb20f714..c481d291 100644 --- a/src/backends/lr.c +++ b/src/backends/lr.c @@ -210,6 +210,7 @@ HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table, engine->stack = h_slist_new(tarena); engine->input = *stream; engine->merged = NULL; + engine->mp = NULL; engine->arena = arena; engine->tarena = tarena; diff --git a/src/backends/lr.h b/src/backends/lr.h index 5febc247..ab486335 100644 --- a/src/backends/lr.h +++ b/src/backends/lr.h @@ -74,7 +74,8 @@ typedef struct HLREngine_ { HSlist *stack; // holds pairs: (saved state, semantic value) HInputStream input; - HSlist *merged; // saved ancestor engines that merged to form this one + struct HLREngine_ *merged; // ancestor merged into this engine at mp + HSlistNode *mp; // mergepoint: stack->head at time of merge HArena *arena; // will hold the results HArena *tarena; // tmp, deleted after parse -- GitLab