module Lecture19 where

type Token = Char

{-
H  -> G | epsilon
G  -> gC | gB
F  -> fE | gD
E  -> Ce
D  -> BA
C  -> cA
B  -> bd
A  -> a
-}

parseA :: [Token] -> Maybe [Token]
parseA ('a':ts)  = Just ts
parseA _         = Nothing

parseB :: [Token] -> Maybe [Token]
parseB ('b':'d':ts)  = Just ts
parseB _             = Nothing

parseC :: [Token] -> Maybe [Token]
parseC ('c':ts)  = parseA ts
parseC _         = Nothing

parseD :: [Token] -> Maybe [Token]
parseD ts =  case parseB ts of
               Nothing   -> Nothing
               Just ts'  -> parseA ts'
        
parseE :: [Token] -> Maybe [Token]
parseE ts =  case parseC ts of
               Just ('e':ts')  -> Just ts' 
               _               -> Nothing
               
parseF :: [Token] -> Maybe [Token]
parseF ('f':ts)  = parseE ts
parseF ('g':ts)  = parseD ts
parseF _         = Nothing

parseG :: [Token] -> Maybe [Token]
parseG ('g':ts)  =  case parseC ts of -- note: limited backtracking only!
                      Just ts'  -> Just ts'
                      Nothing   -> parseB ts
parseG _         =  Nothing

parseH :: [Token] -> Maybe [Token]
parseH ts =  case parseG ts of
               Just ts'  -> Just ts'
               Nothing   -> Just ts
               
parser :: [Token] -> Bool
parser ts =  case parseH ts of
               Just []  -> True
               _        -> False