diff --git a/src/datastructures.c b/src/datastructures.c index e7552e57adb7c0fe183e51e7cf278a24e6bdbdb6..5758f5dc0cac41bd0695bd0d165564664521a63d 100644 --- a/src/datastructures.c +++ b/src/datastructures.c @@ -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); } + diff --git a/src/hammer.c b/src/hammer.c index d1a3334c77ed43b9945a94c1e7249341bffb77e9..0946044b6343a5c428ea946abd2f4cff902023f1 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -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); diff --git a/src/internal.h b/src/internal.h index b59f8240ff5b2e2046d5a833442295fda2729ad1..bf2d661cf70bd7a621cf5ffaaa4870e75e641ca7 100644 --- a/src/internal.h +++ b/src/internal.h @@ -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