zhaw-fup/Exercises/exercise-3/Regex.hs

124 lines
3.4 KiB
Haskell

{- Syntax
Implementieren Sie den AST (abstract syntax tree) entsprechend den Vorgaben
auf dem Übungsblatt.
-}
data Regex
= Empty
| Epsilon
| Symbol Char
-- | Sequence, Star, Choice fehlen noch.
deriving Show
{- Semantik
Ziel ist es die Funktion 'match :: Regex -> String -> Bool' zu implementieren,
die überprüft ob ein gegebener String zu einer gegebenen Regex passt. Im
folgenden werden dafür zuerst drei Hilfsfunktionen implementiert, die Sie dann
für 'match' verwenden können.
-}
{- Helper function 1:
Given a predicate and a string this function returns all (proper) tails
of the string that are obtained by removing an initial segment that
satisfies the predicate.
Examples:
tails (\s -> length s == 1) "abcde" == ["bcde"]
tails (\s -> length s >= 1) "abcde" == ["bcde","cde","de","e",""]
-}
tails :: (String -> Bool) -> String -> [String]
tails f s = error "fixme"
{- Helper function 2:
By repeatedly calling the tails function, this function checks if
it is possible to partition a given string into consecutive segments
each of which satisfies the predicate.
Examples:
segmentable (\s -> length s == 2) "abcde" == False
segmentable (\s -> length s == 2) "abcd" == True
-}
segmentable :: (String -> Bool) -> String -> Bool
segmentable f s
| s == "" = True
| "" `elem` leads = True
| leads == [] = False
| otherwise = error "fixme"
{- Helper function 3:
Given two predicates and a string, this function checks if it is
possible to partition the string into a prefix and a suffix such that
the prefix satisfies the first predicate and the suffix satisfies the
second predicate.
Examples:
combinable (\s -> length s == 2) (\s -> length s == 3) "12345" == True
combinable (\s -> length s == 2) (\s -> length s == 3) "1234" == False
combinable (\s -> length s == 2) (\s -> length s == 3) "123456" == False
-}
combinable :: (String -> Bool) -> (String -> Bool) -> String -> Bool
combinable f g s = error "fixme"
{-
Matching a particular string to a regex a regex now simply means to check
to cover the base cases and use the helper functions.
-}
match :: Regex -> String -> Bool
match r s = case r of
Empty -> error "fixme"
Epsilon -> error "fixme"
Symbol c -> error "fixme"
Choice r1 r2 -> error "fixme"
Sequence r1 r2 -> error "fixme"
Star r1 -> error "fixme"
{-
Examples/test-cases
-}
-- (ab*|ac*)*
r1 :: Regex
r1 = Star
( Choice
( Sequence
( Symbol 'a')
( Star (Symbol 'b'))
)
(Sequence
(Symbol 'a')
(Star (Symbol 'c'))
)
)
-- (ab*|ac*)*x*
r2 :: Regex
r2 = Sequence r1 (Star (Symbol 'x'))
-- ab
r3 :: Regex
r3 = Sequence (Symbol 'a') (Symbol 'b')
-- a(a|b)*
r4 :: Regex
r4 = Sequence (Symbol 'a') $ Star $ Choice (Symbol 'a') (Symbol 'b')
shouldBeTrue1 :: Bool
shouldBeTrue1 = match r1 "abbbbaccca"
shouldBeFalse1 :: Bool
shouldBeFalse1 = match r1 "abbcc"
shouldBeTrue2 :: Bool
shouldBeTrue2 = match r2 "abbbbacccabxxxx"
shouldBeFalse2 :: Bool
shouldBeFalse2 = match r2 "abbxxxacc"
shouldBeTrue3 :: Bool
shouldBeTrue3 = match r3 "ab"
shouldBeFalse3 :: Bool
shouldBeFalse3 = match r3 "aba"
shouldBeTrue4 :: Bool
shouldBeTrue4 = match r4 "abbbab"
shouldBeFalse4 :: Bool