From 6522530d839bcb431efa767bfe40a539ffeae619 Mon Sep 17 00:00:00 2001
From: picomeg <megordon5@gmail.com>
Date: Fri, 11 Nov 2022 06:00:10 +0000
Subject: [PATCH] extract code for dealing with parameter k for backends with
 lookahead k

---
 src/SConscript      |  5 +--
 src/backends/glr.c  | 84 ++++++++------------------------------------
 src/backends/lalr.c | 85 ++++++++-------------------------------------
 src/backends/llk.c  | 80 ++++++------------------------------------
 src/hammer.c        | 10 ++++++
 src/t_names.c       | 42 ++++++++++++++++++++++
 6 files changed, 96 insertions(+), 210 deletions(-)

diff --git a/src/SConscript b/src/SConscript
index f060ba12..cb646967 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -25,7 +25,8 @@ parsers_headers = [
 backends_headers = [
     'backends/regex.h',
     'backends/contextfree.h',
-    'backends/missing.h'
+    'backends/missing.h',
+    'backends/params.h'
 ]
 
 parsers = ['parsers/%s.c'%s for s in
@@ -60,7 +61,7 @@ parsers = ['parsers/%s.c'%s for s in
             'seek']]
 
 backends = ['backends/%s.c' % s for s in
-            ['missing', 'packrat', 'llk', 'regex', 'glr', 'lalr', 'lr', 'lr0']]
+            ['missing', 'packrat', 'llk', 'regex', 'glr', 'lalr', 'lr', 'lr0', 'params']]
 
 misc_hammer_parts = [
     'allocator.c',
diff --git a/src/backends/glr.c b/src/backends/glr.c
index 92ee09c5..06ab394b 100644
--- a/src/backends/glr.c
+++ b/src/backends/glr.c
@@ -1,5 +1,6 @@
 #include <assert.h>
 #include "lr.h"
+#include "params.h"
 
 static bool glr_step(HParseResult **result, HSlist *engines,
                      HLREngine *engine, const HLRAction *action);
@@ -244,35 +245,16 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
 char * h_glr_get_description(HAllocator *mm__,
                              HParserBackend be, void *param) {
   const char *format_str = "GLR(%zu) parser backend";
-  /* TODO fix the backend */
+
   const char *generic_descr_format_str =
-    "GLR(k) parser backend (actually using the param is broken)";
-  uintptr_t params_int;
-  size_t k, len;
+    "GLR(k) parser backend (default k is %zu)";
+
+  size_t k;
   char *descr = NULL;
 
-  params_int = (uintptr_t)param;
-  if (params_int > 0) {
-    /* A specific k was given */
-    k = (size_t)params_int;
-    /* Measure how big a buffer we need */
-    len = snprintf(NULL, 0, format_str, k);
-    /* Allocate it and do the real snprintf */
-    descr = h_new(char, len + 1);
-    if (descr) {
-      snprintf(descr, len + 1, format_str, k);
-    }
-  } else {
-    /*
-     * No specific k; TODO actually have a default and fix the backend
-     */
-    len = strlen(generic_descr_format_str);
-    /* Allocate and do the real snprintf */
-    descr = h_new(char, len + 1);
-    if (descr) {
-      strncpy(descr, generic_descr_format_str, len + 1);
-    }
-  }
+  k = h_get_param_k(param);
+
+  descr = h_format_description_with_param_k(mm__, format_str, generic_descr_format_str, k);
 
   return descr;
 }
@@ -280,57 +262,21 @@ char * h_glr_get_description(HAllocator *mm__,
 char * h_glr_get_short_name(HAllocator *mm__,
                             HParserBackend be, void *param) {
   const char *format_str = "GLR(%zu)", *generic_name = "GLR(k)";
-  uintptr_t params_int;
-  size_t k, len;
+
+  size_t k;
   char *name = NULL;
 
-  params_int = (uintptr_t)param;
-  if (params_int > 0) {
-    /* A specific k was given */
-    k = (size_t)params_int;
-    /* Measure how big a buffer we need */
-    len = snprintf(NULL, 0, format_str, k);
-    /* Allocate it and do the real snprintf */
-    name = h_new(char, len + 1);
-    if (name) {
-      snprintf(name, len + 1, format_str, k);
-    }
-  } else {
-    /* No specific k */
-    len = strlen(generic_name);
-    name = h_new(char, len + 1);
-    strncpy(name, generic_name, len + 1);
-  }
+  k = h_get_param_k(param);
+
+  name = h_format_name_with_param_k(mm__, format_str, generic_name, k);
 
   return name;
 }
 
-/*TODO: better handling of errors?*/
-int h_glr_extract_params(HParserBackendWithParams * be_with_params, backend_with_params_t * be_with_params_t) {
-
-  be_with_params->params = NULL;
-
-  int param_0 = -1;
-  int success = 0;
-  uintptr_t param;
 
-  size_t expected_params_len = 1;
-  backend_params_t params_t = be_with_params_t->params;
-  size_t actual_params_len = params_t.len;
-
-  if(actual_params_len >= expected_params_len) {
-    backend_param_with_name_t param_t = params_t.params[0];
-    uint8_t * param = param_t.param.param;
-    success = sscanf((char*)param, "%d", &param_0);
-  }
-
-  if(success) {
-    param = (uintptr_t) param_0;
-    be_with_params->params = (void *)param;
-  }
-
-  return success;
+int h_glr_extract_params(HParserBackendWithParams * be_with_params, backend_with_params_t * be_with_params_t) {
 
+  return h_extract_param_k(be_with_params, be_with_params_t);
 }
 
 HParserBackendVTable h__glr_backend_vtable = {
diff --git a/src/backends/lalr.c b/src/backends/lalr.c
index e4c00a2e..473f595a 100644
--- a/src/backends/lalr.c
+++ b/src/backends/lalr.c
@@ -1,8 +1,8 @@
 #include <assert.h>
 #include "contextfree.h"
 #include "lr.h"
+#include "params.h"
 
-static const size_t DEFAULT_K = 1;
 
 /* LALR-via-SLR grammar transformation */
 
@@ -275,7 +275,7 @@ HCFChoice *h_desugar_augmented(HAllocator *mm__, HParser *parser)
 
 int h_lalr_compile(HAllocator* mm__, HParser* parser, const void* params)
 {
-  size_t k = params? (uintptr_t)params : DEFAULT_K;
+  size_t k = params? (uintptr_t)params : DEFAULT_KMAX;
   // generate (augmented) CFG from parser
   // construct LR(0) DFA
   // build LR(0) table
@@ -377,35 +377,15 @@ void h_lalr_free(HParser *parser)
 char * h_lalr_get_description(HAllocator *mm__,
                               HParserBackend be, void *param) {
   const char *format_str = "LALR(%zu) parser backend";
-  /* TODO fix the backend */
+
   const char *generic_descr_format_str =
-    "LALR(k) parser backend (actually using the param is broken)";
-  uintptr_t params_int;
-  size_t k, len;
+    "LALR(k) parser backend  (default k is %zu)";
+  size_t k;
   char *descr = NULL;
 
-  params_int = (uintptr_t)param;
-  if (params_int > 0) {
-    /* A specific k was given */
-    k = (size_t)params_int;
-    /* Measure how big a buffer we need */
-    len = snprintf(NULL, 0, format_str, k);
-    /* Allocate it and do the real snprintf */
-    descr = h_new(char, len + 1);
-    if (descr) {
-      snprintf(descr, len + 1, format_str, k);
-    }
-  } else {
-    /*
-     * No specific k; TODO actually have a default and fix the backend
-     */
-    len = strlen(generic_descr_format_str);
-    /* Allocate and do the real snprintf */
-    descr = h_new(char, len + 1);
-    if (descr) {
-      strncpy(descr, generic_descr_format_str, len + 1);
-    }
-  }
+  k = h_get_param_k(param);
+
+  descr = h_format_description_with_param_k(mm__, format_str, generic_descr_format_str, k);
 
   return descr;
 }
@@ -413,56 +393,21 @@ char * h_lalr_get_description(HAllocator *mm__,
 char * h_lalr_get_short_name(HAllocator *mm__,
                             HParserBackend be, void *param) {
   const char *format_str = "LALR(%zu)", *generic_name = "LALR(k)";
-  uintptr_t params_int;
-  size_t k, len;
+
+  size_t k;
   char *name = NULL;
 
-  params_int = (uintptr_t)param;
-  if (params_int > 0) {
-    /* A specific k was given */
-    k = (size_t)params_int;
-    /* Measure how big a buffer we need */
-    len = snprintf(NULL, 0, format_str, k);
-    /* Allocate it and do the real snprintf */
-    name = h_new(char, len + 1);
-    if (name) {
-      snprintf(name, len + 1, format_str, k);
-    }
-  } else {
-    /* No specific k */
-    len = strlen(generic_name);
-    name = h_new(char, len + 1);
-    strncpy(name, generic_name, len + 1);
-  }
+  k = h_get_param_k(param);
+
+  name = h_format_name_with_param_k(mm__, format_str, generic_name, k);
 
   return name;
 }
 
-/*TODO better error handling*/
-int h_lalr_extract_params(HParserBackendWithParams * be_with_params, backend_with_params_t * be_with_params_t) {
-
-  be_with_params->params = NULL;
-
-  int param_0 = -1;
-  int success = 0;
-  uintptr_t param;
-
-  size_t expected_params_len = 1;
-  backend_params_t params_t = be_with_params_t->params;
-  size_t actual_params_len = params_t.len;
 
-  if(actual_params_len >= expected_params_len) {
-    backend_param_with_name_t param_t = params_t.params[0];
-    uint8_t * param = param_t.param.param;
-    success = sscanf((char*)param, "%d", &param_0);
-  }
-
-  if(success) {
-    param = (uintptr_t) param_0;
-    be_with_params->params = (void *)param;
-  }
+int h_lalr_extract_params(HParserBackendWithParams * be_with_params, backend_with_params_t * be_with_params_t) {
 
-  return success;
+  return h_extract_param_k(be_with_params, be_with_params_t);
 
 }
 
diff --git a/src/backends/llk.c b/src/backends/llk.c
index 064d859b..e0a9fc92 100644
--- a/src/backends/llk.c
+++ b/src/backends/llk.c
@@ -2,8 +2,7 @@
 #include "../internal.h"
 #include "../cfgrammar.h"
 #include "../parsers/parser_internal.h"
-
-static const size_t DEFAULT_KMAX = 1;
+#include "params.h"
 
 
 /* Generating the LL(k) parse table */
@@ -612,33 +611,13 @@ char * h_llk_get_description(HAllocator *mm__,
   const char *format_str = "LL(%zu) parser backend";
   const char *generic_descr_format_str =
     "LL(k) parser backend (default k is %zu)";
-  uintptr_t params_int;
+
   size_t k, len;
   char *descr = NULL;
 
-  params_int = (uintptr_t)param;
-  if (params_int > 0) {
-    /* A specific k was given */
-    k = (size_t)params_int;
-    /* Measure how big a buffer we need */
-    len = snprintf(NULL, 0, format_str, k);
-    /* Allocate it and do the real snprintf */
-    descr = h_new(char, len + 1);
-    if (descr) {
-      snprintf(descr, len + 1, format_str, k);
-    }
-  } else {
-    /*
-     * No specific k, would use DEFAULT_KMAX.  We say what DEFAULT_KMAX
-     * was compiled in in the description.
-     */
-    len = snprintf(NULL, 0, generic_descr_format_str, DEFAULT_KMAX);
-    /* Allocate and do the real snprintf */
-    descr = h_new(char, len + 1);
-    if (descr) {
-      snprintf(descr, len + 1, generic_descr_format_str, DEFAULT_KMAX);
-    }
-  }
+  k = h_get_param_k(param);
+
+  descr = h_format_description_with_param_k(mm__, format_str, generic_descr_format_str, k);
 
   return descr;
 }
@@ -646,57 +625,20 @@ char * h_llk_get_description(HAllocator *mm__,
 char * h_llk_get_short_name(HAllocator *mm__,
                             HParserBackend be, void *param) {
   const char *format_str = "LL(%zu)", *generic_name = "LL(k)";
-  uintptr_t params_int;
-  size_t k, len;
+
+  size_t k;
   char *name = NULL;
 
-  params_int = (uintptr_t)param;
-  if (params_int > 0) {
-    /* A specific k was given */
-    k = (size_t)params_int;
-    /* Measure how big a buffer we need */
-    len = snprintf(NULL, 0, format_str, k);
-    /* Allocate it and do the real snprintf */
-    name = h_new(char, len + 1);
-    if (name) {
-      snprintf(name, len + 1, format_str, k);
-    }
-  } else {
-    /* No specific k, would use DEFAULT_KMAX */
-    len = strlen(generic_name);
-    name = h_new(char, len + 1);
-    strncpy(name, generic_name, len + 1);
-  }
+  k = h_get_param_k(param);
+
+  name = h_format_name_with_param_k(mm__, format_str, generic_name, k);
 
   return name;
 }
 
-/*TODO better error handling*/
 int h_llk_extract_params(HParserBackendWithParams * be_with_params, backend_with_params_t *be_with_params_t) {
 
-  be_with_params->params = NULL;
-
-  int param_0 = -1;
-  int success = 0;
-  uintptr_t param;
-
-  size_t expected_params_len = 1;
-  backend_params_t params_t = be_with_params_t->params;
-  size_t actual_params_len = params_t.len;
-
-  if(actual_params_len >= expected_params_len) {
-    backend_param_with_name_t param_t = params_t.params[0];
-    uint8_t * param = param_t.param.param;
-    success = sscanf((char*)param, "%d", &param_0);
-  }
-
-  if(success) {
-    param = (uintptr_t) param_0;
-    be_with_params->params = (void *)param;
-  }
-
-  return success;
-
+  return h_extract_param_k(be_with_params, be_with_params_t);
 }
 
 
diff --git a/src/hammer.c b/src/hammer.c
index 648dbe27..e1933676 100644
--- a/src/hammer.c
+++ b/src/hammer.c
@@ -265,7 +265,17 @@ static char * h_get_string_for_backend_with_params__m(HAllocator *mm__,
  done:
   return text;
 }
+/* Allocate and return an identifying name for this backend
+ * with parameters.  The caller is responsible for freeing the result.
+ */
+char * h_get_name_for_backend_with_params__m(HAllocator *mm__,
+    HParserBackendWithParams *be_with_params) {
+  return h_get_string_for_backend_with_params__m(mm__, be_with_params, 0);
+}
 
+char * h_get_name_for_backend_with_params(HParserBackendWithParams *be_with_params) {
+  return h_get_name_for_backend_with_params__m(&system_allocator, be_with_params);
+}
 /*
  * Allocate and return some human-readable descriptive text for this backend
  * with parameters.  The caller is responsible for freeing the result.
diff --git a/src/t_names.c b/src/t_names.c
index e30a8b07..fc9a012b 100644
--- a/src/t_names.c
+++ b/src/t_names.c
@@ -115,6 +115,44 @@ static void test_tt_get_backend_with_params_by_name(void) {
 
 }
 
+static void test_tt_h_get_descriptive_text_for_backend_with_params(void){
+  HAllocator *mm__ = &system_allocator;
+  HParserBackendWithParams *be_with_params = h_get_backend_with_params_by_name("llk(1)");
+  char * descr = h_get_descriptive_text_for_backend_with_params(be_with_params);
+  g_check_maybe_string_eq(descr, "LL(1) parser backend");
+  h_free(descr);
+  h_free_backend_with_params(be_with_params);
+  be_with_params = h_get_backend_with_params_by_name("lalr(1)");
+  descr = h_get_descriptive_text_for_backend_with_params(be_with_params);
+  g_check_maybe_string_eq(descr, "LALR(1) parser backend");
+  h_free(descr);
+  h_free_backend_with_params(be_with_params);
+  be_with_params = h_get_backend_with_params_by_name("glr(2)");
+  descr = h_get_descriptive_text_for_backend_with_params(be_with_params);
+  g_check_maybe_string_eq(descr, "GLR(2) parser backend");
+  h_free(descr);
+  h_free_backend_with_params(be_with_params);
+}
+
+static void test_tt_h_get_name_for_backend_with_params(void){
+  HAllocator *mm__ = &system_allocator;
+  HParserBackendWithParams *be_with_params = h_get_backend_with_params_by_name("llk(1)");
+  char * descr = h_get_name_for_backend_with_params(be_with_params);
+  g_check_maybe_string_eq(descr, "LL(1)");
+  h_free(descr);
+  h_free_backend_with_params(be_with_params);
+  be_with_params = h_get_backend_with_params_by_name("lalr(2)");
+  descr = h_get_name_for_backend_with_params(be_with_params);
+  g_check_maybe_string_eq(descr, "LALR(2)");
+  h_free(descr);
+  h_free_backend_with_params(be_with_params);
+  be_with_params = h_get_backend_with_params_by_name("glr(1)");
+  descr = h_get_name_for_backend_with_params(be_with_params);
+  g_check_maybe_string_eq(descr, "GLR(1)");
+  h_free(descr);
+  h_free_backend_with_params(be_with_params);
+}
+
 /* test that we can request a backend with params from character
  * and compile a parser using it */
 static void test_tt_h_compile_for_backend_with_params(void) {
@@ -141,5 +179,9 @@ void register_names_tests(void) {
   g_test_add_func("/core/names/tt_backend_description", test_tt_backend_description);
   g_test_add_func("/core/names/tt_query_backend_by_name", test_tt_query_backend_by_name);
   g_test_add_func("/core/names/tt_get_backend_with_params_by_name", test_tt_get_backend_with_params_by_name);
+  g_test_add_func("/core/names/tt_test_tt_h_get_descriptive_text_for_backend_with_params",
+                  test_tt_h_get_descriptive_text_for_backend_with_params);
+  g_test_add_func("/core/names/test_tt_h_get_name_for_backend_with_params",
+                  test_tt_h_get_name_for_backend_with_params);
   g_test_add_func("/core/names/tt_h_compile_for_backend_with_params", test_tt_h_compile_for_backend_with_params);
  }
-- 
GitLab