Replaced GQueue and GSlist with HSlist.
This commit is contained in:
parent
b6bf0ea30c
commit
ef6af551d1
3 changed files with 61 additions and 25 deletions
|
|
@ -15,6 +15,7 @@ HCountedArray *h_carray_new_sized(HArena * arena, size_t size) {
|
||||||
ret->elements = h_arena_malloc(arena, sizeof(void*) * size);
|
ret->elements = h_arena_malloc(arena, sizeof(void*) * size);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
HCountedArray *h_carray_new(HArena * arena) {
|
HCountedArray *h_carray_new(HArena * arena) {
|
||||||
return h_carray_new_sized(arena, 4);
|
return h_carray_new_sized(arena, 4);
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +33,6 @@ void h_carray_append(HCountedArray *array, void* item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HSlist
|
// HSlist
|
||||||
|
|
||||||
HSlist* h_slist_new(HArena *arena) {
|
HSlist* h_slist_new(HArena *arena) {
|
||||||
HSlist *ret = h_arena_malloc(arena, sizeof(HSlist));
|
HSlist *ret = h_arena_malloc(arena, sizeof(HSlist));
|
||||||
ret->head = NULL;
|
ret->head = NULL;
|
||||||
|
|
@ -58,8 +58,42 @@ void h_slist_push(HSlist *slist, void* item) {
|
||||||
slist->head = hnode;
|
slist->head = hnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool h_slist_find(HSlist *slist, const void* item) {
|
||||||
|
assert (item != NULL);
|
||||||
|
HSlistNode *head = slist->head;
|
||||||
|
while (head != NULL) {
|
||||||
|
if (head->elem == item)
|
||||||
|
return true;
|
||||||
|
head = head->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HSlist* h_slist_remove_all(HSlist *slist, const void* item) {
|
||||||
|
assert (item != NULL);
|
||||||
|
HSlistNode *node = slist->head;
|
||||||
|
HSlistNode *prev = NULL;
|
||||||
|
while (node != NULL) {
|
||||||
|
if (node->elem == item) {
|
||||||
|
HSlistNode *next = node->next;
|
||||||
|
if (prev)
|
||||||
|
prev->next = next;
|
||||||
|
else
|
||||||
|
slist->head = next;
|
||||||
|
// FIXME free the removed node! this leaks.
|
||||||
|
node = next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev = node;
|
||||||
|
node = prev->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slist;
|
||||||
|
}
|
||||||
|
|
||||||
void h_slist_free(HSlist *slist) {
|
void h_slist_free(HSlist *slist) {
|
||||||
while (slist->head != NULL)
|
while (slist->head != NULL)
|
||||||
h_slist_pop(slist);
|
h_slist_pop(slist);
|
||||||
h_arena_free(slist->arena, slist);
|
h_arena_free(slist->arena, slist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
20
src/hammer.c
20
src/hammer.c
|
|
@ -79,7 +79,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
|
||||||
if (!head) { // No heads found
|
if (!head) { // No heads found
|
||||||
return cached;
|
return cached;
|
||||||
} else { // Some heads found
|
} else { // Some heads found
|
||||||
if (!cached && head->head_parser != k->parser && !g_slist_find(head->involved_set, k->parser)) {
|
if (!cached && head->head_parser != k->parser && !h_slist_find(head->involved_set, k->parser)) {
|
||||||
// Nothing in the cache, and the key parser is not involved
|
// Nothing in the cache, and the key parser is not involved
|
||||||
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;
|
||||||
|
|
@ -87,9 +87,9 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
|
||||||
ret->value_type = PC_RIGHT; ret->right = cached_result(state, 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 (h_slist_find(head->eval_set, k->parser)) {
|
||||||
// Something is in the cache, and the key parser is in the eval set. Remove the key parser from the eval set of the head.
|
// Something is in the cache, and the key parser is in the eval set. Remove the key parser from the eval set of the head.
|
||||||
head->eval_set = g_slist_remove_all(head->eval_set, k->parser);
|
head->eval_set = h_slist_remove_all(head->eval_set, k->parser);
|
||||||
HParseResult *tmp_res = perform_lowlevel_parse(state, k->parser);
|
HParseResult *tmp_res = perform_lowlevel_parse(state, k->parser);
|
||||||
// we know that cached has an entry here, modify it
|
// we know that cached has an entry here, modify it
|
||||||
if (!cached)
|
if (!cached)
|
||||||
|
|
@ -112,11 +112,11 @@ void setupLR(const HParser *p, HParseState *state, HLeftRec *rec_detect) {
|
||||||
some->head_parser = p; some->involved_set = NULL; some->eval_set = NULL;
|
some->head_parser = p; some->involved_set = NULL; some->eval_set = NULL;
|
||||||
rec_detect->head = some;
|
rec_detect->head = some;
|
||||||
}
|
}
|
||||||
size_t i = 0;
|
assert(state->lr_stack->head != NULL);
|
||||||
HLeftRec *lr = g_queue_peek_nth(state->lr_stack, i);
|
HLeftRec *lr = state->lr_stack->head->elem;
|
||||||
while (lr && lr->rule != p) {
|
while (lr && lr->rule != p) {
|
||||||
lr->head = rec_detect->head;
|
lr->head = rec_detect->head;
|
||||||
lr->head->involved_set = g_slist_prepend(lr->head->involved_set, (gpointer)lr->rule);
|
h_slist_push(lr->head->involved_set, (gpointer)lr->rule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
|
||||||
// It doesn't exist, so create a dummy result to cache
|
// It doesn't exist, so create a dummy result to cache
|
||||||
HLeftRec *base = a_new(HLeftRec, 1);
|
HLeftRec *base = a_new(HLeftRec, 1);
|
||||||
base->seed = NULL; base->rule = parser; base->head = NULL;
|
base->seed = NULL; base->rule = parser; base->head = NULL;
|
||||||
g_queue_push_head(state->lr_stack, base);
|
h_slist_push(state->lr_stack, base);
|
||||||
// cache it
|
// cache it
|
||||||
HParserCacheValue *dummy = a_new(HParserCacheValue, 1);
|
HParserCacheValue *dummy = a_new(HParserCacheValue, 1);
|
||||||
dummy->value_type = PC_LEFT; dummy->left = base;
|
dummy->value_type = PC_LEFT; dummy->left = base;
|
||||||
|
|
@ -198,7 +198,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
|
||||||
// parse the input
|
// parse the input
|
||||||
HParseResult *tmp_res = perform_lowlevel_parse(state, parser);
|
HParseResult *tmp_res = perform_lowlevel_parse(state, parser);
|
||||||
// the base variable has passed equality tests with the cache
|
// the base variable has passed equality tests with the cache
|
||||||
g_queue_pop_head(state->lr_stack);
|
h_slist_pop(state->lr_stack);
|
||||||
// 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);
|
||||||
|
|
@ -250,12 +250,12 @@ HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length
|
||||||
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;
|
||||||
parse_state->lr_stack = g_queue_new();
|
parse_state->lr_stack = h_slist_new(arena);
|
||||||
parse_state->recursion_heads = g_hash_table_new(cache_key_hash,
|
parse_state->recursion_heads = g_hash_table_new(cache_key_hash,
|
||||||
cache_key_equal);
|
cache_key_equal);
|
||||||
parse_state->arena = arena;
|
parse_state->arena = arena;
|
||||||
HParseResult *res = h_do_parse(parser, parse_state);
|
HParseResult *res = h_do_parse(parser, parse_state);
|
||||||
g_queue_free(parse_state->lr_stack);
|
h_slist_free(parse_state->lr_stack);
|
||||||
g_hash_table_destroy(parse_state->recursion_heads);
|
g_hash_table_destroy(parse_state->recursion_heads);
|
||||||
// tear down the parse state
|
// tear down the parse state
|
||||||
g_hash_table_destroy(parse_state->cache);
|
g_hash_table_destroy(parse_state->cache);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,17 @@ typedef struct HInputStream_ {
|
||||||
char overrun;
|
char overrun;
|
||||||
} HInputStream;
|
} HInputStream;
|
||||||
|
|
||||||
|
typedef struct HSlistNode_ {
|
||||||
|
void* elem;
|
||||||
|
struct HSlistNode_ *next;
|
||||||
|
} HSlistNode;
|
||||||
|
|
||||||
|
typedef struct HSlist_ {
|
||||||
|
HSlistNode *head;
|
||||||
|
struct HArena_ *arena;
|
||||||
|
} HSlist;
|
||||||
|
|
||||||
|
|
||||||
/* The state of the parser.
|
/* The state of the parser.
|
||||||
*
|
*
|
||||||
* Members:
|
* Members:
|
||||||
|
|
@ -57,7 +68,7 @@ struct HParseState_ {
|
||||||
GHashTable *cache;
|
GHashTable *cache;
|
||||||
HInputStream input_stream;
|
HInputStream input_stream;
|
||||||
HArena * arena;
|
HArena * arena;
|
||||||
GQueue *lr_stack;
|
HSlist *lr_stack;
|
||||||
GHashTable *recursion_heads;
|
GHashTable *recursion_heads;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -90,8 +101,8 @@ typedef enum HParserCacheValueType_ {
|
||||||
*/
|
*/
|
||||||
typedef struct HRecursionHead_ {
|
typedef struct HRecursionHead_ {
|
||||||
const HParser *head_parser;
|
const HParser *head_parser;
|
||||||
GSList *involved_set;
|
HSlist *involved_set;
|
||||||
GSList *eval_set;
|
HSlist *eval_set;
|
||||||
} HRecursionHead;
|
} HRecursionHead;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -154,20 +165,11 @@ HCountedArray *h_carray_new_sized(HArena * arena, size_t size);
|
||||||
HCountedArray *h_carray_new(HArena * arena);
|
HCountedArray *h_carray_new(HArena * arena);
|
||||||
void h_carray_append(HCountedArray *array, void* item);
|
void h_carray_append(HCountedArray *array, void* item);
|
||||||
|
|
||||||
typedef struct HSlistNode_ {
|
|
||||||
void* elem;
|
|
||||||
struct HSlistNode_ *next;
|
|
||||||
} HSlistNode;
|
|
||||||
|
|
||||||
typedef struct HSlist_ {
|
|
||||||
HSlistNode *head;
|
|
||||||
struct HArena_ *arena;
|
|
||||||
} HSlist;
|
|
||||||
|
|
||||||
|
|
||||||
HSlist* h_slist_new(HArena *arena);
|
HSlist* h_slist_new(HArena *arena);
|
||||||
void* h_slist_pop(HSlist *slist);
|
void* h_slist_pop(HSlist *slist);
|
||||||
void h_slist_push(HSlist *slist, void* item);
|
void h_slist_push(HSlist *slist, void* item);
|
||||||
|
bool h_slist_find(HSlist *slist, const void* item);
|
||||||
|
HSlist* h_slist_remove_all(HSlist *slist, const void* item);
|
||||||
void h_slist_free(HSlist *slist);
|
void h_slist_free(HSlist *slist);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue