save input stream with cached results
This commit is contained in:
parent
5668b46f97
commit
80ad3476e2
2 changed files with 25 additions and 16 deletions
33
src/hammer.c
33
src/hammer.c
|
|
@ -34,6 +34,15 @@ static guint djbhash(const uint8_t *buf, size_t len) {
|
||||||
return hash;
|
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* recall(HParserCacheKey *k, HParseState *state) {
|
||||||
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
|
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
|
||||||
HRecursionHead *head = g_hash_table_lookup(state->recursion_heads, 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);
|
HParseResult *tmp = a_new(HParseResult, 1);
|
||||||
tmp->ast = NULL; tmp->arena = state->arena;
|
tmp->ast = NULL; tmp->arena = state->arena;
|
||||||
HParserCacheValue *ret = a_new(HParserCacheValue, 1);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
if (g_slist_find(head->eval_set, k->parser)) {
|
if (g_slist_find(head->eval_set, k->parser)) {
|
||||||
|
|
@ -58,7 +67,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
|
||||||
if (!cached)
|
if (!cached)
|
||||||
cached = a_new(HParserCacheValue, 1);
|
cached = a_new(HParserCacheValue, 1);
|
||||||
cached->value_type = PC_RIGHT;
|
cached->value_type = PC_RIGHT;
|
||||||
cached->right = tmp_res;
|
cached->right = cached_result(state, tmp_res);
|
||||||
}
|
}
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +102,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
|
||||||
HParserCacheValue *old_cached = g_hash_table_lookup(state->cache, k);
|
HParserCacheValue *old_cached = g_hash_table_lookup(state->cache, k);
|
||||||
if (!old_cached || PC_LEFT == old_cached->value_type)
|
if (!old_cached || PC_LEFT == old_cached->value_type)
|
||||||
errx(1, "impossible match");
|
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
|
// reset the eval_set of the head of the recursion at each beginning of growth
|
||||||
head->eval_set = head->involved_set;
|
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) ||
|
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)) {
|
(old_res->ast->index == tmp_res->ast->index && old_res->ast->bit_offset < tmp_res->ast->bit_offset)) {
|
||||||
HParserCacheValue *v = a_new(HParserCacheValue, 1);
|
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);
|
g_hash_table_replace(state->cache, k, v);
|
||||||
return grow(k, state, head);
|
return grow(k, state, head);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -116,7 +125,7 @@ HParseResult* grow(HParserCacheKey *k, HParseState *state, HRecursionHead *head)
|
||||||
g_hash_table_remove(state->recursion_heads, k);
|
g_hash_table_remove(state->recursion_heads, k);
|
||||||
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
|
HParserCacheValue *cached = g_hash_table_lookup(state->cache, k);
|
||||||
if (cached && PC_RIGHT == cached->value_type) {
|
if (cached && PC_RIGHT == cached->value_type) {
|
||||||
return cached->right;
|
return cached->right->result;
|
||||||
} else {
|
} else {
|
||||||
errx(1, "impossible match");
|
errx(1, "impossible match");
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +145,7 @@ HParseResult* lr_answer(HParserCacheKey *k, HParseState *state, HLeftRec *growab
|
||||||
else {
|
else {
|
||||||
// update cache
|
// update cache
|
||||||
HParserCacheValue *v = a_new(HParserCacheValue, 1);
|
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);
|
g_hash_table_replace(state->cache, k, v);
|
||||||
if (!growable->seed)
|
if (!growable->seed)
|
||||||
return NULL;
|
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
|
// 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) {
|
if (NULL == base->head) {
|
||||||
HParserCacheValue *right = a_new(HParserCacheValue, 1);
|
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);
|
g_hash_table_replace(state->cache, key, right);
|
||||||
return tmp_res;
|
return tmp_res;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -208,14 +217,8 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
|
||||||
setupLR(parser, state, m->left);
|
setupLR(parser, state, m->left);
|
||||||
return m->left->seed; // BUG: this might not be correct
|
return m->left->seed; // BUG: this might not be correct
|
||||||
} else {
|
} else {
|
||||||
HParseResult *res = m->right;
|
state->input_stream = m->right->input_stream;
|
||||||
|
return m->right->result;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,12 @@ typedef struct HLeftRec_ {
|
||||||
HRecursionHead *head;
|
HRecursionHead *head;
|
||||||
} HLeftRec;
|
} 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
|
/* Tagged union for values in the cache: either HLeftRec's (Left) or
|
||||||
* HParseResult's (Right).
|
* HParseResult's (Right).
|
||||||
*/
|
*/
|
||||||
|
|
@ -115,7 +121,7 @@ typedef struct HParserCacheValue_t {
|
||||||
HParserCacheValueType value_type;
|
HParserCacheValueType value_type;
|
||||||
union {
|
union {
|
||||||
HLeftRec *left;
|
HLeftRec *left;
|
||||||
HParseResult *right;
|
HCachedResult *right;
|
||||||
};
|
};
|
||||||
} HParserCacheValue;
|
} HParserCacheValue;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue