From 19892acc788ecb8e8098abbc36c8cca63858068b Mon Sep 17 00:00:00 2001
From: "Sven M. Hallberg" <pesco@khjk.org>
Date: Fri, 21 Feb 2020 19:35:40 +0100
Subject: [PATCH] do fixpoint iteration on workset for h_first/h_follow

---
 src/cfgrammar.c | 47 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/src/cfgrammar.c b/src/cfgrammar.c
index 47a27f13..5da26c6a 100644
--- a/src/cfgrammar.c
+++ b/src/cfgrammar.c
@@ -393,6 +393,15 @@ bool h_stringmap_equal(const HStringMap *a, const HStringMap *b)
   return h_hashtable_equal(a->char_branches, b->char_branches, eq_stringmap);
 }
 
+// helper for h_follow and h_first
+bool workset_equal(HHashTable *a, HHashTable *b)
+{
+  if (a == NULL || b == NULL)
+    return (a == b);
+  else
+    return h_hashtable_equal(a, b, eq_stringmap);
+}
+
 static const HStringMap *
 h_first_seq_work(size_t k, HCFGrammar *g, HHashTable **pws, HCFChoice **s);
 
@@ -481,13 +490,18 @@ h_first_work(size_t k, HCFGrammar *g, HHashTable **pws, const HCFChoice *x)
 
 const HStringMap *h_first(size_t k, HCFGrammar *g, const HCFChoice *x)
 {
-  HHashTable *ws = NULL;
+  HHashTable *ws, *bak;
   const HStringMap *ret;
 
-  // XXX perform fixpoint iteration on workset
-  ret = h_first_work(k, g, &ws, x);
-  assert(ret != NULL);
+  // fixpoint iteration on workset
+  ws = NULL;
+  do {
+    bak = ws;
+    ws = NULL;
+    ret = h_first_work(k, g, &ws, x);
+  } while(!workset_equal(ws, bak));
 
+  assert(ret != NULL);
   return ret;
 }
 
@@ -539,13 +553,18 @@ h_first_seq_work(size_t k, HCFGrammar *g, HHashTable **pws, HCFChoice **s)
 
 const HStringMap *h_first_seq(size_t k, HCFGrammar *g, HCFChoice **s)
 {
-  HHashTable *ws = NULL;
+  HHashTable *ws, *bak;
   const HStringMap *ret;
 
-  // XXX perform fixpoint iteration on workset
-  ret = h_first_seq_work(k, g, &ws, s);
-  assert(ret != NULL);
+  // fixpoint iteration on workset
+  ws = NULL;
+  do {
+    bak = ws;
+    ws = NULL;
+    ret = h_first_seq_work(k, g, &ws, s);
+  } while(!workset_equal(ws, bak));
 
+  assert(ret != NULL);
   return ret;
 }
 
@@ -718,12 +737,18 @@ h_follow_work(size_t k, HCFGrammar *g, HHashTable **pws, const HCFChoice *x)
 
 const HStringMap *h_follow(size_t k, HCFGrammar *g, const HCFChoice *x)
 {
-  HHashTable *ws = NULL;
+  HHashTable *ws, *bak;
   const HStringMap *ret;
 
-  // XXX perform fixpoint iteration on workset
-  ret = h_follow_work(k, g, &ws, x);
+  // fixpoint iteration on workset
+  ws = NULL;
+  do {
+    bak = ws;
+    ws = NULL;
+    ret = h_follow_work(k, g, &ws, x);
+  } while(!workset_equal(ws, bak));
 
+  assert(ret != NULL);
   return ret;
 }
 
-- 
GitLab