From 55c9a3d9c51fb752e89c85f49987a124c35acc88 Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Wed, 19 Jun 2013 17:20:53 +0200
Subject: [PATCH] add stub GLR backend with h_glr_parse() a copy of
 h_lr_parse()

---
 src/Makefile       |  3 +-
 src/backends/glr.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++
 src/backends/lr.h  |  1 +
 src/hammer.c       |  1 +
 src/hammer.h       |  4 +-
 src/internal.h     |  1 +
 src/t_parser.c     | 38 +++++++++++++++++++
 7 files changed, 138 insertions(+), 3 deletions(-)
 create mode 100644 src/backends/glr.c

diff --git a/src/Makefile b/src/Makefile
index 380436ae..9ce6d9f8 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 00000000..c57ffd6b
--- /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 13e10d41..f766d5b7 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 7d5b4e90..7fc80dba 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 a5ebcfff..67fb8e4b 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 2f3018df..d8b221a7 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 a0e4040b..57486cdc 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);
 }
-- 
GitLab