------------------------------------------------------------------------------ --- A library with deterministic parser combinators. --- --- Might be moved into a separate package in the future. ------------------------------------------------------------------------------ module DetParser where type Parser token a = [token] -> Either ParseError ([token], a) type ParseError = String --- Combine parsers with resulting representation of first one. (<*) :: Parser token a -> Parser token b -> Parser token a a <* b = const <$> a <*> b --- Combine parsers with resulting representation of second one. (*>) :: Parser token a -> Parser token b -> Parser token b a *> b = const id <$> a <*> b (<*>) :: Parser token (a -> b) -> Parser token a -> Parser token b a <*> b = \ts -> case a ts of Left e -> Left e Right (ts', f) -> case b ts' of Left e -> Left e Right (ts2, x) -> Right (ts2, f x) --- Combines two parsers in an alternative manner. (<|>) :: Parser token a -> Parser token a -> Parser token a a <|> b = \ts -> case a ts of Right (ts', x) -> Right (ts', x) Left e -> case b ts of Left e' -> Left $ "parse error: " ++ e' ++ " | " ++ e Right (ts2, y) -> Right (ts2, y) --- Apply unary function `f` to result of parser `p` (<$>) :: (a -> b) -> Parser token a -> Parser token b f <$> p = yield f <*> p --- Apply binary function `f` to results of parsers `p1` and `p2` liftP2 :: (a -> b -> r) -> Parser token a -> Parser token b -> Parser token r liftP2 f p1 p2 = \ts -> case p1 ts of Left e -> Left e Right (ts', x) -> case p2 ts' of Left e -> Left e Right (ts2, y) -> Right (ts2, f x y) --- A parser with `x` as representation while consuming no tokens. yield :: a -> Parser token a yield x ts = Right (ts, x) --- A parser recognizing a particular terminal symbol. terminal :: (Eq token, Show token) => token -> Parser token () terminal _ [] = eof [] terminal x (t:ts) = case x == t of True -> Right (ts, ()) False -> unexpected t ts --- Returns parse error about unexpected end-of-file eof :: Parser token a eof _ = Left "unexpected end-of-file" --- Returns parse error about unexpected token `t` unexpected :: Show token => token -> Parser token a unexpected t _ = Left $ "unexpected token " ++ show t --- A star combinator for parsers. The returned parser --- repeats zero or more times a parser p and --- returns the representation of all parsers in a list. star :: Parser token a -> Parser token [a] star p = (\ts -> case p ts of Left e -> Left e Right (ts', x) -> (x:) <$> star p $ ts') <|> yield [] --- A some combinator for parsers. The returned parser --- repeats the argument parser at least once. some :: Parser token a -> Parser token [a] some p = \ts -> case p ts of Left e -> Left e Right (ts', x) -> (x:) <$> star p $ ts' -- same as <$> -- liftP :: (a -> r) -> Parser token a -> Parser token r -- liftP f m = \ts -> let res = m ts -- in case res of -- Left e -> Left e -- Right (ts', x) -> Right (ts', f x)