diff --git a/src/hammer.c b/src/hammer.c index c257e07278dc58e2c0d4fe3a978a17e8b8a5debf..f66b96301a186d2e8c33e6bb90e43230dd67845e 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -34,6 +34,15 @@ static guint djbhash(const uint8_t *buf, size_t len) { return hash; } +// short-hand for constructing HCachedResult's +static HCachedResult *cached_result(const HParseState *state, HParseResult *result) +{ + HCachedResult *ret = a_new(HCachedResult, 1); + ret->result = result; + ret->input_stream = state->input_stream; + return ret; +} + HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) { HParserCacheValue *cached = g_hash_table_lookup(state->cache, k); HRecursionHead *head = g_hash_table_lookup(state->recursion_heads, k); @@ -45,7 +54,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) { HParseResult *tmp = a_new(HParseResult, 1); tmp->ast = NULL; tmp->arena = state->arena; HParserCacheValue *ret = a_new(HParserCacheValue, 1); - ret->value_type = PC_RIGHT; ret->right = tmp; + ret->value_type = PC_RIGHT; ret->right = cached_result(state, tmp); return ret; } if (g_slist_find(head->eval_set, k->parser)) { @@ -58,7 +67,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) { if (!cached) cached = a_new(HParserCacheValue, 1); cached->value_type = PC_RIGHT; - cached->right = tmp_res; + cached->right = cached_result(state, tmp_res); } return cached; } @@ -93,7 +102,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) HParserCacheValue *old_cached = g_hash_table_lookup(state->cache, k); if (!old_cached || PC_LEFT == old_cached->value_type) errx(1, "impossible match"); - HParseResult *old_res = old_cached->right; + HParseResult *old_res = old_cached->right->result; // reset the eval_set of the head of the recursion at each beginning of growth head->eval_set = head->involved_set; @@ -108,7 +117,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) if ((old_res->ast->index < tmp_res->ast->index) || (old_res->ast->index == tmp_res->ast->index && old_res->ast->bit_offset < tmp_res->ast->bit_offset)) { HParserCacheValue *v = a_new(HParserCacheValue, 1); - v->value_type = PC_RIGHT; v->right = tmp_res; + v->value_type = PC_RIGHT; v->right = cached_result(state, tmp_res); g_hash_table_replace(state->cache, k, v); return grow(k, state, head); } else { @@ -116,7 +125,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head) g_hash_table_remove(state->recursion_heads, k); HParserCacheValue *cached = g_hash_table_lookup(state->cache, k); if (cached && PC_RIGHT == cached->value_type) { - return cached->right; + return cached->right->result; } else { errx(1, "impossible match"); } @@ -136,7 +145,7 @@ HParseResult* lr_answer(HParserCacheKey *k, HParseState *state, HLeftRec *growab else { // update cache HParserCacheValue *v = a_new(HParserCacheValue, 1); - v->value_type = PC_RIGHT; v->right = growable->seed; + v->value_type = PC_RIGHT; v->right = cached_result(state, growable->seed); g_hash_table_replace(state->cache, k, v); if (!growable->seed) return NULL; @@ -194,7 +203,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) { // 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) { HParserCacheValue *right = a_new(HParserCacheValue, 1); - right->value_type = PC_RIGHT; right->right = tmp_res; + right->value_type = PC_RIGHT; right->right = cached_result(state, tmp_res); g_hash_table_replace(state->cache, key, right); return tmp_res; } else { @@ -208,14 +217,8 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) { setupLR(parser, state, m->left); return m->left->seed; // BUG: this might not be correct } else { - HParseResult *res = m->right; - - // skip over the previously-parsed input - long long offs = res->bit_length + state->input_stream.bit_offset; - state->input_stream.index += offs >> 3; - state->input_stream.bit_offset = offs & 7; - - return res; + state->input_stream = m->right->input_stream; + return m->right->result; } } } diff --git a/src/internal.h b/src/internal.h index 73956328454ab58bcb61c527766184d3f358b416..cc35a8b6ce0d1f8fffe6d2b98acb1ef0b06e276c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -108,6 +108,12 @@ typedef struct HLeftRec_ { HRecursionHead *head; } HLeftRec; +/* Result and remaining input, for rerunning from a cached position. */ +typedef struct HCachedResult_ { + HParseResult *result; + HInputStream input_stream; +} HCachedResult; + /* Tagged union for values in the cache: either HLeftRec's (Left) or * HParseResult's (Right). */ @@ -115,7 +121,7 @@ typedef struct HParserCacheValue_t { HParserCacheValueType value_type; union { HLeftRec *left; - HParseResult *right; + HCachedResult *right; }; } HParserCacheValue;