From d77a8305e8d21b4c92f051570ddaf8169e179e02 Mon Sep 17 00:00:00 2001 From: picomeg <megordon5@gmail.com> Date: Fri, 25 Sep 2020 20:08:48 +0100 Subject: [PATCH] capability to extract name of backend and params from string of form "glr(1)" and call compile for the appropriate backend. Needs clean up and refactor, and tests, but it compiles and my hard-drive is periodically making threatening noises... --- src/backends/glr.c | 25 +++++++++++-- src/backends/lalr.c | 25 +++++++++++-- src/backends/llk.c | 22 +++++++++++- src/hammer.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ src/hammer.h | 23 +++++++++++- src/internal.h | 3 ++ 6 files changed, 176 insertions(+), 8 deletions(-) diff --git a/src/backends/glr.c b/src/backends/glr.c index 781b9aee..b91f7c45 100644 --- a/src/backends/glr.c +++ b/src/backends/glr.c @@ -266,11 +266,11 @@ char * h_glr_get_description(HAllocator *mm__, /* * No specific k; TODO actually have a default and fix the backend */ - len = snprintf(NULL, 0, generic_descr_format_str); + len = strlen(generic_descr_format_str); /* Allocate and do the real snprintf */ descr = h_new(char, len + 1); if (descr) { - snprintf(descr, len + 1, generic_descr_format_str); + strncpy(descr, generic_descr_format_str, len + 1); } } @@ -305,6 +305,23 @@ char * h_glr_get_short_name(HAllocator *mm__, return name; } +int h_glr_extract_params(void ** params, char* raw_params) { + + params = NULL; + + int param_0 = -1; + int success = 0; + + success = sscanf(raw_params + 1, "%d", ¶m_0); + + if(success) { + *params = (void *)(unsigned long long) param_0; + } + + return success; + +} + HParserBackendVTable h__glr_backend_vtable = { .compile = h_glr_compile, .parse = h_glr_parse, @@ -317,7 +334,9 @@ HParserBackendVTable h__glr_backend_vtable = { .backend_short_name = "glr", .backend_description = "GLR(k) parser backend", .get_description_with_params = h_glr_get_description, - .get_short_name_with_params = h_glr_get_short_name + .get_short_name_with_params = h_glr_get_short_name, + + .extract_params = h_glr_extract_params }; diff --git a/src/backends/lalr.c b/src/backends/lalr.c index cc7ff36c..2f0f27e5 100644 --- a/src/backends/lalr.c +++ b/src/backends/lalr.c @@ -397,11 +397,11 @@ char * h_lalr_get_description(HAllocator *mm__, /* * No specific k; TODO actually have a default and fix the backend */ - len = snprintf(NULL, 0, generic_descr_format_str); + len = strlen(generic_descr_format_str); /* Allocate and do the real snprintf */ descr = h_new(char, len + 1); if (descr) { - snprintf(descr, len + 1, generic_descr_format_str); + strncpy(descr, generic_descr_format_str, len + 1); } } @@ -436,6 +436,23 @@ char * h_lalr_get_short_name(HAllocator *mm__, return name; } +int h_lalr_extract_params(void ** params, char* raw_params) { + + params = NULL; + + int param_0 = -1; + int success = 0; + + success = sscanf(raw_params + 1, "%d", ¶m_0); + + if(success) { + *params = (void *)(unsigned long long) param_0; + } + + return success; + +} + HParserBackendVTable h__lalr_backend_vtable = { .compile = h_lalr_compile, .parse = h_lr_parse, @@ -450,7 +467,9 @@ HParserBackendVTable h__lalr_backend_vtable = { .backend_short_name = "lalr", .backend_description = "LALR(k) parser backend", .get_description_with_params = h_lalr_get_description, - .get_short_name_with_params = h_lalr_get_short_name + .get_short_name_with_params = h_lalr_get_short_name, + + .extract_params = h_lalr_extract_params }; // dummy! diff --git a/src/backends/llk.c b/src/backends/llk.c index b2e89e33..cf7e2aba 100644 --- a/src/backends/llk.c +++ b/src/backends/llk.c @@ -670,6 +670,23 @@ char * h_llk_get_short_name(HAllocator *mm__, return name; } +int h_llk_extract_params(void ** params, char * raw_params) { + + params = NULL; + + int param_0 = -1; + int success = 0; + + success = sscanf(raw_params + 1, "%d", ¶m_0); + + if(success) { + *params = (void *)(unsigned long long) param_0; + } + + return success; + +} + HParserBackendVTable h__llk_backend_vtable = { .compile = h_llk_compile, @@ -687,7 +704,10 @@ HParserBackendVTable h__llk_backend_vtable = { .backend_short_name = "llk", .backend_description = "LL(k) parser backend", .get_description_with_params = h_llk_get_description, - .get_short_name_with_params = h_llk_get_short_name + .get_short_name_with_params = h_llk_get_short_name, + + /*extraction of params from string*/ + .extract_params = h_llk_extract_params }; diff --git a/src/hammer.c b/src/hammer.c index 78279bab..a67fc7f8 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -328,6 +328,70 @@ char * h_get_short_name_with_no_params(HAllocator *mm__, return h_get_backend_text_with_no_params(mm__, be, 0); } +HParserBackendWithParams * h_get_backend_with_params_by_name(const char *name_with_params) { + + HParserBackendWithParams *result = NULL; + + HAllocator *mm__ = &system_allocator; + + char *name_with_no_params = NULL; + char *params_as_string = NULL; + + size_t name_len, params_len; + size_t len = strlen(name_with_params); + + params_as_string = strstr(name_with_params, "("); + + if(params_as_string) { + params_len = strlen(params_as_string); + name_len = len - params_len; + } else { + name_len = len; + } + + name_with_no_params = h_new(char, name_len+1); + memset(name_with_no_params, 0, name_len+1); + strncpy(name_with_no_params, name_with_params, name_len); + + HParserBackend backend = h_query_backend_by_name(name_with_no_params); + + result = h_new(HParserBackendWithParams, 1); + + if (result) { + + result->backend = backend; + + result->name = name_with_no_params; + + if(params_as_string) { + //store the raw string containing the param(s) + char * raw_params_string = h_new(char, params_len+1); + memset(name_with_no_params, 0, params_len+1); + strncpy(raw_params_string, params_as_string, params_len); + result->raw_params = raw_params_string; + + //if the backend is one built as part of hammer, use it + if(backend){ + int s = backends[backend]->extract_params(&(result->params), params_as_string); + if (!s) { + /* copy_params() failed */ + h_free(result); + result = NULL; + } + } + + } else { + /* else just ignore it and set it to NULL */ + result->params = NULL; + result->raw_params = NULL; + } + + } + + return result; + +} + #define DEFAULT_ENDIANNESS (BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN) HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length) { @@ -373,6 +437,28 @@ bool h_not_regular(HRVMProg *prog, void *env) { return false; } +int h_compile_for_named_backend(HParser* parser, HParserBackendWithParams* be_with_params){ + HAllocator* mm__ = be_with_params->mm__; + + if(mm__ == NULL){ + mm__ = &system_allocator; + } + + return h_compile_for_named_backend__m(mm__, parser, be_with_params); +} + +int h_compile_for_named_backend__m(HAllocator* mm__, HParser* parser, HParserBackendWithParams* be_with_params) { + /*if (parser->backend >= PB_MIN && parser->backend <= PB_MAX && + backends[parser->backend]->free != NULL) { + backends[parser->backend]->free(parser); + } + int ret = backends[be_with_params->backend]->compile(mm__, parser, (const void*) be_with_params->params); + if (!ret) + parser->backend = be_with_params->backend; + return ret;*/ + return h_compile__m(mm__, parser, be_with_params->backend, be_with_params->params); +} + int h_compile(HParser* parser, HParserBackend backend, const void* params) { return h_compile__m(&system_allocator, parser, backend, params); } diff --git a/src/hammer.h b/src/hammer.h index ab5ea080..fc14125b 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -55,7 +55,9 @@ typedef enum HParserBackend_ { } HParserBackend; typedef struct HParserBackendWithParams_ { - /* The backend */ + /* Name of backend (for loading backends from modules */ + char *name; + /* The backend (if backend is to be loaded from an external module set to invalid (?))*/ HParserBackend backend; /* * Backend-specific parameters - if this needs to be freed, the backend @@ -64,6 +66,8 @@ typedef struct HParserBackendWithParams_ { * and PB_GLR take an integer cast to void * */ void *params; + /*raw substring the params were extracted from*/ + char *raw_params; /* Allocator to use to free this (and the params if necessary) */ HAllocator *mm__; } HParserBackendWithParams; @@ -349,6 +353,21 @@ HAMMER_FN_DECL(char *, h_get_descriptive_text_for_backend_with_params, HParserBackend h_query_backend_by_name(const char *name); +/** + * Get a Hammer Backend with params from a string of the form + * backend_name(params) for example "lalr(1)". + * + * If the backend is one of the existing backends in the HBackend enum, + * HBackend will be populated in the result. + * + * TODO: actually do the below, also improve this comment to be more clear and concise. + * Otherwise the result will save the name for use in attempts later at + * loading the named module. + * + */ + +HAMMER_FN_DECL(HParserBackendWithParams *, h_get_backend_with_params_by_name, const char *name_with_params); + /** * Top-level function to call a parser that has been built over some * piece of input (of known size). @@ -881,6 +900,8 @@ void h_pprintln(FILE* stream, const HParsedToken* tok); * * Consult each backend for details. */ +HAMMER_FN_DECL(int, h_compile_for_named_backend, HParser* parser, HParserBackendWithParams *be_with_params); + HAMMER_FN_DECL(int, h_compile, HParser* parser, HParserBackend backend, const void* params); /** diff --git a/src/internal.h b/src/internal.h index 03d6c8ad..467396eb 100644 --- a/src/internal.h +++ b/src/internal.h @@ -262,6 +262,9 @@ typedef struct HParserBackendVTable_ { char * (*get_short_name_with_params)(HAllocator *mm__, HParserBackend be, void *params); + + /* extract params from the input string */ + int (*extract_params)(void** params, char *raw_params); } HParserBackendVTable; -- GitLab