module RegExp where
(<==>) :: Bool -> Bool -> Bool
a <==> b = a == b
-- ---------------------
data Nat = Zer
| Suc Nat
deriving (Eq, Show)
sub :: Nat -> Nat -> Nat
sub x y =
case y of
Zer -> x
Suc y' -> case x of
Zer -> Zer
Suc x' -> sub x' y'
data Sym = N0
| N1 Sym
deriving (Eq, Show)
data RE = Sym Sym
| Or RE RE
| Seq RE RE
| And RE RE
| Star RE
| Empty
deriving (Eq, Show)
accepts :: RE -> [Sym] -> Bool
accepts re ss =
case re of
Sym n -> case ss of
[] -> False
(n':ss') -> n == n' && null ss'
Or re1 re2 -> accepts re1 ss || accepts re2 ss
Seq re1 re2 -> seqSplit re1 re2 [] ss
And re1 re2 -> accepts re1 ss && accepts re2 ss
Star re' -> case ss of
[] -> True
(s:ss') -> seqSplit re' re (s:[]) ss'
-- accepts Empty ss || accepts (Seq re' re) ss
Empty -> null ss
seqSplit :: RE -> RE -> [Sym] -> [Sym] -> Bool
seqSplit re1 re2 ss2 ss =
seqSplit'' re1 re2 ss2 ss || seqSplit' re1 re2 ss2 ss
seqSplit'' :: RE -> RE -> [Sym] -> [Sym] -> Bool
seqSplit'' re1 re2 ss2 ss = accepts re1 ss2 && accepts re2 ss
seqSplit' :: RE -> RE -> [Sym] -> [Sym] -> Bool
seqSplit' re1 re2 ss2 ss =
case ss of
[] -> False
(n:ss') ->
seqSplit re1 re2 (ss2 ++ [n]) ss'
rep :: Nat -> RE -> RE
rep n re =
case n of
Zer -> Empty
Suc n' -> Seq re (rep n' re)
repMax :: Nat -> RE -> RE
repMax n re =
case n of
Zer -> Empty
Suc n' -> Or (rep n re) (repMax n' re)
repInt' :: Nat -> Nat -> RE -> RE
repInt' n k re =
case k of
Zer -> rep n re
Suc k' -> Or (rep n re) (repInt' (Suc n) k' re)
repInt :: Nat -> Nat -> RE -> RE
repInt n k re = repInt' n (sub k n) re
-- Properties
prop_regex :: (Nat, Nat, RE, RE, [Sym]) -> Bool
prop_regex (n, k, p, q, s) = r
where
r = (accepts (repInt n k (And p q)) s)
<==> (accepts (And (repInt n k p) (repInt n k q)) s)
--(accepts (And (repInt n k p) (repInt n k q)) s) <==> (accepts (repInt n k (And p q)) s)^M
a_sol = (Zer, Suc (Suc Zer), Sym N0, Seq (Sym N0) (Sym N0), [N0, N0])