diff --git a/src/backends/glr.c b/src/backends/glr.c
index 82ad5c06bf6e80c426ae45453933976bf7a32ef6..2978e62daf22854cd2410b1d89f94c8eedfcea5a 100644
--- a/src/backends/glr.c
+++ b/src/backends/glr.c
@@ -43,6 +43,44 @@ HLREngine *fork_engine(const HLREngine *engine)
   return eng2;
 }
 
+static void stow_engine(HSlist *engines, HLREngine *engine)
+{
+  // XXX switch to one engine per state, and do the merge here
+  h_slist_push(engines, engine);
+}
+
+static const HLRAction *handle_conflict(HSlist *engines, const HLREngine *engine,
+                                        const HSlist *branches)
+{
+  // there should be at least two conflicting actions
+  assert(branches->head);
+  assert(branches->head->next);     // this is just a consistency check
+
+  // fork a new engine for all but the first action
+  for(HSlistNode *x=branches->head->next; x; x=x->next) {
+    HLRAction *act = x->elem; 
+    HLREngine *eng = fork_engine(engine);
+
+    // perform one step and add to list
+    h_lrengine_step(eng, act);
+    stow_engine(engines, eng);
+  } 
+
+  // return first action for use with original engine
+  return branches->head->elem;
+}
+
+static HLREngine *handle_demerge(HSlist *engines, HLREngine *engine,
+                                 const HLRAction *reduce)
+{
+  return engine; // XXX
+
+  for(size_t i=0; i<reduce->production.length; i++) {
+    // XXX if stack hits bottom, demerge
+  }
+  // XXX call step and stow on the newly-created engines
+}
+
 HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream* stream)
 {
   HLRTable *table = parser->backend_data;
@@ -60,12 +98,11 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
     for(HSlistNode **x = &engines->head; *x; ) {
       HLREngine *engine = (*x)->elem;
 
-      // check for terminated engines
-      if(engine->run) {
-        x = &(*x)->next;    // advance x with no change
-      } else {
-        *x = (*x)->next;    // advance x, removing the current element
+      // remove engine from list; it may come back in below
+      *x = (*x)->next;    // advance x, removing the current element
 
+      // drop those engines that have terminated
+      if(!engine->run) {
         // check for parse success
         HParseResult *res = h_lrengine_result(engine);
         if(res)
@@ -76,29 +113,19 @@ HParseResult *h_glr_parse(HAllocator* mm__, const HParser* parser, HInputStream*
 
       const HLRAction *action = h_lrengine_action(engine);
 
-      // fork engine on conflicts
-      if(action && action->type == HLR_CONFLICT) {
-        const HSlist *branches = action->branches;
-
-        // there should be at least two conflicting actions
-        assert(branches->head);
-        assert(branches->head->next);
-
-        // save first action for use with old engine below
-        action = branches->head->elem;
-
-        // fork a new engine for all the other actions
-        for(HSlistNode *x=branches->head->next; x; x=x->next) {
-          HLRAction *act = x->elem; 
-          HLREngine *eng = fork_engine(engine);
-
-          // perform one step and add to list
-          h_lrengine_step(eng, act);
-          h_slist_push(engines, eng);
-        } 
+      // handle forks and demerges (~> spawn engines)
+      if(action) {
+        if(action->type == HLR_CONFLICT) {
+          // fork engine on conflicts
+          action = handle_conflict(engines, engine, action->branches);
+        } else if(action->type == HLR_REDUCE) {
+          // demerge as needed to ensure that stacks are deep enough
+          engine = handle_demerge(engines, engine, action);
+        }
       }
 
       h_lrengine_step(engine, action);
+      stow_engine(engines, engine);
     }
   }
 
diff --git a/src/backends/lr.c b/src/backends/lr.c
index ca45582d65a11be833ba701827e6d2c51f0f3428..bb20f7148de97ad3e8284c5ae03b2338e7c2966e 100644
--- a/src/backends/lr.c
+++ b/src/backends/lr.c
@@ -209,6 +209,7 @@ HLREngine *h_lrengine_new(HArena *arena, HArena *tarena, const HLRTable *table,
   engine->run = true;
   engine->stack = h_slist_new(tarena);
   engine->input = *stream;
+  engine->merged = NULL;
   engine->arena = arena;
   engine->tarena = tarena;
 
diff --git a/src/backends/lr.h b/src/backends/lr.h
index 1158542ba98a0224355e98529b8b7562e3e67197..5febc2470dc3bdcdd32454573fbcdfd041f6fc08 100644
--- a/src/backends/lr.h
+++ b/src/backends/lr.h
@@ -74,8 +74,10 @@ typedef struct HLREngine_ {
   HSlist *stack;        // holds pairs: (saved state, semantic value)
   HInputStream input;
 
-  HArena *arena;    // will hold the results
-  HArena *tarena;   // tmp, deleted after parse
+  HSlist *merged;       // saved ancestor engines that merged to form this one
+
+  HArena *arena;        // will hold the results
+  HArena *tarena;       // tmp, deleted after parse
 } HLREngine;