From 09ede3acde939ff2580700132982188ba3ff5291 Mon Sep 17 00:00:00 2001 From: Julin S Date: Mon, 26 Jun 2023 17:12:11 +0530 Subject: [PATCH] [haskell] brzozowski derivative --- haskell/brzozowksi.hs | 95 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 haskell/brzozowksi.hs diff --git a/haskell/brzozowksi.hs b/haskell/brzozowksi.hs new file mode 100644 index 0000000..6d1e622 --- /dev/null +++ b/haskell/brzozowksi.hs @@ -0,0 +1,95 @@ +-- {-# LANGUAGE UnicodeSyntax #-} + +-- Brzozowski derivatives + +-- | Type of regexes +data Re a + = Nil + | Eps + | Chr a + | Cat (Re a) (Re a) + | Alt (Re a) (Re a) + | Star (Re a) + +instance Show a => Show (Re a) where + show r = + case r of + Nil -> "Nil" + Eps -> "Eps" + Chr c -> "C " ++ (show c) + Cat r1 r2 -> (show r1) ++ "; " ++ (show r2) + Alt r1 r2 -> (show r1) ++ "| " ++ (show r2) + Star r -> (show r) ++ "* " + +-- | Check if ε can be derived from a regex +εderiv :: Eq a => Re a -> Bool +εderiv r = + case r of + Nil -> False + Eps -> True + Chr _ -> False + Cat r1 r2 -> (εderiv r1) && (εderiv r2) + Alt r1 r2 -> (εderiv r1) || (εderiv r2) + Star _ -> True + +-- | Find Brzozowski derivative of a regex with respect to a letter +deriv :: Eq a => a -> Re a -> Re a +deriv a r = + case r of + Nil -> Nil + Eps -> Nil + Chr c -> + if c==a then Eps + else Nil + Cat r1 r2 -> + if εderiv r1 then deriv a r2 + else Cat (deriv a r1) r2 + Alt r1 r2 -> Alt (deriv a r1) (deriv a r2) + Star rr -> Cat (deriv a rr) (Star rr) + + +-- | See if a string matches a regex +-- exact match only +match :: Eq a => [a] -> Re a -> Bool +match [] r = + if εderiv r then True + else False +match (x:xs) r = + let newr = deriv x r in + case newr of + Nil -> False + _ -> match xs newr +-- λ> match "" (Star (Chr 'a')) +-- True +-- λ> match "aaaaa" (Star (Chr 'a')) +-- True +-- λ> match "aaaaab" (Star (Chr 'a')) +-- False + +-- Couldn't figure out how to make unicode work +(/\) = Cat +(\/) = Alt +-- (@) = Chr + +(|=) :: Eq a => [a] -> Re a -> Bool +(|=) = match + +-- lower precedence for smaller numbers +-- infixr 7 @ +infixr 6 /\ +infixr 5 \/ +infixr 4 |= + +-- ↑0;(↑1│↑0∗);↑1 +-- egr1 = Cat (Chr 0) (Cat (Alt (Chr 1) (Chr 2)) (Chr 3)) +egr1 = (Chr 0) /\ ((Chr 1) \/ (Chr 2)) /\ (Chr 3) +-- egr1 = (@ 0) /\ ((Chr 1) \/ (Chr 2)) /\ (Chr 3) +-- λ> match [0,2,3] egr1 +-- True +-- λ> match [0,1,3] egr1 +-- True +-- λ> match [0,1,2,3] egr1 +-- False +-- +-- λ> [0,2,3] |= egr1 +-- True