From 7b04ab8d9de37b7ced1b5038565821082fa42285 Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Fri, 14 Jun 2013 12:27:35 +0200
Subject: [PATCH] pre-allocate h_desugar's result to squelch recursive calls

---
 src/backends/contextfree.h | 7 ++++++-
 src/desugar.c              | 4 +++-
 src/parsers/indirect.c     | 2 +-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/backends/contextfree.h b/src/backends/contextfree.h
index 9c2ec459..3f01d708 100644
--- a/src/backends/contextfree.h
+++ b/src/backends/contextfree.h
@@ -11,6 +11,7 @@ struct HCFStack_ {
   int count;
   int cap;
   HCFChoice *last_completed; // Last completed choice.
+  HCFChoice *prealloc;       // If not NULL, will serve as outermost choice.
 };
 
 #ifndef UNUSED
@@ -25,11 +26,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 +59,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 ce87ca32..46176eaf 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 746f1a9e..2217a202 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 = {
-- 
GitLab