add demerge code path (untested)
This commit is contained in:
parent
bf9c9b5f7a
commit
23afea4b4e
3 changed files with 50 additions and 9 deletions
|
|
@ -70,15 +70,54 @@ static const HLRAction *handle_conflict(HSlist *engines, const HLREngine *engine
|
||||||
return branches->head->elem;
|
return branches->head->elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HLREngine *handle_demerge(HSlist *engines, HLREngine *engine,
|
static HSlist *demerge_stack(HSlistNode *bottom, HSlistNode *mp, HSlist *stack)
|
||||||
const HLRAction *reduce)
|
|
||||||
{
|
{
|
||||||
return engine; // XXX
|
HArena *arena = stack->arena;
|
||||||
|
|
||||||
for(size_t i=0; i<reduce->production.length; i++) {
|
HSlist *ret = h_slist_new(arena);
|
||||||
// XXX if stack hits bottom, demerge
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
// XXX call step and stow on the newly-created engines
|
*y = bottom; // attach the ancestor stack
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
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
|
// fork engine on conflicts
|
||||||
action = handle_conflict(engines, engine, action->branches);
|
action = handle_conflict(engines, engine, action->branches);
|
||||||
} else if(action->type == HLR_REDUCE) {
|
} else if(action->type == HLR_REDUCE) {
|
||||||
// demerge as needed to ensure that stacks are deep enough
|
// demerge/respawn as needed
|
||||||
engine = handle_demerge(engines, engine, action);
|
handle_demerge(engines, engine, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
|
||||||
engine->stack = h_slist_new(tarena);
|
engine->stack = h_slist_new(tarena);
|
||||||
engine->input = *stream;
|
engine->input = *stream;
|
||||||
engine->merged = NULL;
|
engine->merged = NULL;
|
||||||
|
engine->mp = NULL;
|
||||||
engine->arena = arena;
|
engine->arena = arena;
|
||||||
engine->tarena = tarena;
|
engine->tarena = tarena;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,8 @@ typedef struct HLREngine_ {
|
||||||
HSlist *stack; // holds pairs: (saved state, semantic value)
|
HSlist *stack; // holds pairs: (saved state, semantic value)
|
||||||
HInputStream input;
|
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 *arena; // will hold the results
|
||||||
HArena *tarena; // tmp, deleted after parse
|
HArena *tarena; // tmp, deleted after parse
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue