From caf00006f33a7cd6a35cd051add147bad4f33d8a Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" <pesco@khjk.org> Date: Wed, 16 Sep 2015 23:43:30 +0200 Subject: [PATCH] add iterative API to LALR backend --- src/backends/lalr.c | 5 +++- src/backends/lr.c | 61 ++++++++++++++++++++++++++++++++++++++++++--- src/backends/lr.h | 3 +++ src/t_parser.c | 3 +++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/backends/lalr.c b/src/backends/lalr.c index ec7a5b5f..975735a1 100644 --- a/src/backends/lalr.c +++ b/src/backends/lalr.c @@ -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 }; diff --git a/src/backends/lr.c b/src/backends/lr.c index 161bbf96..3f99eb51 100644 --- a/src/backends/lr.c +++ b/src/backends/lr.c @@ -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 */ diff --git a/src/backends/lr.h b/src/backends/lr.h index f9cb9a20..724d126c 100644 --- a/src/backends/lr.h +++ b/src/backends/lr.h @@ -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); diff --git a/src/t_parser.c b/src/t_parser.c index a8bdb0d0..3d54ff6b 100644 --- a/src/t_parser.c +++ b/src/t_parser.c @@ -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); -- GitLab