add iterative API to LALR backend
This commit is contained in:
parent
ff55937e00
commit
caf00006f3
4 changed files with 67 additions and 5 deletions
|
|
@ -346,7 +346,10 @@ void h_lalr_free(HParser *parser)
|
||||||
HParserBackendVTable h__lalr_backend_vtable = {
|
HParserBackendVTable h__lalr_backend_vtable = {
|
||||||
.compile = h_lalr_compile,
|
.compile = h_lalr_compile,
|
||||||
.parse = h_lr_parse,
|
.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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -199,15 +199,14 @@ bool h_lrtable_row_empty(const HLRTable *table, size_t i)
|
||||||
|
|
||||||
/* LR driver */
|
/* LR driver */
|
||||||
|
|
||||||
HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
|
static
|
||||||
const HInputStream *stream)
|
HLREngine *h_lrengine_new_(HArena *arena, HArena *tarena, const HLRTable *table)
|
||||||
{
|
{
|
||||||
HLREngine *engine = h_arena_malloc(tarena, sizeof(HLREngine));
|
HLREngine *engine = h_arena_malloc(tarena, sizeof(HLREngine));
|
||||||
|
|
||||||
engine->table = table;
|
engine->table = table;
|
||||||
engine->state = 0;
|
engine->state = 0;
|
||||||
engine->stack = h_slist_new(tarena);
|
engine->stack = h_slist_new(tarena);
|
||||||
engine->input = *stream;
|
|
||||||
engine->merged[0] = NULL;
|
engine->merged[0] = NULL;
|
||||||
engine->merged[1] = NULL;
|
engine->merged[1] = NULL;
|
||||||
engine->arena = arena;
|
engine->arena = arena;
|
||||||
|
|
@ -216,6 +215,14 @@ HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
|
||||||
return engine;
|
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 *
|
static const HLRAction *
|
||||||
terminal_lookup(const HLREngine *engine, const HInputStream *stream)
|
terminal_lookup(const HLREngine *engine, const HInputStream *stream)
|
||||||
{
|
{
|
||||||
|
|
@ -352,7 +359,7 @@ HParseResult *h_lrengine_result(HLREngine *engine)
|
||||||
assert(!h_slist_empty(engine->stack));
|
assert(!h_slist_empty(engine->stack));
|
||||||
HParsedToken *tok = engine->stack->head->elem;
|
HParsedToken *tok = engine->stack->head->elem;
|
||||||
HParseResult *res = make_result(engine->arena, tok);
|
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;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -379,7 +386,53 @@ HParseResult *h_lr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
|
||||||
return result;
|
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 */
|
/* Pretty-printers */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,9 @@ const HLRAction *h_lrengine_action(const HLREngine *engine);
|
||||||
bool h_lrengine_step(HLREngine *engine, const HLRAction *action);
|
bool h_lrengine_step(HLREngine *engine, const HLRAction *action);
|
||||||
HParseResult *h_lrengine_result(HLREngine *engine);
|
HParseResult *h_lrengine_result(HLREngine *engine);
|
||||||
HParseResult *h_lr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream);
|
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);
|
HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream);
|
||||||
|
|
||||||
void h_pprint_lritem(FILE *f, const HCFGrammar *g, const HLRItem *item);
|
void h_pprint_lritem(FILE *f, const HCFGrammar *g, const HLRItem *item);
|
||||||
|
|
|
||||||
|
|
@ -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/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/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/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/token", GINT_TO_POINTER(PB_GLR), test_token);
|
||||||
g_test_add_data_func("/core/parser/glr/ch", GINT_TO_POINTER(PB_GLR), test_ch);
|
g_test_add_data_func("/core/parser/glr/ch", GINT_TO_POINTER(PB_GLR), test_ch);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue