Merge remote-tracking branch 'bunter/master'
Conflicts: src/hammer.c
This commit is contained in:
commit
92df2d081b
3 changed files with 69 additions and 25 deletions
67
src/hammer.c
67
src/hammer.c
|
|
@ -35,6 +35,18 @@ guint djbhash(const uint8_t *buf, size_t len) {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupLR(const parser_t *p, GQueue *stack, LR_t *recDetect) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_result_t* lr_answer(const parser_t *p, parse_state_t *state, LR_t *growable) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_result_t* grow(const parser_t *p, parse_state_t *state, head_t *head) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) {
|
parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) {
|
||||||
// TODO(thequux): add caching here.
|
// TODO(thequux): add caching here.
|
||||||
parser_cache_key_t *key = a_new(parser_cache_key_t, 1);
|
parser_cache_key_t *key = a_new(parser_cache_key_t, 1);
|
||||||
|
|
@ -42,31 +54,53 @@ parse_result_t* do_parse(const parser_t* parser, parse_state_t *state) {
|
||||||
key->parser = parser;
|
key->parser = parser;
|
||||||
|
|
||||||
// check to see if there is already a result for this object...
|
// check to see if there is already a result for this object...
|
||||||
if (g_hash_table_contains(state->cache, &key)) {
|
if (!g_hash_table_contains(state->cache, key)) {
|
||||||
// it exists!
|
// It doesn't exist, so create a dummy result to cache
|
||||||
// TODO(thequux): handle left recursion case
|
LR_t *base = a_new(LR_t, 1);
|
||||||
return g_hash_table_lookup(state->cache, &key);
|
base->seed = NULL; base->rule = parser; base->head = NULL;
|
||||||
} else {
|
g_queue_push_head(state->input_stream.lr_stack, base);
|
||||||
// It doesn't exist... run the
|
// cache it
|
||||||
parse_result_t *res;
|
parser_cache_value_t *dummy = a_new(parser_cache_value_t, 1);
|
||||||
|
dummy->value_type = PC_LEFT; dummy->left = base;
|
||||||
|
g_hash_table_replace(state->cache, key, dummy);
|
||||||
|
// parse the input
|
||||||
|
parse_result_t *tmp_res;
|
||||||
if (parser) {
|
if (parser) {
|
||||||
res = parser->fn(parser->env, state);
|
tmp_res = parser->fn(parser->env, state);
|
||||||
if (res)
|
tmp_res->arena = state->arena;
|
||||||
res->arena = state->arena;
|
|
||||||
} else
|
} else
|
||||||
res = NULL;
|
tmp_res = NULL;
|
||||||
if (state->input_stream.overrun)
|
if (state->input_stream.overrun)
|
||||||
res = NULL; // overrun is always failure.
|
return NULL; // overrun is always failure.
|
||||||
// update the cache
|
|
||||||
g_hash_table_replace(state->cache, &key, res);
|
|
||||||
#ifdef CONSISTENCY_CHECK
|
#ifdef CONSISTENCY_CHECK
|
||||||
if (!res) {
|
if (!tmp_res) {
|
||||||
state->input_stream = INVALID;
|
state->input_stream = INVALID;
|
||||||
state->input_stream.input = key.input_pos.input;
|
state->input_stream.input = key->input_pos.input;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// the base variable has passed equality tests with the cache
|
||||||
|
g_queue_pop_head(state->input_stream.lr_stack);
|
||||||
|
// 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) {
|
||||||
|
parser_cache_value_t *right = a_new(parser_cache_value_t, 1);
|
||||||
|
right->value_type = PC_RIGHT; right->right = tmp_res;
|
||||||
|
g_hash_table_replace(state->cache, key, right);
|
||||||
|
return tmp_res;
|
||||||
|
} else {
|
||||||
|
base->seed = tmp_res;
|
||||||
|
parse_result_t *res = lr_answer(parser, state, base);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// it exists!
|
||||||
|
parser_cache_value_t *value = g_hash_table_lookup(state->cache, key);
|
||||||
|
if (PC_LEFT == value->value_type) {
|
||||||
|
setupLR(parser, state->input_stream.lr_stack, value->left);
|
||||||
|
return value->left->seed; // BUG: this might not be correct
|
||||||
|
} else {
|
||||||
|
return value->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function, since these lines appear in every parser */
|
/* Helper function, since these lines appear in every parser */
|
||||||
|
|
@ -651,6 +685,7 @@ parse_result_t* parse(const parser_t* parser, const uint8_t* input, size_t lengt
|
||||||
parse_state->input_stream.overrun = 0;
|
parse_state->input_stream.overrun = 0;
|
||||||
parse_state->input_stream.endianness = BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN;
|
parse_state->input_stream.endianness = BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN;
|
||||||
parse_state->input_stream.length = length;
|
parse_state->input_stream.length = length;
|
||||||
|
g_queue_init(parse_state->input_stream.lr_stack);
|
||||||
parse_state->arena = arena;
|
parse_state->arena = arena;
|
||||||
parse_result_t *res = do_parse(parser, parse_state);
|
parse_result_t *res = do_parse(parser, parse_state);
|
||||||
// tear down the parse state. For now, leak like a sieve.
|
// tear down the parse state. For now, leak like a sieve.
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ typedef struct input_stream {
|
||||||
char bit_offset;
|
char bit_offset;
|
||||||
char endianness;
|
char endianness;
|
||||||
char overrun;
|
char overrun;
|
||||||
|
GQueue *lr_stack;
|
||||||
} input_stream_t;
|
} input_stream_t;
|
||||||
|
|
||||||
typedef struct parse_state {
|
typedef struct parse_state {
|
||||||
|
|
|
||||||
|
|
@ -38,19 +38,27 @@ typedef struct parser_cache_key {
|
||||||
} parser_cache_key_t;
|
} parser_cache_key_t;
|
||||||
|
|
||||||
typedef enum parser_cache_value_type {
|
typedef enum parser_cache_value_type {
|
||||||
PC_BASE,
|
PC_LEFT,
|
||||||
PC_IN_RECURSION,
|
PC_RIGHT
|
||||||
PC_LRESULT,
|
|
||||||
PC_RESULT
|
|
||||||
} parser_cache_value_type_t;
|
} parser_cache_value_type_t;
|
||||||
|
|
||||||
|
typedef struct head {
|
||||||
|
parser_t *head_parser;
|
||||||
|
GSList *involved_set;
|
||||||
|
GSList *eval_set;
|
||||||
|
} head_t;
|
||||||
|
|
||||||
|
typedef struct LR {
|
||||||
|
parse_result_t *seed;
|
||||||
|
const parser_t *rule;
|
||||||
|
head_t *head;
|
||||||
|
} LR_t;
|
||||||
|
|
||||||
typedef struct parser_cache_value {
|
typedef struct parser_cache_value {
|
||||||
parser_cache_value_type_t value_type;
|
parser_cache_value_type_t value_type;
|
||||||
union {
|
union {
|
||||||
int base;
|
LR_t *left;
|
||||||
parse_result_t *in_recursion;
|
parse_result_t *right;
|
||||||
parse_result_t *lresult;
|
|
||||||
parse_result_t *result;
|
|
||||||
};
|
};
|
||||||
} parser_cache_value_t;
|
} parser_cache_value_t;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue