diff --git a/src/Makefile b/src/Makefile index 380436ae42f951dedccb8b5c7e9757fd025b5476..9ce6d9f8314ddbf22f1083c880dad86a349b82d9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,9 +27,10 @@ PARSERS := \ BACKENDS := \ packrat \ + regex \ llk \ lalr \ - regex + glr HAMMER_PARTS := \ bitreader.o \ diff --git a/src/backends/glr.c b/src/backends/glr.c new file mode 100644 index 0000000000000000000000000000000000000000..c57ffd6b698fdff78b213d2f433c9adc898398fd --- /dev/null +++ b/src/backends/glr.c @@ -0,0 +1,93 @@ +#include "lr.h" + + + +/* GLR driver */ + +HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream) +{ + HLRTable *table = parser->backend_data; + if(!table) + return NULL; + + HArena *arena = h_new_arena(mm__, 0); // will hold the results + HArena *tarena = h_new_arena(mm__, 0); // tmp, deleted after parse + HLREngine *engine = h_lrengine_new(arena, tarena, table); + + // iterate engine to completion + while(h_lrengine_step(engine, h_lrengine_action(engine, stream))); + + HParseResult *result = h_lrengine_result(engine); + if(!result) + h_delete_arena(arena); + h_delete_arena(tarena); + return result; +} + + + +HParserBackendVTable h__glr_backend_vtable = { + .compile = h_lalr_compile, + .parse = h_glr_parse, + .free = h_lalr_free +}; + + + + +// dummy! +int test_glr(void) +{ + /* + E -> E '-' T + | T + T -> '(' E ')' + | 'n' -- also try [0-9] for the charset paths + */ + + HParser *n = h_ch('n'); + HParser *E = h_indirect(); + HParser *T = h_choice(h_sequence(h_ch('('), E, h_ch(')'), NULL), n, NULL); + HParser *E_ = h_choice(h_sequence(E, h_ch('-'), T, NULL), T, NULL); + h_bind_indirect(E, E_); + HParser *p = E; + + printf("\n==== G R A M M A R ====\n"); + HCFGrammar *g = h_cfgrammar(&system_allocator, p); + if(g == NULL) { + fprintf(stderr, "h_cfgrammar failed\n"); + return 1; + } + h_pprint_grammar(stdout, g, 0); + + printf("\n==== D F A ====\n"); + HLRDFA *dfa = h_lr0_dfa(g); + if(dfa) + h_pprint_lrdfa(stdout, g, dfa, 0); + else + fprintf(stderr, "h_lalr_dfa failed\n"); + + printf("\n==== L R ( 0 ) T A B L E ====\n"); + HLRTable *table0 = h_lr0_table(g, dfa); + if(table0) + h_pprint_lrtable(stdout, g, table0, 0); + else + fprintf(stderr, "h_lr0_table failed\n"); + h_lrtable_free(table0); + + printf("\n==== L A L R T A B L E ====\n"); + if(h_compile(p, PB_GLR, NULL)) { + fprintf(stderr, "does not compile\n"); + return 2; + } + h_pprint_lrtable(stdout, g, (HLRTable *)p->backend_data, 0); + + printf("\n==== P A R S E R E S U L T ====\n"); + HParseResult *res = h_parse(p, (uint8_t *)"n-(n-((n)))-n", 13); + if(res) + h_pprint(stdout, res->ast, 0, 2); + else + printf("no parse\n"); + + return 0; +} diff --git a/src/backends/lr.h b/src/backends/lr.h index 13e10d41cf4eac5d692457a286f2c9ed533e35a3..f766d5b791747a6a2c6592718270242cd3394b38 100644 --- a/src/backends/lr.h +++ b/src/backends/lr.h @@ -131,6 +131,7 @@ const HLRAction *h_lrengine_action(HLREngine *engine, HInputStream *stream); 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); +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_lrstate(FILE *f, const HCFGrammar *g, diff --git a/src/hammer.c b/src/hammer.c index 7d5b4e90b2edd224f6f28a57d0b65bacf2de94b7..7fc80dba0c86ec76a2376d0d69914f235bf08afc 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -31,6 +31,7 @@ static HParserBackendVTable *backends[PB_MAX + 1] = { &h__regex_backend_vtable, &h__llk_backend_vtable, &h__lalr_backend_vtable, + &h__glr_backend_vtable, }; diff --git a/src/hammer.h b/src/hammer.h index a5ebcfff640bd33ba4459b1b59ea106033cb5eb2..67fb8e4bff34eb741d7f14d3c64fcba160598369 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -37,8 +37,8 @@ typedef enum HParserBackend_ { PB_REGULAR, PB_LLk, PB_LALR, - PB_GLR, // Not Implemented - PB_MAX = PB_LALR + PB_GLR, + PB_MAX = PB_GLR } HParserBackend; typedef enum HTokenType_ { diff --git a/src/internal.h b/src/internal.h index 2f3018df2aebe3e61b2af74c3b4b5a70997211f2..d8b221a72b1ed45d2b795771dfc6a0f7f9c1cc32 100644 --- a/src/internal.h +++ b/src/internal.h @@ -220,6 +220,7 @@ struct HBitWriter_ { extern HParserBackendVTable h__packrat_backend_vtable; extern HParserBackendVTable h__llk_backend_vtable; extern HParserBackendVTable h__lalr_backend_vtable; +extern HParserBackendVTable h__glr_backend_vtable; // }}} // TODO(thequux): Set symbol visibility for these functions so that they aren't exported. diff --git a/src/t_parser.c b/src/t_parser.c index a0e4040b2d5378c423b07d0699001b6a5018594e..57486cdc1044b2ed7d73b9a01118b1228d13a028 100644 --- a/src/t_parser.c +++ b/src/t_parser.c @@ -585,4 +585,42 @@ void register_parser_tests(void) { g_test_add_data_func("/core/parser/lalr/ignore", GINT_TO_POINTER(PB_LALR), test_ignore); g_test_add_data_func("/core/parser/lalr/leftrec", GINT_TO_POINTER(PB_LALR), test_leftrec); g_test_add_data_func("/core/parser/lalr/rightrec", GINT_TO_POINTER(PB_LALR), test_rightrec); + + 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_range", GINT_TO_POINTER(PB_GLR), test_ch_range); + g_test_add_data_func("/core/parser/glr/int64", GINT_TO_POINTER(PB_GLR), test_int64); + g_test_add_data_func("/core/parser/glr/int32", GINT_TO_POINTER(PB_GLR), test_int32); + g_test_add_data_func("/core/parser/glr/int16", GINT_TO_POINTER(PB_GLR), test_int16); + g_test_add_data_func("/core/parser/glr/int8", GINT_TO_POINTER(PB_GLR), test_int8); + g_test_add_data_func("/core/parser/glr/uint64", GINT_TO_POINTER(PB_GLR), test_uint64); + g_test_add_data_func("/core/parser/glr/uint32", GINT_TO_POINTER(PB_GLR), test_uint32); + g_test_add_data_func("/core/parser/glr/uint16", GINT_TO_POINTER(PB_GLR), test_uint16); + g_test_add_data_func("/core/parser/glr/uint8", GINT_TO_POINTER(PB_GLR), test_uint8); + g_test_add_data_func("/core/parser/glr/int_range", GINT_TO_POINTER(PB_GLR), test_int_range); +#if 0 + g_test_add_data_func("/core/parser/glr/float64", GINT_TO_POINTER(PB_GLR), test_float64); + g_test_add_data_func("/core/parser/glr/float32", GINT_TO_POINTER(PB_GLR), test_float32); +#endif + g_test_add_data_func("/core/parser/glr/whitespace", GINT_TO_POINTER(PB_GLR), test_whitespace); + g_test_add_data_func("/core/parser/glr/left", GINT_TO_POINTER(PB_GLR), test_left); + g_test_add_data_func("/core/parser/glr/right", GINT_TO_POINTER(PB_GLR), test_right); + g_test_add_data_func("/core/parser/glr/middle", GINT_TO_POINTER(PB_GLR), test_middle); + g_test_add_data_func("/core/parser/glr/action", GINT_TO_POINTER(PB_GLR), test_action); + g_test_add_data_func("/core/parser/glr/in", GINT_TO_POINTER(PB_GLR), test_in); + g_test_add_data_func("/core/parser/glr/not_in", GINT_TO_POINTER(PB_GLR), test_not_in); + g_test_add_data_func("/core/parser/glr/end_p", GINT_TO_POINTER(PB_GLR), test_end_p); + g_test_add_data_func("/core/parser/glr/nothing_p", GINT_TO_POINTER(PB_GLR), test_nothing_p); + g_test_add_data_func("/core/parser/glr/sequence", GINT_TO_POINTER(PB_GLR), test_sequence); + g_test_add_data_func("/core/parser/glr/choice", GINT_TO_POINTER(PB_GLR), test_choice); + g_test_add_data_func("/core/parser/glr/many", GINT_TO_POINTER(PB_GLR), test_many); + g_test_add_data_func("/core/parser/glr/many1", GINT_TO_POINTER(PB_GLR), test_many1); + g_test_add_data_func("/core/parser/glr/optional", GINT_TO_POINTER(PB_GLR), test_optional); + g_test_add_data_func("/core/parser/glr/sepBy", GINT_TO_POINTER(PB_GLR), test_sepBy); + g_test_add_data_func("/core/parser/glr/sepBy1", GINT_TO_POINTER(PB_GLR), test_sepBy1); + g_test_add_data_func("/core/parser/glr/epsilon_p", GINT_TO_POINTER(PB_GLR), test_epsilon_p); + g_test_add_data_func("/core/parser/glr/attr_bool", GINT_TO_POINTER(PB_GLR), test_attr_bool); + g_test_add_data_func("/core/parser/glr/ignore", GINT_TO_POINTER(PB_GLR), test_ignore); + g_test_add_data_func("/core/parser/glr/leftrec", GINT_TO_POINTER(PB_GLR), test_leftrec); + g_test_add_data_func("/core/parser/glr/rightrec", GINT_TO_POINTER(PB_GLR), test_rightrec); }