diff --git a/src/backends/contextfree.h b/src/backends/contextfree.h
index 9c2ec4598cb703ba773c4d515b90a2165a73c336..b387e55df21387d4be137d7ff159889de50985ba 100644
--- a/src/backends/contextfree.h
+++ b/src/backends/contextfree.h
@@ -11,6 +11,8 @@ struct HCFStack_ {
   int count;
   int cap;
   HCFChoice *last_completed; // Last completed choice.
+                             // XXX is last_completed still needed?
+  HCFChoice *prealloc; // If not NULL, will be used for the outermost choice.
 };
 
 #ifndef UNUSED
@@ -25,11 +27,13 @@ static HCFStack* h_cfstack_new(HAllocator *mm__) {
   stack->count = 0;
   stack->cap = 4;
   stack->stack = h_new(HCFChoice*, stack->cap);
+  stack->prealloc = NULL;
   return stack;
 }
 
 static void h_cfstack_free(HAllocator *mm__, HCFStack *stk__) UNUSED; 
 static void h_cfstack_free(HAllocator *mm__, HCFStack *stk__) {
+  h_free(stk__->prealloc);
   h_free(stk__->stack);
   h_free(stk__);
 }
@@ -56,7 +60,9 @@ static inline void h_cfstack_add_to_seq(HAllocator *mm__, HCFStack *stk__, HCFCh
 }
 
 static inline HCFChoice* h_cfstack_new_choice_raw(HAllocator *mm__, HCFStack *stk__) {
-  HCFChoice *ret = h_new(HCFChoice, 1);
+  HCFChoice *ret = stk__->prealloc? stk__->prealloc : h_new(HCFChoice, 1);
+  stk__->prealloc = NULL;
+
   ret->reshape = NULL;
   ret->action = NULL;
   ret->pred = NULL;
diff --git a/src/desugar.c b/src/desugar.c
index ce87ca326b1d8ad533c8b9eecbaf81e4513eb488..46176eaf39b827e7124499096368ab8cba9442ae 100644
--- a/src/desugar.c
+++ b/src/desugar.c
@@ -8,9 +8,11 @@ HCFChoice *h_desugar(HAllocator *mm__, HCFStack *stk__, const HParser *parser) {
     if (nstk__ == NULL) {
       nstk__ = h_cfstack_new(mm__);
     }
+    if(nstk__->prealloc == NULL)
+      nstk__->prealloc = h_new(HCFChoice, 1);
     // we're going to do something naughty and cast away the const to memoize
+    ((HParser *)parser)->desugared = nstk__->prealloc;
     parser->vtable->desugar(mm__, nstk__, parser->env);
-    ((HParser *)parser)->desugared = nstk__->last_completed;
     if (stk__ == NULL)
       h_cfstack_free(mm__, nstk__);
   } else if (stk__ != NULL) {
diff --git a/src/parsers/indirect.c b/src/parsers/indirect.c
index 746f1a9ee37a0fbcdf6558cf7670290d34a76972..2217a202968f2a11306c60ccea34c9e3126186c1 100644
--- a/src/parsers/indirect.c
+++ b/src/parsers/indirect.c
@@ -10,7 +10,7 @@ static bool indirect_isValidCF(void *env) {
 }
 
 static void desugar_indirect(HAllocator *mm__, HCFStack *stk__, void *env) {
-  HCFS_DESUGAR( (HParser*)env );
+  HCFS_DESUGAR( (HParser *)env );
 }
 
 static const HParserVtable indirect_vt = {
diff --git a/src/t_parser.c b/src/t_parser.c
index 8aab7bb38e4b950e60da93e1c362b4a09ef0bbb0..fa191510cdf7513d160e3c2e76f1c676401ca0db 100644
--- a/src/t_parser.c
+++ b/src/t_parser.c
@@ -407,7 +407,7 @@ static void test_not(gconstpointer backend) {
 }
 /*
 static void test_leftrec(gconstpointer backend) {
-  const HParser *a_ = h_ch('a');
+  HParser *a_ = h_ch('a');
 
   HParser *lr_ = h_indirect();
   h_bind_indirect(lr_, h_choice(h_sequence(lr_, a_, NULL), a_, NULL));
@@ -417,6 +417,17 @@ static void test_leftrec(gconstpointer backend) {
   g_check_parse_ok(lr_, (HParserBackend)GPOINTER_TO_INT(backend), "aaa", 3, "((u0x61 u0x61) u0x61)");
 }
 */
+static void test_rightrec(gconstpointer backend) {
+  HParser *a_ = h_ch('a');
+
+  HParser *rr_ = h_indirect();
+  h_bind_indirect(rr_, h_choice(h_sequence(a_, rr_, NULL), h_epsilon_p(), NULL));
+
+  g_check_parse_ok(rr_, (HParserBackend)GPOINTER_TO_INT(backend), "a", 1, "(u0x61)");
+  g_check_parse_ok(rr_, (HParserBackend)GPOINTER_TO_INT(backend), "aa", 2, "(u0x61 (u0x61))");
+  g_check_parse_ok(rr_, (HParserBackend)GPOINTER_TO_INT(backend), "aaa", 3, "(u0x61 (u0x61 (u0x61)))");
+}
+
 void register_parser_tests(void) {
   g_test_add_data_func("/core/parser/packrat/token", GINT_TO_POINTER(PB_PACKRAT), test_token);
   g_test_add_data_func("/core/parser/packrat/ch", GINT_TO_POINTER(PB_PACKRAT), test_ch);
@@ -460,6 +471,7 @@ void register_parser_tests(void) {
   g_test_add_data_func("/core/parser/packrat/not", GINT_TO_POINTER(PB_PACKRAT), test_not);
   g_test_add_data_func("/core/parser/packrat/ignore", GINT_TO_POINTER(PB_PACKRAT), test_ignore);
   //  g_test_add_data_func("/core/parser/packrat/leftrec", GINT_TO_POINTER(PB_PACKRAT), test_leftrec);
+  g_test_add_data_func("/core/parser/packrat/rightrec", GINT_TO_POINTER(PB_PACKRAT), test_rightrec);
 
   g_test_add_data_func("/core/parser/llk/token", GINT_TO_POINTER(PB_LLk), test_token);
   g_test_add_data_func("/core/parser/llk/ch", GINT_TO_POINTER(PB_LLk), test_ch);
@@ -496,6 +508,8 @@ void register_parser_tests(void) {
   g_test_add_data_func("/core/parser/llk/epsilon_p", GINT_TO_POINTER(PB_LLk), test_epsilon_p);
   g_test_add_data_func("/core/parser/llk/attr_bool", GINT_TO_POINTER(PB_LLk), test_attr_bool);
   g_test_add_data_func("/core/parser/llk/ignore", GINT_TO_POINTER(PB_LLk), test_ignore);
+  //g_test_add_data_func("/core/parser/llk/leftrec", GINT_TO_POINTER(PB_LLk), test_leftrec);
+  g_test_add_data_func("/core/parser/llk/rightrec", GINT_TO_POINTER(PB_LLk), test_rightrec);
 
   g_test_add_data_func("/core/parser/regex/token", GINT_TO_POINTER(PB_REGULAR), test_token);
   g_test_add_data_func("/core/parser/regex/ch", GINT_TO_POINTER(PB_REGULAR), test_ch);