module Parsing ( Parser -- exports the type name but not the constructor ,parse, success,failure,sat,pmap,item,char,digit, (+++),(<:>),(>*>),(>->),(<-<), oneOrMore,zeroOrMore ) {---------------------- Week 5A Same as RefactoredParser but now Parser added to typeclass Monad ----------------------} where import Data.Maybe import Data.Char ------------------ data Parser a = P (String -> Maybe (a,String)) instance Monad Parser where (>>=) = (>*>) return = success parse :: Parser a -> String -> Maybe(a,String) -- run a parser on a given string parse (P p) s = p s ------------------- -- Basic Parsers, dependent on internal structure -- -- success and fail failure :: Parser a failure = P $ \_ -> Nothing success :: a -> Parser a success a = P $ \s -> Just (a,s) -- Parse any single character item = P $ \s -> case s of (c:cs) -> Just (c,cs) _ -> Nothing -- (+++) parse either using p or else using q infixr 5 +++ (+++) :: Parser a -> Parser a -> Parser a p +++ q = P $ \s-> parse p s `orElse` parse q s where Just a `orElse` _ = Just a _ `orElse` b = b -- (p >*> f) parse using p to produce a. -- Then parse using f a infixl 1 >*> (>*>) :: Parser a -> (a -> Parser b) -> Parser b p >*> f = P $ \s -> case parse p s of Just (a,s') -> parse (f a) s' _ -> Nothing ----------------------------------------------- -- Parsers below do not depend on the internal -- representation of Parser -- sat p parse a single character satisfying p sat :: (Char -> Bool) -> Parser Char sat p = item >*> \c -> if p c then success c else failure char c = sat (==c) digit = sat isDigit -- pmap modifies the result of a parser pmap :: (a -> b) -> Parser a -> Parser b pmap f p = p >*> success . f (>->) :: Parser a -> Parser b -> Parser b p >-> q = p >*> \_ -> q -- equivalent to monadic op: >> (<-<) :: Parser b -> Parser a -> Parser b p <-< q = p >*> \a -> q >-> success a (<:>):: Parser a -> Parser [a] -> Parser [a] p <:> q = p >*> \a -> pmap (a:) q oneOrMore, zeroOrMore :: Parser a -> Parser [a] oneOrMore p = p <:> zeroOrMore p {- do a <- p as <- zeroOrMore p return (a:as) -} zeroOrMore p = oneOrMore p +++ success []