From c5d9bae0b7c37443112ea13b74d7298e9c8413af Mon Sep 17 00:00:00 2001 From: Andrea Shepard <andrea@persephoneslair.org> Date: Sun, 7 May 2017 17:56:20 +0000 Subject: [PATCH] Add PB_INVALID, the missing backend, h_get_default_backend() and h_is_backend_available() --- src/SConscript | 5 +++-- src/backends/missing.c | 25 +++++++++++++++++++++++++ src/backends/missing.h | 7 +++++++ src/hammer.c | 27 +++++++++++++++++++++------ src/hammer.h | 18 +++++++++++++++++- src/internal.h | 14 ++++++++++++++ 6 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 src/backends/missing.c create mode 100644 src/backends/missing.h diff --git a/src/SConscript b/src/SConscript index 0c4f81ed..2af08ae1 100644 --- a/src/SConscript +++ b/src/SConscript @@ -21,7 +21,8 @@ parsers_headers = [ backends_headers = [ 'backends/regex.h', - 'backends/contextfree.h' + 'backends/contextfree.h', + 'backends/missing.h' ] parsers = ['parsers/%s.c'%s for s in @@ -55,7 +56,7 @@ parsers = ['parsers/%s.c'%s for s in 'value']] backends = ['backends/%s.c' % s for s in - ['packrat', 'llk', 'regex', 'glr', 'lalr', 'lr', 'lr0']] + ['missing', 'packrat', 'llk', 'regex', 'glr', 'lalr', 'lr', 'lr0']] misc_hammer_parts = [ 'allocator.c', diff --git a/src/backends/missing.c b/src/backends/missing.c new file mode 100644 index 00000000..f159bf19 --- /dev/null +++ b/src/backends/missing.c @@ -0,0 +1,25 @@ +#include "missing.h" + +/* Placeholder backend that always fails */ + +int h_missing_compile(HAllocator* mm__, HParser* parser, const void* params) { + /* Always fail */ + + return -1; +} + +HParseResult *h_missing_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream) { + /* Always fail */ + + return NULL; +} + +void h_missing_free(HParser *parser) { + /* No-op */ +} + +HParserBackendVTable h__missing_backend_vtable = { + .compile = h_missing_compile, + .parse = h_missing_parse, + .free = h_missing_free, +}; diff --git a/src/backends/missing.h b/src/backends/missing.h new file mode 100644 index 00000000..4efe5f35 --- /dev/null +++ b/src/backends/missing.h @@ -0,0 +1,7 @@ +#ifndef HAMMER_BACKENDS_MISSING__H +#define HAMMER_BACKENDS_MISSING__H + +#include "../hammer.h" +#include "../internal.h" + +#endif /* !defined(HAMMER_BACKENDS_MISSING__H) */ diff --git a/src/hammer.c b/src/hammer.c index 70ebc8a4..44ff2e66 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -26,11 +26,12 @@ #include "parsers/parser_internal.h" static HParserBackendVTable *backends[PB_MAX + 1] = { - &h__packrat_backend_vtable, - &h__regex_backend_vtable, - &h__llk_backend_vtable, - &h__lalr_backend_vtable, - &h__glr_backend_vtable, + &h__missing_backend_vtable, /* For PB_INVALID */ + &h__packrat_backend_vtable, /* For PB_PACKRAT */ + &h__regex_backend_vtable, /* For PB_REGULAR */ + &h__llk_backend_vtable, /* For PB_LLk */ + &h__lalr_backend_vtable, /* For PB_LALR */ + &h__glr_backend_vtable /* For PB_GLR */ }; @@ -41,7 +42,18 @@ typedef struct { const HParser *p2; } HTwoParsers; +/* Backend-related inquiries */ +int h_is_backend_available(HParserBackend backend) { + if (backend >= PB_MIN && backend <= PB_MAX) { + return (backends[backend] != &h__missing_backend_vtable) ? 1 : 0; + } else return 0; +} + +HParserBackend h_get_default_backend(void) { + /* Call the inline version in internal.h */ + return h_get_default_backend__int(); +} #define DEFAULT_ENDIANNESS (BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN) @@ -93,7 +105,10 @@ int h_compile(HParser* parser, HParserBackend backend, const void* params) { } int h_compile__m(HAllocator* mm__, HParser* parser, HParserBackend backend, const void* params) { - backends[parser->backend]->free(parser); + if (parser->backend >= PB_MIN && parser->backend <= PB_MAX && + backends[parser->backend]->free != NULL) { + backends[parser->backend]->free(parser); + } int ret = backends[backend]->compile(mm__, parser, params); if (!ret) parser->backend = backend; diff --git a/src/hammer.h b/src/hammer.h index ad44fee9..a9ace572 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -41,7 +41,12 @@ typedef struct HParseState_ HParseState; typedef enum HParserBackend_ { PB_MIN = 0, - PB_PACKRAT = PB_MIN, // PB_MIN is always the default. + /* + * Have a backend that always fails to pass around "no such backend" + * indications + */ + PB_INVALID = PB_MIN, + PB_PACKRAT, PB_REGULAR, PB_LLk, PB_LALR, @@ -260,6 +265,17 @@ typedef struct HBenchmarkResults_ { #endif // SWIG // }}} +/** + * Ask if this backend is available + */ + +int h_is_backend_available(HParserBackend backend); + +/** + * Ask what the default backend is (currently always PB_PACKRAT) + */ + +HParserBackend h_get_default_backend(void); /** * Top-level function to call a parser that has been built over some diff --git a/src/internal.h b/src/internal.h index 0e92e99e..51898bf0 100644 --- a/src/internal.h +++ b/src/internal.h @@ -318,6 +318,7 @@ struct HBitWriter_ { // Backends {{{ +extern HParserBackendVTable h__missing_backend_vtable; extern HParserBackendVTable h__packrat_backend_vtable; extern HParserBackendVTable h__llk_backend_vtable; extern HParserBackendVTable h__lalr_backend_vtable; @@ -334,12 +335,25 @@ static inline size_t h_input_stream_pos(HInputStream* state) { HParseResult* h_do_parse(const HParser* parser, HParseState *state); void put_cached(HParseState *ps, const HParser *p, HParseResult *cached); +/* + * Inline this for benefit of h_new_parser() below, then make + * the API h_get_default_backend() call it. + */ +static inline HParserBackend h_get_default_backend__int(void) { + return PB_PACKRAT; +} + static inline HParser *h_new_parser(HAllocator *mm__, const HParserVtable *vt, void *env) { HParser *p = h_new(HParser, 1); memset(p, 0, sizeof(HParser)); p->vtable = vt; p->env = env; + /* + * Current limitation: if we specify backends solely by HParserBackend, we + * can't set a default backend that requires any parameters to h_compile() + */ + p->backend = h_get_default_backend__int(); return p; } -- GitLab