add iterative API to LALR backend

This commit is contained in:
Sven M. Hallberg 2015-09-16 23:43:30 +02:00
parent ff55937e00
commit caf00006f3
4 changed files with 67 additions and 5 deletions

View file

@ -346,7 +346,10 @@ void h_lalr_free(HParser *parser)
HParserBackendVTable h__lalr_backend_vtable = {
.compile = h_lalr_compile,
.parse = h_lr_parse,
.free = h_lalr_free
.free = h_lalr_free,
.parse_start = h_lr_parse_start,
.parse_chunk = h_lr_parse_chunk,
.parse_finish = h_lr_parse_finish
};

View file

@ -199,15 +199,14 @@ bool h_lrtable_row_empty(const HLRTable *table, size_t i)
/* LR driver */
HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
const HInputStream *stream)
static
HLREngine *h_lrengine_new_(HArena *arena, HArena *tarena, const HLRTable *table)
{
HLREngine *engine = h_arena_malloc(tarena, sizeof(HLREngine));
engine->table = table;
engine->state = 0;
engine->stack = h_slist_new(tarena);
engine->input = *stream;
engine->merged[0] = NULL;
engine->merged[1] = NULL;
engine->arena = arena;
@ -216,6 +215,14 @@ HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
return engine;
}
HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
const HInputStream *stream)
{
HLREngine *engine = h_lrengine_new_(arena, tarena, table);
engine->input = *stream;
return engine;
}
static const HLRAction *
terminal_lookup(const HLREngine *engine, const HInputStream *stream)
{
@ -352,7 +359,7 @@ HParseResult *h_lrengine_result(HLREngine *engine)
assert(!h_slist_empty(engine->stack));
HParsedToken *tok = engine->stack->head->elem;
HParseResult *res = make_result(engine->arena, tok);
res->bit_length = engine->input.index * 8;
res->bit_length = (engine->input.pos + engine->input.index) * 8;
return res;
} else {
return NULL;
@ -379,7 +386,53 @@ HParseResult *h_lr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
return result;
}
void h_lr_parse_start(HSuspendedParser *s)
{
HLRTable *table = s->parser->backend_data;
assert(table != NULL);
HArena *arena = h_new_arena(s->mm__, 0); // will hold the results
HArena *tarena = h_new_arena(s->mm__, 0); // tmp, deleted after parse
HLREngine *engine = h_lrengine_new_(arena, tarena, table);
s->backend_state = engine;
}
bool h_lr_parse_chunk(HSuspendedParser* s, HInputStream *stream)
{
HLREngine *engine = s->backend_state;
engine->input = *stream;
bool run = true;
while(run) {
// check input against table to determine which action to take
const HLRAction *action = h_lrengine_action(engine);
if(action == NEED_INPUT) {
// XXX assume lookahead 1
assert(engine->input.length - engine->input.index == 0);
break;
}
// execute action
run = h_lrengine_step(engine, action);
if(engine->input.overrun && !engine->input.last_chunk)
break;
}
*stream = engine->input;
return !run; // done if engine no longer running
}
HParseResult *h_lr_parse_finish(HSuspendedParser *s)
{
HLREngine *engine = s->backend_state;
HParseResult *result = h_lrengine_result(engine);
if(!result)
h_delete_arena(engine->arena);
h_delete_arena(engine->tarena);
return result;
}
/* Pretty-printers */

View file

@ -134,6 +134,9 @@ const HLRAction *h_lrengine_action(const HLREngine *engine);
bool h_lrengine_step(HLREngine *engine, const HLRAction *action);
HParseResult *h_lrengine_result(HLREngine *engine);
HParseResult *h_lr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream);
void h_lr_parse_start(HSuspendedParser *s);
bool h_lr_parse_chunk(HSuspendedParser* s, HInputStream *stream);
HParseResult *h_lr_parse_finish(HSuspendedParser *s);
HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream);
void h_pprint_lritem(FILE *f, const HCFGrammar *g, const HLRItem *item);

View file

@ -883,6 +883,9 @@ void register_parser_tests(void) {
g_test_add_data_func("/core/parser/lalr/leftrec-ne", GINT_TO_POINTER(PB_LALR), test_leftrec_ne);
g_test_add_data_func("/core/parser/lalr/rightrec", GINT_TO_POINTER(PB_LALR), test_rightrec);
g_test_add_data_func("/core/parser/lalr/result_length", GINT_TO_POINTER(PB_LALR), test_result_length);
g_test_add_data_func("/core/parser/lalr/iterative", GINT_TO_POINTER(PB_LALR), test_iterative);
g_test_add_data_func("/core/parser/lalr/iterative/lookahead", GINT_TO_POINTER(PB_LALR), test_iterative_lookahead);
g_test_add_data_func("/core/parser/lalr/iterative/result_length", GINT_TO_POINTER(PB_LALR), test_iterative_result_length);
g_test_add_data_func("/core/parser/glr/token", GINT_TO_POINTER(PB_GLR), test_token);
g_test_add_data_func("/core/parser/glr/ch", GINT_TO_POINTER(PB_GLR), test_ch);