diff --git a/src/backends/llk.c b/src/backends/llk.c
index ad09aa5a5b02ca69dd06259d4404f708b85e2ea0..69fb7efa979152fc1b9eaa0cc84f0be1ae99a9ed 100644
--- a/src/backends/llk.c
+++ b/src/backends/llk.c
@@ -3,6 +3,8 @@
 #include "../cfgrammar.h"
 #include "../parsers/parser_internal.h"
 
+static const size_t DEFAULT_KMAX = 1;
+
 
 /* Generating the LL(k) parse table */
 
@@ -17,11 +19,6 @@ typedef struct HLLkTable_ {
 } HLLkTable;
 
 
-// XXX adaptation to LL(1), to be removed
-typedef HCharKey HCFToken;
-static const HCFToken end_token = 0x200;
-#define char_token char_key
-
 /* Interface to look up an entry in the parse table. */
 const HCFSequence *h_llk_lookup(const HLLkTable *table, const HCFChoice *x,
                                 HInputStream lookahead)
@@ -116,7 +113,7 @@ static void *combine_entries(HHashSet *workset, void *dst, const void *src)
 
   if(dst == CONFLICT) {                 // previous conflict
     h_hashset_put(workset, src);
-  } else if(dst != src) {               // new conflict
+  } else if(dst == src) {               // new conflict
     h_hashset_put(workset, dst);
     h_hashset_put(workset, src);
     dst = CONFLICT;
@@ -161,12 +158,15 @@ static void stringmap_merge(HHashSet *workset, HCFStringMap *dst, HCFStringMap *
         if(dst_)
           stringmap_merge(workset, dst_, src_);
         else
-          dst_ = src_;
+          h_hashtable_put(dst->char_branches, (void *)c, src_);
       }
     }
   }
 }
 
+void pprint_sequence(FILE *f, const HCFGrammar *g, const HCFSequence *seq);
+void pprint_symbol(FILE *f, const HCFGrammar *g, const HCFChoice *x);
+
 /* Generate entries for the production "A" in the given table row. */
 static int fill_table_row(size_t kmax, HCFGrammar *g, HCFStringMap *row,
                           const HCFChoice *A)
@@ -202,8 +202,23 @@ static int fill_table_row(size_t kmax, HCFGrammar *g, HCFStringMap *row,
         // merge predict set into the row
         // accumulates conflicts in new workset
         stringmap_merge(nextset, row, pred);
+
+        // XXX debug
+        if(A == g->start) {
+          printf("predict(");
+          pprint_sequence(stdout, g, rhs);
+          printf("  ) = ");
+          h_pprint_stringset(stdout, g, pred, 0);
+        }
       }
     }
+    // XXX debug
+    if(A == g->start) {
+      printf("row(");
+      pprint_symbol(stdout, g, A);
+      printf(") = ");
+      h_pprint_stringset(stdout, g, row, 0);
+    }
 
     // switch to the updated workset
     h_hashtable_free(workset);
@@ -254,8 +269,6 @@ static int fill_table(size_t kmax, HCFGrammar *g, HLLkTable *table)
   return 0;
 }
 
-static const size_t DEFAULT_KMAX = 1;
-
 int h_llk_compile(HAllocator* mm__, HParser* parser, const void* params)
 {
   size_t kmax = params? (uintptr_t)params : DEFAULT_KMAX;
@@ -460,7 +473,7 @@ int test_llk(void)
   */
 
   HParser *X = h_optional(h_ch('x'));
-  HParser *Y = h_epsilon_p(); //h_sequence(h_ch('y'), NULL);
+  HParser *Y = h_sequence(h_ch('y'), NULL);
   HParser *A = h_sequence(X, Y, h_ch('a'), NULL);
   HParser *B = h_sequence(Y, h_ch('b'), NULL);
   HParser *p = h_choice(A, B, NULL);
diff --git a/src/cfgrammar.c b/src/cfgrammar.c
index 9abfd10e97c7dfaaaf765fefb3b4092441a2e0a7..1721122e8a3a34496f09949800ca85ff024ef101 100644
--- a/src/cfgrammar.c
+++ b/src/cfgrammar.c
@@ -624,7 +624,7 @@ static HCFChoice **pprint_string(FILE *f, HCFChoice **x)
   return x;
 }
 
-static void pprint_symbol(FILE *f, const HCFGrammar *g, const HCFChoice *x)
+void pprint_symbol(FILE *f, const HCFGrammar *g, const HCFChoice *x)
 {
   switch(x->type) {
   case HCF_CHAR:
@@ -643,7 +643,7 @@ static void pprint_symbol(FILE *f, const HCFGrammar *g, const HCFChoice *x)
   }
 }
 
-static void pprint_sequence(FILE *f, const HCFGrammar *g, const HCFSequence *seq)
+void pprint_sequence(FILE *f, const HCFGrammar *g, const HCFSequence *seq)
 {
   HCFChoice **x = seq->items;