From 865f97a343fa82bc5cfbe8c6540e78fc7ad4875a Mon Sep 17 00:00:00 2001
From: Hans-Peter Deifel <hpd@hpdeifel.de>
Date: Wed, 18 Jan 2017 00:42:09 +0100
Subject: [PATCH] Fix edge case in epsilon elimination

The previous procedure would crash if a vertex was not a key in the
graph map, which can happen if it doesn't have any children.
---
 src/Search/EpsilonElimination.hs      | 2 +-
 test/Search/EpsilonEliminationSpec.hs | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/Search/EpsilonElimination.hs b/src/Search/EpsilonElimination.hs
index 11771d2..a7a7c08 100644
--- a/src/Search/EpsilonElimination.hs
+++ b/src/Search/EpsilonElimination.hs
@@ -84,7 +84,7 @@ removeUnreachableNodes start graph =
       | node `S.member` visited = visited
       | otherwise =
         S.foldr (\succ visited' -> getReachable visited' succ) (S.insert node visited) (successors node)
-    successors node = S.map edgeTo $ graph M.! node
+    successors node = S.map edgeTo $ M.findWithDefault S.empty node graph
 
 -- | Return true iff the edge is an ɛ-transition
 isEpsilon :: Edge -> Bool
diff --git a/test/Search/EpsilonEliminationSpec.hs b/test/Search/EpsilonEliminationSpec.hs
index e68691d..6006f14 100644
--- a/test/Search/EpsilonEliminationSpec.hs
+++ b/test/Search/EpsilonEliminationSpec.hs
@@ -54,6 +54,15 @@ eliminateEpsilonsSpec = do
                        ]
     in eliminateEpsilons (mkVertex "A") graph1 `shouldBe` graph2
 
+  it "Works when not all vertices are keys in the map" $
+    let
+      graph1 = mkGraph [ ("A", edges [(Nothing, "B"), (Just "c", "C")])
+                       , ("B", edges [(Just "b", "C")])
+                       ]
+      graph2 = mkGraph [ ("A", edges [(Just "b", "C"), (Just "c", "C")])
+                       ]
+    in eliminateEpsilons (mkVertex "A") graph1 `shouldBe` graph2
+
 epsilonClosureSpec :: Spec
 epsilonClosureSpec = do
   it "Returns the identity map for a graph without epsilons" $
-- 
GitLab