From ccdb0fa85cd2bdac9d91098aad33db4233dcfc1f Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Sat, 11 May 2013 20:40:33 +0200
Subject: [PATCH] eliminate duplication of result handling code in LL driver

---
 src/backends/llk.c | 67 ++++++++++++++++++++++------------------------
 1 file changed, 32 insertions(+), 35 deletions(-)

diff --git a/src/backends/llk.c b/src/backends/llk.c
index 60587d29..f2e83108 100644
--- a/src/backends/llk.c
+++ b/src/backends/llk.c
@@ -200,33 +200,12 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
           lookahead = char_token(c);
     }
 
-    // pop top of stack and check for frame delimiter
+    // pop top of stack for inspection
     HCFChoice *x = h_slist_pop(stack);
     assert(x != NULL);
-    if(x == mark) {
-      // hit stack frame boundary
-
-      // wrap the accumulated parse result, this sequence is finished
-      HParsedToken *tok = h_arena_malloc(arena, sizeof(HParsedToken));
-      tok->token_type = TT_SEQUENCE;
-      tok->seq = seq;
-      // XXX tok->index and tok->bit_offset (don't take directly from stream, cuz peek!)
-
-      // recover original nonterminal and result sequence
-      x   = h_slist_pop(stack);
-      seq = h_slist_pop(stack);
-      // tok becomes next left-most element of higher-level sequence
 
-      // call validation and semantic action, if present
-      if(x->pred && !x->pred(make_result(tarena, tok)))
-        goto no_parse;    // validation failed -> no parse
-      if(x->action)
-        tok = (HParsedToken *)x->action(make_result(arena, tok));
-
-      h_carray_append(seq, tok);
-    }
-    else if(x->type == HCF_CHOICE) {
-      // x is a nonterminal; apply the appropriate production
+    if(x != mark && x->type == HCF_CHOICE) {
+      // x is a nonterminal; apply the appropriate production and continue
 
       // push stack frame
       h_slist_push(stack, seq);   // save current partial value
@@ -244,15 +223,31 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
       for(s = p->items; *s; s++);
       for(s--; s >= p->items; s--)
         h_slist_push(stack, *s);
+
+      continue; // no result to record
+    }
+
+    // the top of stack is such that there will be a result...
+    HParsedToken *tok;  // will hold result token
+    if(x == mark) {
+      // hit stack frame boundary...
+      // wrap the accumulated parse result, this sequence is finished
+      tok = h_arena_malloc(arena, sizeof(HParsedToken));
+      tok->token_type = TT_SEQUENCE;
+      tok->seq = seq;
+
+      // recover original nonterminal and result sequence
+      x   = h_slist_pop(stack);
+      seq = h_slist_pop(stack);
+      // tok becomes next left-most element of higher-level sequence
     }
     else {
-      // x is a terminal, or simple charset; match against input
+      // x is a terminal or simple charset; match against input
 
       // consume the input token
       HCFToken input = lookahead;
       lookahead = 0;
 
-      HParsedToken *tok;
       switch(x->type) {
       case HCF_END:
         if(input != end_token)
@@ -282,18 +277,20 @@ HParseResult *h_llk_parse(HAllocator* mm__, const HParser* parser, HInputStream*
         assert_message(0, "unknown HCFChoice type");
         goto no_parse;
       }
+    }
 
-      // XXX tok->index and tok->bit_offset (don't take directly from stream, cuz peek!)
+    // 'tok' has been parsed; process it
 
-      // call validation and semantic action, if present
-      if(x->pred && !x->pred(make_result(tarena, tok)))
-        goto no_parse;  // validation failed -> no parse
-      if(x->action)
-        tok = (HParsedToken *)x->action(make_result(arena, tok));
+    // XXX set tok->index and tok->bit_offset (don't take directly from stream, cuz peek!)
 
-      // append to result sequence
-      h_carray_append(seq, tok);
-    }
+    // call validation and semantic action, if present
+    if(x->pred && !x->pred(make_result(tarena, tok)))
+      goto no_parse;    // validation failed -> no parse
+    if(x->action)
+      tok = (HParsedToken *)x->action(make_result(arena, tok));
+
+    // append to result sequence
+    h_carray_append(seq, tok);
   }
 
   // since we started with a single nonterminal on the stack, seq should
-- 
GitLab