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