From 969d7682053bb73cc78503556d63dd10039eb59f Mon Sep 17 00:00:00 2001 From: "Meredith L. Patterson" <mlp@thesmartpolitenerd.com> Date: Sat, 3 Oct 2015 17:54:11 +0200 Subject: [PATCH] Don't cache dummy results for primitive parsers. --- src/backends/packrat.c | 30 +++++++++++++++++------------- src/internal.h | 7 ++++--- src/parsers/action.c | 1 + src/parsers/and.c | 1 + src/parsers/attr_bool.c | 1 + src/parsers/bind.c | 1 + src/parsers/bits.c | 1 + src/parsers/butnot.c | 1 + src/parsers/ch.c | 1 + src/parsers/charset.c | 1 + src/parsers/choice.c | 1 + src/parsers/difference.c | 1 + src/parsers/end.c | 1 + src/parsers/endianness.c | 1 + src/parsers/epsilon.c | 1 + src/parsers/ignore.c | 1 + src/parsers/ignoreseq.c | 1 + src/parsers/indirect.c | 1 + src/parsers/int_range.c | 1 + src/parsers/many.c | 1 + src/parsers/not.c | 1 + src/parsers/nothing.c | 1 + src/parsers/optional.c | 1 + src/parsers/permutation.c | 1 + src/parsers/sequence.c | 1 + src/parsers/token.c | 1 + src/parsers/unimplemented.c | 1 + src/parsers/value.c | 2 ++ src/parsers/whitespace.c | 1 + src/parsers/xor.c | 1 + 30 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/backends/packrat.c b/src/backends/packrat.c index e6f86f29..9977cc3c 100644 --- a/src/backends/packrat.c +++ b/src/backends/packrat.c @@ -3,7 +3,7 @@ #include "../internal.h" #include "../parsers/parser_internal.h" -// short-hand for creating cache values (regular case) +// short-hand for creating lowlevel parse cache values (parse result case) static HParserCacheValue * cached_result(HParseState *state, HParseResult *result) { HParserCacheValue *ret = a_new(HParserCacheValue, 1); @@ -13,7 +13,7 @@ HParserCacheValue * cached_result(HParseState *state, HParseResult *result) { return ret; } -// short-hand for caching parse results (left recursion case) +// short-hand for creating lowlevel parse cache values (left recursion case) static HParserCacheValue *cached_lr(HParseState *state, HLeftRec *lr) { HParserCacheValue *ret = a_new(HParserCacheValue, 1); @@ -186,18 +186,22 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) { if (!m) { // It doesn't exist, so create a dummy result to cache HLeftRec *base = a_new(HLeftRec, 1); - base->seed = NULL; base->rule = parser; base->head = NULL; - h_slist_push(state->lr_stack, base); - // cache it - h_hashtable_put(state->cache, key, cached_lr(state, base)); - // parse the input + if (parser->vtable->higher) { + base->seed = NULL; base->rule = parser; base->head = NULL; + h_slist_push(state->lr_stack, base); + // cache it + h_hashtable_put(state->cache, key, cached_lr(state, base)); + // parse the input + } HParseResult *tmp_res = perform_lowlevel_parse(state, parser); - // the base variable has passed equality tests with the cache - h_slist_pop(state->lr_stack); - // update the cached value to our new position - HParserCacheValue *cached = h_hashtable_get(state->cache, key); - assert(cached != NULL); - cached->input_stream = state->input_stream; + if (parser->vtable->higher) { + // the base variable has passed equality tests with the cache + h_slist_pop(state->lr_stack); + // update the cached value to our new position + HParserCacheValue *cached = h_hashtable_get(state->cache, key); + assert(cached != NULL); + cached->input_stream = state->input_stream; + } // setupLR, used below, mutates the LR to have a head if appropriate, so we check to see if we have one if (NULL == base->head) { h_hashtable_put(state->cache, key, cached_result(state, tmp_res)); diff --git a/src/internal.h b/src/internal.h index b35b7d5a..776f6368 100644 --- a/src/internal.h +++ b/src/internal.h @@ -278,9 +278,9 @@ typedef struct HRecursionHead_ { /* A left recursion. * * Members: - * seed - - * rule - - * head - + * seed - the HResult yielded by rule + * rule - the HParser that produces seed + * head - the */ typedef struct HLeftRec_ { HParseResult *seed; @@ -419,6 +419,7 @@ struct HParserVtable_ { bool (*isValidCF)(void *env); bool (*compile_to_rvm)(HRVMProg *prog, void* env); // FIXME: forgot what the bool return value was supposed to mean. void (*desugar)(HAllocator *mm__, HCFStack *stk__, void *env); + bool higher; // false if primitive }; bool h_false(void*); diff --git a/src/parsers/action.c b/src/parsers/action.c index 04eb7a4c..a3243334 100644 --- a/src/parsers/action.c +++ b/src/parsers/action.c @@ -81,6 +81,7 @@ static const HParserVtable action_vt = { .isValidCF = action_isValidCF, .desugar = desugar_action, .compile_to_rvm = action_ctrvm, + .higher = true, }; HParser* h_action(const HParser* p, const HAction a, void* user_data) { diff --git a/src/parsers/and.c b/src/parsers/and.c index c5c9836d..e07bc9fc 100644 --- a/src/parsers/and.c +++ b/src/parsers/and.c @@ -17,6 +17,7 @@ static const HParserVtable and_vt = { revision. --mlp, 18/12/12 */ .isValidCF = h_false, /* despite TODO above, this remains false. */ .compile_to_rvm = h_not_regular, + .higher = true, }; diff --git a/src/parsers/attr_bool.c b/src/parsers/attr_bool.c index e8359ab0..f7667740 100644 --- a/src/parsers/attr_bool.c +++ b/src/parsers/attr_bool.c @@ -79,6 +79,7 @@ static const HParserVtable attr_bool_vt = { .isValidCF = ab_isValidCF, .desugar = desugar_ab, .compile_to_rvm = ab_ctrvm, + .higher = true, }; diff --git a/src/parsers/bind.c b/src/parsers/bind.c index f024a82f..7fa821dc 100644 --- a/src/parsers/bind.c +++ b/src/parsers/bind.c @@ -60,6 +60,7 @@ static const HParserVtable bind_vt = { .isValidRegular = h_false, .isValidCF = h_false, .compile_to_rvm = h_not_regular, + .higher = true, }; HParser *h_bind(const HParser *p, HContinuation k, void *env) diff --git a/src/parsers/bits.c b/src/parsers/bits.c index 716524ce..be8f13f1 100644 --- a/src/parsers/bits.c +++ b/src/parsers/bits.c @@ -102,6 +102,7 @@ static const HParserVtable bits_vt = { .isValidCF = h_true, .desugar = desugar_bits, .compile_to_rvm = bits_ctrvm, + .higher = false, }; HParser* h_bits(size_t len, bool sign) { diff --git a/src/parsers/butnot.c b/src/parsers/butnot.c index f114a1fa..24ece4be 100644 --- a/src/parsers/butnot.c +++ b/src/parsers/butnot.c @@ -40,6 +40,7 @@ static const HParserVtable butnot_vt = { .isValidRegular = h_false, .isValidCF = h_false, // XXX should this be true if both p1 and p2 are CF? .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_butnot(const HParser* p1, const HParser* p2) { diff --git a/src/parsers/ch.c b/src/parsers/ch.c index b4386cff..3da1091a 100644 --- a/src/parsers/ch.c +++ b/src/parsers/ch.c @@ -47,6 +47,7 @@ static const HParserVtable ch_vt = { .isValidCF = h_true, .desugar = desugar_ch, .compile_to_rvm = ch_ctrvm, + .higher = false, }; HParser* h_ch(const uint8_t c) { diff --git a/src/parsers/charset.c b/src/parsers/charset.c index e1a910f8..a4b8c89c 100644 --- a/src/parsers/charset.c +++ b/src/parsers/charset.c @@ -76,6 +76,7 @@ static const HParserVtable charset_vt = { .isValidCF = h_true, .desugar = desugar_charset, .compile_to_rvm = cs_ctrvm, + .higher = false, }; HParser* h_ch_range(const uint8_t lower, const uint8_t upper) { diff --git a/src/parsers/choice.c b/src/parsers/choice.c index bfc3f904..dd3908ce 100644 --- a/src/parsers/choice.c +++ b/src/parsers/choice.c @@ -75,6 +75,7 @@ static const HParserVtable choice_vt = { .isValidCF = choice_isValidCF, .desugar = desugar_choice, .compile_to_rvm = choice_ctrvm, + .higher = true, }; HParser* h_choice(HParser* p, ...) { diff --git a/src/parsers/difference.c b/src/parsers/difference.c index 76a2cc44..a24f5acf 100644 --- a/src/parsers/difference.c +++ b/src/parsers/difference.c @@ -39,6 +39,7 @@ static HParserVtable difference_vt = { .isValidRegular = h_false, .isValidCF = h_false, // XXX should this be true if both p1 and p2 are CF? .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_difference(const HParser* p1, const HParser* p2) { diff --git a/src/parsers/end.c b/src/parsers/end.c index 30b3ba12..85499d93 100644 --- a/src/parsers/end.c +++ b/src/parsers/end.c @@ -25,6 +25,7 @@ static const HParserVtable end_vt = { .isValidCF = h_true, .desugar = desugar_end, .compile_to_rvm = end_ctrvm, + .higher = false, }; HParser* h_end_p() { diff --git a/src/parsers/endianness.c b/src/parsers/endianness.c index e3f53ab8..cb3abc3d 100644 --- a/src/parsers/endianness.c +++ b/src/parsers/endianness.c @@ -46,6 +46,7 @@ static const HParserVtable endianness_vt = { .isValidCF = h_false, .desugar = NULL, .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_with_endianness(char endianness, const HParser *p) diff --git a/src/parsers/epsilon.c b/src/parsers/epsilon.c index e8ef525f..bb6e8beb 100644 --- a/src/parsers/epsilon.c +++ b/src/parsers/epsilon.c @@ -18,6 +18,7 @@ static const HParserVtable epsilon_vt = { .isValidCF = h_true, .desugar = desugar_epsilon, .compile_to_rvm = epsilon_ctrvm, + .higher = false, }; HParser* h_epsilon_p() { diff --git a/src/parsers/ignore.c b/src/parsers/ignore.c index af606b0e..c56802ac 100644 --- a/src/parsers/ignore.c +++ b/src/parsers/ignore.c @@ -49,6 +49,7 @@ static const HParserVtable ignore_vt = { .isValidCF = ignore_isValidCF, .desugar = desugar_ignore, .compile_to_rvm = ignore_ctrvm, + .higher = true, }; HParser* h_ignore(const HParser* p) { diff --git a/src/parsers/ignoreseq.c b/src/parsers/ignoreseq.c index e562136f..07bdc65c 100644 --- a/src/parsers/ignoreseq.c +++ b/src/parsers/ignoreseq.c @@ -103,6 +103,7 @@ static const HParserVtable ignoreseq_vt = { .isValidCF = is_isValidCF, .desugar = desugar_ignoreseq, .compile_to_rvm = is_ctrvm, + .higher = true, }; diff --git a/src/parsers/indirect.c b/src/parsers/indirect.c index 026286d3..b36cb947 100644 --- a/src/parsers/indirect.c +++ b/src/parsers/indirect.c @@ -31,6 +31,7 @@ static const HParserVtable indirect_vt = { .isValidCF = indirect_isValidCF, .desugar = desugar_indirect, .compile_to_rvm = h_not_regular, + .higher = true, }; void h_bind_indirect__m(HAllocator *mm__, HParser* indirect, const HParser* inner) { diff --git a/src/parsers/int_range.c b/src/parsers/int_range.c index 29379930..49b06421 100644 --- a/src/parsers/int_range.c +++ b/src/parsers/int_range.c @@ -117,6 +117,7 @@ static const HParserVtable int_range_vt = { .isValidCF = h_true, .desugar = desugar_int_range, .compile_to_rvm = ir_ctrvm, + .higher = false, }; HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t upper) { diff --git a/src/parsers/many.c b/src/parsers/many.c index cae2b0ea..6496bbe6 100644 --- a/src/parsers/many.c +++ b/src/parsers/many.c @@ -199,6 +199,7 @@ static const HParserVtable many_vt = { .isValidCF = many_isValidCF, .desugar = desugar_many, .compile_to_rvm = many_ctrvm, + .higher = true, }; HParser* h_many(const HParser* p) { diff --git a/src/parsers/not.c b/src/parsers/not.c index 6c34bad4..8c2003de 100644 --- a/src/parsers/not.c +++ b/src/parsers/not.c @@ -15,6 +15,7 @@ static const HParserVtable not_vt = { .isValidRegular = h_false, /* see and.c for why */ .isValidCF = h_false, .compile_to_rvm = h_not_regular, // Is actually regular, but the generation step is currently unable to handle it. TODO: fix this. + .higher = true, }; HParser* h_not(const HParser* p) { diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index 120c1e01..0a60108b 100644 --- a/src/parsers/nothing.c +++ b/src/parsers/nothing.c @@ -22,6 +22,7 @@ static const HParserVtable nothing_vt = { .isValidCF = h_true, .desugar = desugar_nothing, .compile_to_rvm = nothing_ctrvm, + .higher = false, }; HParser* h_nothing_p() { diff --git a/src/parsers/optional.c b/src/parsers/optional.c index ccee53fa..72660664 100644 --- a/src/parsers/optional.c +++ b/src/parsers/optional.c @@ -84,6 +84,7 @@ static const HParserVtable optional_vt = { .isValidCF = opt_isValidCF, .desugar = desugar_optional, .compile_to_rvm = opt_ctrvm, + .higher = true, }; HParser* h_optional(const HParser* p) { diff --git a/src/parsers/permutation.c b/src/parsers/permutation.c index 564565af..b1675841 100644 --- a/src/parsers/permutation.c +++ b/src/parsers/permutation.c @@ -104,6 +104,7 @@ static const HParserVtable permutation_vt = { .isValidCF = h_false, .desugar = NULL, .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_permutation(HParser* p, ...) { diff --git a/src/parsers/sequence.c b/src/parsers/sequence.c index 93c0cfb9..30de34a4 100644 --- a/src/parsers/sequence.c +++ b/src/parsers/sequence.c @@ -93,6 +93,7 @@ static const HParserVtable sequence_vt = { .isValidCF = sequence_isValidCF, .desugar = desugar_sequence, .compile_to_rvm = sequence_ctrvm, + .higher = true, }; HParser* h_sequence(HParser* p, ...) { diff --git a/src/parsers/token.c b/src/parsers/token.c index d36ec54b..19029726 100644 --- a/src/parsers/token.c +++ b/src/parsers/token.c @@ -73,6 +73,7 @@ const HParserVtable token_vt = { .isValidCF = h_true, .desugar = desugar_token, .compile_to_rvm = token_ctrvm, + .higher = false, }; HParser* h_token(const uint8_t *str, const size_t len) { diff --git a/src/parsers/unimplemented.c b/src/parsers/unimplemented.c index e3f30394..e085858b 100644 --- a/src/parsers/unimplemented.c +++ b/src/parsers/unimplemented.c @@ -18,6 +18,7 @@ static const HParserVtable unimplemented_vt = { .isValidCF = h_false, .desugar = NULL, .compile_to_rvm = h_not_regular, + .higher = true, }; static HParser unimplemented = { diff --git a/src/parsers/value.c b/src/parsers/value.c index 531db7cb..7fa863a1 100644 --- a/src/parsers/value.c +++ b/src/parsers/value.c @@ -26,6 +26,7 @@ static const HParserVtable put_vt = { .isValidRegular = h_false, .isValidCF = h_false, .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_put_value(const HParser* p, const char* name) { @@ -55,6 +56,7 @@ static const HParserVtable get_vt = { .isValidRegular = h_false, .isValidCF = h_false, .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_get_value(const char* name) { diff --git a/src/parsers/whitespace.c b/src/parsers/whitespace.c index 04284e86..970a32c8 100644 --- a/src/parsers/whitespace.c +++ b/src/parsers/whitespace.c @@ -75,6 +75,7 @@ static const HParserVtable whitespace_vt = { .isValidCF = ws_isValidCF, .desugar = desugar_whitespace, .compile_to_rvm = ws_ctrvm, + .higher = false, }; HParser* h_whitespace(const HParser* p) { diff --git a/src/parsers/xor.c b/src/parsers/xor.c index e031d5d5..3a3f21d2 100644 --- a/src/parsers/xor.c +++ b/src/parsers/xor.c @@ -36,6 +36,7 @@ static const HParserVtable xor_vt = { .isValidRegular = h_false, .isValidCF = h_false, // XXX should this be true if both p1 and p2 are CF? .compile_to_rvm = h_not_regular, + .higher = true, }; HParser* h_xor(const HParser* p1, const HParser* p2) { -- GitLab