Replaced GQueue and GSlist with HSlist.

This commit is contained in:
Meredith L. Patterson 2012-10-08 18:16:18 +02:00
parent b6bf0ea30c
commit ef6af551d1
3 changed files with 61 additions and 25 deletions

View file

@ -15,6 +15,7 @@ HCountedArray *h_carray_new_sized(HArena * arena, size_t size) {
ret->elements = h_arena_malloc(arena, sizeof(void*) * size);
return ret;
}
HCountedArray *h_carray_new(HArena * arena) {
return h_carray_new_sized(arena, 4);
}
@ -32,7 +33,6 @@ void h_carray_append(HCountedArray *array, void* item) {
}
// HSlist
HSlist* h_slist_new(HArena *arena) {
HSlist *ret = h_arena_malloc(arena, sizeof(HSlist));
ret->head = NULL;
@ -58,8 +58,42 @@ void h_slist_push(HSlist *slist, void* item) {
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) {
while (slist->head != NULL)
h_slist_pop(slist);
h_arena_free(slist->arena, slist);
}

View file

@ -79,7 +79,7 @@ HParserCacheValue* recall(HParserCacheKey *k, HParseState *state) {
if (!head) { // No heads found
return cached;
} 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
HParseResult *tmp = a_new(HParseResult, 1);
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);
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.
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);
// we know that cached has an entry here, modify it
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;
rec_detect->head = some;
}
size_t i = 0;
HLeftRec *lr = g_queue_peek_nth(state->lr_stack, i);
assert(state->lr_stack->head != NULL);
HLeftRec *lr = state->lr_stack->head->elem;
while (lr && lr->rule != p) {
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
HLeftRec *base = a_new(HLeftRec, 1);
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
HParserCacheValue *dummy = a_new(HParserCacheValue, 1);
dummy->value_type = PC_LEFT; dummy->left = base;
@ -198,7 +198,7 @@ HParseResult* h_do_parse(const HParser* parser, HParseState *state) {
// parse the input
HParseResult *tmp_res = perform_lowlevel_parse(state, parser);
// 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
if (NULL == base->head) {
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.endianness = BIT_BIG_ENDIAN | BYTE_BIG_ENDIAN;
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,
cache_key_equal);
parse_state->arena = arena;
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);
// tear down the parse state
g_hash_table_destroy(parse_state->cache);

View file

@ -42,6 +42,17 @@ typedef struct HInputStream_ {
char overrun;
} HInputStream;
typedef struct HSlistNode_ {
void* elem;
struct HSlistNode_ *next;
} HSlistNode;
typedef struct HSlist_ {
HSlistNode *head;
struct HArena_ *arena;
} HSlist;
/* The state of the parser.
*
* Members:
@ -57,7 +68,7 @@ struct HParseState_ {
GHashTable *cache;
HInputStream input_stream;
HArena * arena;
GQueue *lr_stack;
HSlist *lr_stack;
GHashTable *recursion_heads;
};
@ -90,8 +101,8 @@ typedef enum HParserCacheValueType_ {
*/
typedef struct HRecursionHead_ {
const HParser *head_parser;
GSList *involved_set;
GSList *eval_set;
HSlist *involved_set;
HSlist *eval_set;
} HRecursionHead;
@ -154,20 +165,11 @@ HCountedArray *h_carray_new_sized(HArena * arena, size_t size);
HCountedArray *h_carray_new(HArena * arena);
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);
void* h_slist_pop(HSlist *slist);
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);
#if 0