{-# LANGUAGE RankNTypes #-} module ParseLib.Parallel.Core ( -- * The type of parsers Parser(), -- * Elementary parsers anySymbol, satisfy, empty, failp, succeed, pure, -- * Parser combinators (<|>), (<<|>), (<*>), (<$>), (>>=), -- * Lookahead look, -- * Running parsers parse ) where import Data.Char import Data.Traversable import Data.Maybe import Control.Monad import Control.Applicative -- | The parser is a CPS version of Parser' newtype Parser s r = Parser (forall a. (r -> Parser' s a) -> Parser' s a) runParser :: Parser s r -> (r -> Parser' s a) -> Parser' s a runParser (Parser p) = p data Parser' s r = SymbolBind (s -> Parser' s r) | Fail | ReturnPlus r (Parser' s r) | LookBind ([s] -> Parser' s r) instance Functor (Parser s) where fmap f p = p >>= \ r -> return (f r) instance Applicative (Parser s) where pure x = return x p <*> q = p >>= \ f -> q >>= \ x -> return (f x) instance Alternative (Parser s) where empty = mzero p <|> q = mplus p q infixl 3 <<|> -- | Biased choice. Not implemented by the parallel parser -- combinators. Just maps to parallel choice. (<<|>) :: Parser s a -> Parser s a -> Parser s a (<<|>) = (<|>) instance Monad (Parser s) where return x = Parser (\ k -> k x) p >>= f = Parser (\ k -> runParser p (\ x -> runParser (f x) k)) instance MonadPlus (Parser s) where mzero = Parser (\ k -> Fail) mplus p q = Parser (\ k -> runParser p k +++ runParser q k) (+++) :: Parser' s a -> Parser' s a -> Parser' s a SymbolBind f +++ SymbolBind g = SymbolBind (\ x -> f x +++ g x) Fail +++ q = q p +++ Fail = p ReturnPlus x p +++ q = ReturnPlus x (p +++ q) p +++ ReturnPlus x q = ReturnPlus x (p +++ q) LookBind f +++ LookBind g = LookBind (\ x -> f x +++ g x) LookBind f +++ q = LookBind (\ x -> f x +++ q) p +++ LookBind g = LookBind (\ x -> p +++ g x) -- | Parses any single symbol. anySymbol :: Parser s s anySymbol = Parser (\ k -> SymbolBind k) -- | Takes a predicate and returns a parser that parses a -- single symbol satisfying that predicate. satisfy :: (s -> Bool) -> Parser s s satisfy p = anySymbol >>= \ x -> if p x then return x else mzero -- | Parser that always succeeds, i.e., for epsilon. succeed :: a -> Parser s a succeed = pure -- | Same as 'empty'; provided for compatibility with the lecture notes. failp :: Parser s a failp = empty -- | Returns the rest of the input without consuming anything. look :: Parser s [s] look = Parser (\ k -> LookBind k) -- | Runs a parser to a given string. parse :: Parser s a -> [s] -> [(a,[s])] parse p = parse' (runParser p (\ x -> ReturnPlus x Fail)) parse' :: Parser' s a -> [s] -> [(a,[s])] parse' (SymbolBind f) (x : xs) = parse' (f x) xs parse' (ReturnPlus x p) xs = (x,xs) : parse' p xs parse' (LookBind f) xs = parse' (f xs) xs parse' _ _ = []