refactoring in preparation for engine merging

This commit is contained in:
Sven M. Hallberg 2013-06-22 12:51:25 +02:00
parent 8bc3b93e95
commit bf9c9b5f7a
3 changed files with 57 additions and 27 deletions

View file

@ -43,6 +43,44 @@ HLREngine *fork_engine(const HLREngine *engine)
return eng2; return eng2;
} }
static void stow_engine(HSlist *engines, HLREngine *engine)
{
// XXX switch to one engine per state, and do the merge here
h_slist_push(engines, engine);
}
static const HLRAction *handle_conflict(HSlist *engines, const HLREngine *engine,
const HSlist *branches)
{
// there should be at least two conflicting actions
assert(branches->head);
assert(branches->head->next); // this is just a consistency check
// fork a new engine for all but the first action
for(HSlistNode *x=branches->head->next; x; x=x->next) {
HLRAction *act = x->elem;
HLREngine *eng = fork_engine(engine);
// perform one step and add to list
h_lrengine_step(eng, act);
stow_engine(engines, eng);
}
// return first action for use with original engine
return branches->head->elem;
}
static HLREngine *handle_demerge(HSlist *engines, HLREngine *engine,
const HLRAction *reduce)
{
return engine; // XXX
for(size_t i=0; i<reduce->production.length; i++) {
// XXX if stack hits bottom, demerge
}
// XXX call step and stow on the newly-created engines
}
HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream) HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream)
{ {
HLRTable *table = parser->backend_data; HLRTable *table = parser->backend_data;
@ -60,12 +98,11 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
for(HSlistNode **x = &engines->head; *x; ) { for(HSlistNode **x = &engines->head; *x; ) {
HLREngine *engine = (*x)->elem; HLREngine *engine = (*x)->elem;
// check for terminated engines // remove engine from list; it may come back in below
if(engine->run) { *x = (*x)->next; // advance x, removing the current element
x = &(*x)->next; // advance x with no change
} else {
*x = (*x)->next; // advance x, removing the current element
// drop those engines that have terminated
if(!engine->run) {
// check for parse success // check for parse success
HParseResult *res = h_lrengine_result(engine); HParseResult *res = h_lrengine_result(engine);
if(res) if(res)
@ -76,29 +113,19 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
const HLRAction *action = h_lrengine_action(engine); const HLRAction *action = h_lrengine_action(engine);
// fork engine on conflicts // handle forks and demerges (~> spawn engines)
if(action && action->type == HLR_CONFLICT) { if(action) {
const HSlist *branches = action->branches; if(action->type == HLR_CONFLICT) {
// fork engine on conflicts
// there should be at least two conflicting actions action = handle_conflict(engines, engine, action->branches);
assert(branches->head); } else if(action->type == HLR_REDUCE) {
assert(branches->head->next); // demerge as needed to ensure that stacks are deep enough
engine = handle_demerge(engines, engine, action);
// save first action for use with old engine below
action = branches->head->elem;
// fork a new engine for all the other actions
for(HSlistNode *x=branches->head->next; x; x=x->next) {
HLRAction *act = x->elem;
HLREngine *eng = fork_engine(engine);
// perform one step and add to list
h_lrengine_step(eng, act);
h_slist_push(engines, eng);
} }
} }
h_lrengine_step(engine, action); h_lrengine_step(engine, action);
stow_engine(engines, engine);
} }
} }

View file

@ -209,6 +209,7 @@ HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
engine->run = true; engine->run = true;
engine->stack = h_slist_new(tarena); engine->stack = h_slist_new(tarena);
engine->input = *stream; engine->input = *stream;
engine->merged = NULL;
engine->arena = arena; engine->arena = arena;
engine->tarena = tarena; engine->tarena = tarena;

View file

@ -74,8 +74,10 @@ typedef struct HLREngine_ {
HSlist *stack; // holds pairs: (saved state, semantic value) HSlist *stack; // holds pairs: (saved state, semantic value)
HInputStream input; HInputStream input;
HArena *arena; // will hold the results HSlist *merged; // saved ancestor engines that merged to form this one
HArena *tarena; // tmp, deleted after parse
HArena *arena; // will hold the results
HArena *tarena; // tmp, deleted after parse
} HLREngine; } HLREngine;