platinum-parsing-0.1.0.0: test/PPTest/Builders/Nfa.hs
module PPTest.Builders.Nfa (specs) where
import qualified Data.Char as C
import qualified Data.Graph.Inductive.Graph as Gr
import PP
import PP.Builders.Nfa
import PP.Grammars.Lexical
import Test.Hspec
-- Utilities
getNfa expr = let Right ast = (parseAst expr :: To RegExpr) in buildNfa ast
isValue (_, _, NfaValue _) = True
isValue _ = False
specs = describe "PPTest.Builders.Nfa" $ do
it "should build the correct automaton ((a|b)*abb)" $ do
-- Dragon Book (2nd edition, fr), page 142, figure 3.34
let expr = "(a|b)*abb"
let e = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaNode),(3,NfaNode),
(4,NfaNode),(5,NfaNode),(6,NfaNode),(7,NfaNode),
(8,NfaNode),(9,NfaNode),(10,NfaFinal expr)]
[(0,1,NfaEmpty),(0,7,NfaEmpty),(1,2,NfaEmpty),
(1,4,NfaEmpty),(2,3,NfaValue 'a'),(3,6,NfaEmpty),
(4,5,NfaValue 'b'),(5,6,NfaEmpty),(6,1,NfaEmpty),
(6,7,NfaEmpty),(7,8,NfaValue 'a'),(8,9,NfaValue 'b'),
(9,10,NfaValue 'b')]
getNfa expr `shouldBe` e
it "should build the correct automaton (a+)" $ do
let expr = "a+"
let e = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaNode),(3,NfaFinal expr)]
[(0,1,NfaEmpty),(1,2,NfaValue 'a'),
(2,1,NfaEmpty),(2,3,NfaEmpty)]
getNfa expr `shouldBe` e
it "should build the correct automaton (a?)" $ do
let expr = "a?"
let e = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaNode),(3,NfaFinal expr)]
[(0,1,NfaEmpty),(0,3,NfaEmpty),
(1,2,NfaValue 'a'),(2,3,NfaEmpty)]
getNfa expr `shouldBe` e
it "should build the correct automaton ([a-c])" $ do
let expr = "[a-c]"
let e = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaNode),(3,NfaNode),
(4,NfaNode),(5,NfaNode),(6,NfaNode),(7,NfaFinal expr)]
[(0,1,NfaEmpty),(0,3,NfaEmpty),(0,5,NfaEmpty),
(1,2,NfaValue 'a'),(2,7,NfaEmpty),(3,4,NfaValue 'b'),
(4,7,NfaEmpty),(5,6,NfaValue 'c'),(6,7,NfaEmpty)]
getNfa expr `shouldBe` e
it "should build the correct automaton ([a-c0-2.-])" $ do
let expr = "[a-c0-2.-]"
let e = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaNode),(3,NfaNode),
(4,NfaNode),(5,NfaNode),(6,NfaNode),(7,NfaNode),
(8,NfaNode),(9,NfaNode),(10,NfaNode),(11,NfaNode),
(12,NfaNode),(13,NfaNode),(14,NfaNode),(15,NfaNode),
(16,NfaNode),(17,NfaFinal expr)]
[(0,1,NfaEmpty),(0,3,NfaEmpty),(0,5,NfaEmpty),
(0,7,NfaEmpty),(0,9,NfaEmpty),(0,11,NfaEmpty),
(0,13,NfaEmpty),(0,15,NfaEmpty),(1,2,NfaValue 'a'),
(2,17,NfaEmpty),(3,4,NfaValue 'b'),(4,17,NfaEmpty),
(5,6,NfaValue 'c'),(6,17,NfaEmpty),(7,8,NfaValue '0'),
(8,17,NfaEmpty),(9,10,NfaValue '1'),(10,17,NfaEmpty),
(11,12,NfaValue '2'),(12,17,NfaEmpty),(13,14,NfaValue '.'),
(14,17,NfaEmpty),(15,16,NfaValue '-'),(16,17,NfaEmpty)]
getNfa expr `shouldBe` e
it "should build the correct automaton (.)" $ do
let expr = "."
let e = [c | c <- [minBound..maxBound], C.isAscii c]
let values = map (\(_, _, NfaValue c) -> c) $ filter isValue $ Gr.labEdges $ getNfa expr
values `shouldBe` e
it "should combine multiple NFA in one correctly" $ do
let a = Gr.mkGraph [(0,NfaInitial),(1,NfaFinal "a")]
[(0,1,NfaValue 'a')]
let b = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaFinal "bc")]
[(0,1,NfaValue 'b'),(1,2,NfaValue 'c')]
let e = Gr.mkGraph [(0,NfaInitial),(1,NfaNode),(2,NfaFinal "a"),(3,NfaNode),
(4,NfaNode),(5,NfaFinal "bc")]
[(0,1,NfaEmpty),(0,3,NfaEmpty),(1,2,NfaValue 'a'),
(3,4,NfaValue 'b'),(4,5,NfaValue 'c')]
combineNfa [a,b] `shouldBe` e