----------------------------------------------------------------------- -- -- Haskell: The Craft of Functional Programming -- Simon Thompson -- (c) Addison-Wesley, 1996-2011. -- -- RegExp.hs -- -- Regular Expressions -- ----------------------------------------------------------------------- module RegExp where type RegExp = String -> Bool char :: Char -> RegExp epsilon = (=="") char ch = (==[ch]) (|||) :: RegExp -> RegExp -> RegExp e1 ||| e2 = \x -> e1 x || e2 x (<*>) :: RegExp -> RegExp -> RegExp e1 <*> e2 = \x -> or [ e1 y && e2 z | (y,z) <- splits x ] (<**>) :: RegExp -> RegExp -> RegExp e1 <**> e2 = \x -> or [ e1 y && e2 z | (y,z) <- fsplits x ] splits xs = [splitAt n xs | n<-[0..len]] where len = length xs star :: RegExp -> RegExp star p = epsilon ||| (p <**> star p) -- epsilon ||| (p <*> star p) -- is OK as long as p can't have epsilon match fsplits xs = tail (splits xs) -- a = char 'a' -- b = char 'b' infixr 7 :*: infixr 5 :|: data RE = Eps | Ch Char | RE :|: RE | RE :*: RE | St RE | Plus RE deriving(Eq,Show) evens = St two two = (a :|: b) :*: (a :|: b) a = Ch 'a' b = Ch 'b' -- interp: RE -> RegExp: exercise. -- Value recursion -- Eunmerating strings matching a regexp enumerate :: RE -> [String] enumerate Eps = [""] enumerate (Ch ch) = [[ch]] enumerate (re1 :|: re2) = enumerate re1 `interleave` enumerate re2 enumerate (re1 :*: re2) = enumerate re1 `cartesian` enumerate re2 enumerate (St re) = result where result = [""] ++ (enumerate re `cartesian` result) -- Auxiliary functions -- interleave and product for potentially infinite lists interleave :: [a] -> [a] -> [a] interleave [] ys = ys interleave (x:xs) ys = x : interleave ys xs cartesian :: [[a]] -> [[a]] -> [[a]] cartesian [] ys = [] cartesian (x:xs) ys = [ x++y | y<-ys ] `interleave` cartesian xs ys -- Recursive regular expressions anbn :: RE anbn = Eps :|: (a :*: (anbn :*: b)) -- Extending the implementation plus :: RE -> RE plus re = re :*: St re -- Simplification simplify :: RE -> RE simplify (St (St re)) = simplify (St re) simplify (Plus (St re)) = simplify (St re) simplify (St (Plus re)) = simplify (St re) simplify (re1 :|: re2) = if sre1==sre2 then sre1 else sre1 :|: sre2 where sre1 = simplify re1; sre2 = simplify re2 simplify re = re -- smart constructors starC :: RE -> RE starC (St re) = re starC (Plus re) = re starC re = St re