module RefactoredParser where import Data.Char import Data.Maybe infixr 5 +++ type Parser a = String -> Maybe (a,String) -- Parser Combinators ------------------------ pmap :: (a -> b) -> Parser a -> Parser b pmap f p s = case p s of Nothing -> Nothing Just (a,s') -> Just (f a, s') (+++) :: Parser a -> Parser a -> Parser a (p +++ q) s = listToMaybe [x | Just x <- [p s, q s]] (>*>) :: Parser a -> (a -> Parser b) -> Parser b (p >*> f) s = case p s of Nothing -> Nothing Just (a,rest) -> f a rest succeed :: a -> Parser a succeed a s = Just (a,s) fail s = Nothing sat :: (Char -> Bool) -> Parser Char sat p (c:cs) | p c = Just (c,cs) sat _ _ = Nothing -- toplevel parser should not have anything after the parsed item topLevel :: Parser a -> String -> Maybe a topLevel p s = case p s of Just (a,"") -> Just a _ -> Nothing ------------------------------------------------------------------ -- Parsers below do not depend on the representation of Parsers char :: Char -> Parser Char char c = sat (==c) digit :: Parser Char digit = sat isDigit number :: Parser Int number = pmap read (oneOrMore digit) (>->) :: Parser a -> Parser b -> Parser b p >-> q = p >*> \_ -> q p <-< q = p >*> \a -> q >-> succeed a (<:>) :: Parser a -> Parser [a] -> Parser [a] p <:> q = p >*> \a -> pmap (a:) q zeroOrMore,oneOrMore :: Parser a -> Parser [a] zeroOrMore p = oneOrMore p +++ succeed [] oneOrMore p = p <:> zeroOrMore p chain :: Parser a -> Char -> (a -> a -> a) -> Parser a chain p c f = pmap (foldr1 f) (p <:> afterFirst) where afterFirst = zeroOrMore (char c >-> p)