-- |A module providing simple Parser combinator functionality. Useful -- for small parsing tasks such as identifier parsing or command-line -- argument parsing module Language.Parser ( module Definitive, -- * The ParserT Type ParserT(..),Parser,ParserA(..),_ParserA, -- ** The Stream class Stream(..),emptyStream, -- ** Converting to/from Parsers parserT,parser,ioParser, -- * Basic combinators (<+>),(>*>),(<*<),cut, token,satisfy, oneOf,noneOf,single, several, remaining,eoi, -- ** Specialized utilities readable,number,digit,letter,alNum,quotedString,space,spaces,eol, -- * Basic combinators many,many1,sepBy,sepBy1,skipMany,skipMany1, chainl,chainr,option ) where import Definitive hiding (take) import Data.Char import Data.Containers.Sequence newtype ParserT s m a = ParserT (StateT s (ListT m) a) deriving (Unit,Functor,Semigroup,Monoid,Applicative, Monad,MonadFix,MonadList,MonadState s,MonadWriter w) type Parser c a = ParserT c Id a deriving instance Monad m => MonadError Void (ParserT c m) instance MonadTrans (ParserT s) where lift = ParserT . lift . lift instance ConcreteMonad (ParserT s) where generalize = parserT %%~ map (pure.yb i'Id) _ParserT :: Iso (ParserT s m a) (ParserT t n b) (StateT s (ListT m) a) (StateT t (ListT n) b) _ParserT = iso ParserT (\(ParserT p) -> p) parserT :: (Functor n,Functor m) => Iso (ParserT s m a) (ParserT t n b) (s -> m [(s,a)]) (t -> n [(t,b)]) parserT = mapping listT.stateT._ParserT parser :: Iso (Parser s a) (Parser t b) (s -> [(s,a)]) (t -> [(t,b)]) parser = mapping i'Id.parserT ioParser :: Parser a b -> (a -> IO b) ioParser p s = case (p^..parser) s of [] -> error "Error in parsing" (_,a):_ -> return a -- |The @(+)@ operator with lower priority (<+>) :: Semigroup m => m -> m -> m (<+>) = (+) (>*>) :: Monad m => ParserT a m b -> ParserT b m c -> ParserT a m c (>*>) = (>>>)^..(_ParserA<.>_ParserA<.>_ParserA) (<*<) :: Monad m => ParserT b m c -> ParserT a m b -> ParserT a m c (<*<) = flip (>*>) cut :: Monad m => ParserT s m a -> ParserT s m a cut = parserT %%~ map2 (take 1) newtype ParserA m s a = ParserA (ParserT s m a) _ParserA :: Iso (ParserA m s a) (ParserA m' s' a') (ParserT s m a) (ParserT s' m' a') _ParserA = iso ParserA (\(ParserA p) -> p) parserA :: Iso (ParserA m s a) (ParserA m' s' a') (StateA (ListT m) s a) (StateA (ListT m') s' a') parserA = from stateA._ParserT._ParserA instance Monad m => Category (ParserA m) where id = ParserA get (.) = (.)^.(parserA<.>parserA<.>parserA) instance Monad m => Split (ParserA m) where (<#>) = (<#>)^.(parserA<.>parserA<.>parserA) instance Monad m => Choice (ParserA m) where (<|>) = (<|>)^.(parserA<.>parserA<.>parserA) instance Monad m => Arrow (ParserA m) where arr f = arr f^.parserA -- |The remaining Stream to parse remaining :: Monad m => ParserT s m s remaining = get -- |Consume a token from the Stream token :: (Monad m,Stream c s) => ParserT s m c {-# SPECIALIZE token :: Monad m => ParserT [c] m c #-} token = get >>= \s -> case uncons s of Nothing -> zero Just (c,t) -> put t >> pure c -- |Parse zero, one or more successive occurences of a parser. many :: Monad m => ParserT c m a -> ParserT c m [a] many p = many1 p <+> pure [] -- |Parse one or more successiveé occurences of a parser. many1 :: Monad m => ParserT c m a -> ParserT c m [a] many1 p = (:)<$>p<*>many p -- |Skip many occurences of a parser skipMany :: Monad m => ParserT c m a -> ParserT c m () skipMany p = skipMany1 p <+> pure () -- |Skip multiple occurences of a parser skipMany1 :: Monad m => ParserT c m a -> ParserT c m () skipMany1 p = p >> skipMany p -- |Consume a token and succeed if it verifies a predicate satisfy :: (Monad m, Stream c s) => (c -> Bool) -> ParserT s m c {-# SPECIALIZE satisfy :: Monad m => (c -> Bool) -> ParserT [c] m c #-} satisfy p = token <*= guard . p -- |Consume a single fixed token or fail. single :: (Eq c, Monad m, Stream c s) => c -> ParserT s m () single = void . satisfy . (==) -- |Consume a structure of characters or fail several :: (Eq c, Monad m, Foldable t, Stream c s) => t c -> ParserT s m () {-# SPECIALIZE several :: (Eq c, Monad m) => [c] -> ParserT [c] m () #-} several l = traverse_ single l -- |Try to consume a parser. Return a default value when it fails. option :: Monad m => a -> ParserT s m a -> ParserT s m a option a p = p <+> pure a -- |Succeed only at the End Of Input. eoi :: (Monad m,Stream c s) => ParserT s m () eoi = remaining >>= guard.emptyStream -- |The end of a line eol :: (Monad m,Stream Char s) => ParserT s m () eol = single '\n' -- |Parse one or more successive occurences of a parser separated by -- occurences of a second parser. sepBy1 ::Monad m => ParserT c m a -> ParserT c m b -> ParserT c m [a] sepBy1 p sep = (:)<$>p<*>many (sep >> p) -- |Parse zero or more successive occurences of a parser separated by -- occurences of a second parser. sepBy ::Monad m => ParserT c m a -> ParserT c m b -> ParserT c m [a] sepBy p sep = option [] (sepBy1 p sep) -- |Parse a member of a set of values oneOf :: (Eq c, Monad m, Foldable t, Stream c s) => t c -> ParserT s m c oneOf = satisfy . flip elem -- |Parse anything but a member of a set noneOf :: (Eq c, Monad m, Foldable t, Stream c s) => t c -> ParserT s m c noneOf = satisfy . map not . flip elem -- |Parse a litteral decimal number number :: (Monad m,Stream Char s,Num n) => ParserT s m n number = fromInteger.read <$> many1 digit -- |Parse a single decimal digit digit :: (Monad m,Stream Char s) => ParserT s m Char digit = satisfy isDigit alNum :: (Monad m,Stream Char s) => ParserT s m Char alNum = satisfy isAlphaNum letter :: (Monad m,Stream Char s) => ParserT s m Char letter = satisfy isAlpha -- |Parse a delimited string, unsing '\\' as the quoting character quotedString :: (Monad m,Stream Char s) => Char -> ParserT s m String quotedString d = between (single d) (single d) (many ch) where ch = single '\\' >> unquote<$>token <+> noneOf (d:"\\") unquote 'n' = '\n' unquote 't' = '\t' unquote c = c -- |A single space space :: (Monad m,Stream Char s) => ParserT s m Char space = satisfy isSpace -- |Many spaces spaces :: (Monad m,Stream Char s) => ParserT s m String spaces = many1 space infixl 1 `sepBy`,`sepBy1` infixr 0 <+> -- |Chain an operator with an initial value and several tail values. chainr :: (Stream c s,Monad m) => ParserT s m a -> ParserT s m (b -> a -> a) -> ParserT s m b -> ParserT s m a chainr expr op e = compose<$>many (op<**>e)<*>expr -- |Chain an operator with an initial value chainl :: (Stream c s,Monad m) => ParserT s m a -> ParserT s m (a -> b -> a) -> ParserT s m b -> ParserT s m a chainl expr op e = compose<$>many (flip<$>op<*>e)<**>expr -- |Test if a Stream is empty emptyStream :: Stream c s => s -> Bool emptyStream = maybe True (const False) . uncons readable :: (Monad m,Read a) => ParserT String m a readable = generalize $ map2 swap (readsPrec 0)^.parser