{- 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