```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ``` ```--- ---------------------------------------------------------------------------- --- This module provides some simple parser combinators. --- --- @author Jan Tikovsky (with changes by Niels Bunkenburg) --- @version May 2021 --- ---------------------------------------------------------------------------- module ParserComb where data Parser tok a = Parser { runParser :: [tok] -> Either String ([tok], a) } instance Alternative (Parser tok) where empty = Parser \$ const (Left "empty parser") l <|> r = Parser \$ \ts -> case runParser l ts of Left _ -> runParser r ts Right (ts', x) -> Right (ts', x) instance Functor (Parser tok) where fmap f (Parser g) = Parser \$ \ts -> case g ts of Left s -> Left s Right (ts', x) -> Right (ts', f x) instance Applicative (Parser tok) where pure = return af <*> ax = af >>= \f -> fmap f ax instance Monad (Parser tok) where return x = Parser \$ \ts -> Right (ts, x) (Parser p) >>= f = Parser \$ \ts -> case p ts of Left e -> Left e Right (ts', x) -> runParser (f x) ts' eof :: Parser tok a eof = Parser \$ \_ -> Left "Unexpected end-of-file" unexpected :: Show tok => tok -> Parser tok a unexpected t = Parser \$ \_ -> Left \$ "Unexpected token " ++ show t terminal :: (Eq tok, Show tok) => tok -> Parser tok () terminal tok = Parser \$ \tokens -> case tokens of [] -> (runParser eof) [] t:ts | tok == t -> Right (ts, ()) | otherwise -> (runParser (unexpected t)) ts```