module Text.Parsec.Prim
( unknownError
, sysUnExpectError
, unexpected
, ParsecT
, runParsecT
, mkPT
, Parsec
, Consumed(..)
, Reply(..)
, State(..)
, parsecMap
, parserReturn
, parserBind
, mergeErrorReply
, parserFail
, parserZero
, parserPlus
, (<?>)
, (<|>)
, label
, labels
, lookAhead
, Stream(..)
, tokens
, try
, token
, tokenPrim
, tokenPrimEx
, many
, skipMany
, manyAccum
, runPT
, runP
, runParserT
, runParser
, parse
, parseTest
, getPosition
, getInput
, setPosition
, setInput
, getParserState
, setParserState
, updateParserState
, getState
, putState
, modifyState
, setState
, updateState
) where
import Prelude hiding (sequence)
import qualified Data.ByteString.Lazy.Char8 as CL
import qualified Data.ByteString.Char8 as C
import Data.Typeable ( Typeable )
import qualified Data.Text as Text
import qualified Data.Text.Lazy as TextL
import qualified Data.List.NonEmpty as NE
import Data.List ( genericReplicate )
import Data.Traversable (sequence)
import qualified Data.Functor as Functor ( Functor(..) )
import qualified Data.Semigroup as Semigroup ( Semigroup(..) )
import qualified Data.Monoid as Monoid ( Monoid(..) )
import qualified Control.Applicative as Applicative ( Applicative(..), Alternative(..), liftA2 )
import Control.Monad (MonadPlus (..), ap, void, liftM)
import Control.Monad.Trans (MonadTrans (lift), MonadIO (liftIO))
import Control.Monad.Identity (Identity, runIdentity)
import qualified Control.Monad.Fail as Fail
import Control.Monad.Reader.Class (MonadReader (..))
import Control.Monad.State.Class (MonadState (..))
import Control.Monad.Cont.Class (MonadCont (..))
import Control.Monad.Error.Class (MonadError (..))
import Text.Parsec.Pos
import Text.Parsec.Error
unknownError :: State s u -> ParseError
unknownError state = newErrorUnknown (statePos state)
sysUnExpectError :: String -> SourcePos -> Reply s u a
sysUnExpectError msg pos = Error (newErrorMessage (SysUnExpect msg) pos)
unexpected :: (Stream s m t) => String -> ParsecT s u m a
unexpected msg
= ParsecT $ \s _ _ _ eerr ->
eerr $ newErrorMessage (UnExpect msg) (statePos s)
newtype ParsecT s u m a
= ParsecT {unParser :: forall b .
State s u
-> (a -> State s u -> ParseError -> m b)
-> (ParseError -> m b)
-> (a -> State s u -> ParseError -> m b)
-> (ParseError -> m b)
-> m b
}
#if MIN_VERSION_base(4,7,0)
deriving ( Typeable )
#endif
runParsecT :: Monad m => ParsecT s u m a -> State s u -> m (Consumed (m (Reply s u a)))
runParsecT p s = unParser p s cok cerr eok eerr
where cok a s' err = return . Consumed . return $ Ok a s' err
cerr err = return . Consumed . return $ Error err
eok a s' err = return . Empty . return $ Ok a s' err
eerr err = return . Empty . return $ Error err
mkPT :: Monad m => (State s u -> m (Consumed (m (Reply s u a)))) -> ParsecT s u m a
mkPT k = ParsecT $ \s cok cerr eok eerr -> do
cons <- k s
case cons of
Consumed mrep -> do
rep <- mrep
case rep of
Ok x s' err -> cok x s' err
Error err -> cerr err
Empty mrep -> do
rep <- mrep
case rep of
Ok x s' err -> eok x s' err
Error err -> eerr err
type Parsec s u = ParsecT s u Identity
data Consumed a = Consumed a
| Empty !a
deriving ( Typeable )
data Reply s u a = Ok a !(State s u) ParseError
| Error ParseError
deriving ( Typeable )
data State s u = State {
stateInput :: s,
statePos :: !SourcePos,
stateUser :: !u
}
deriving ( Typeable )
instance Semigroup.Semigroup a => Semigroup.Semigroup (ParsecT s u m a) where
(<>) = Applicative.liftA2 (Semigroup.<>)
#if MIN_VERSION_base(4,8,0)
sconcat = fmap Semigroup.sconcat . sequence
#else
sconcat = fmap (Semigroup.sconcat . NE.fromList) . sequence . NE.toList
#endif
stimes b = Semigroup.sconcat . NE.fromList . genericReplicate b
instance ( Monoid.Monoid a
, Semigroup.Semigroup (ParsecT s u m a)
) => Monoid.Monoid (ParsecT s u m a) where
mempty = Applicative.pure Monoid.mempty
mappend = (Semigroup.<>)
mconcat = Functor.fmap Monoid.mconcat . sequence
instance Functor Consumed where
fmap f (Consumed x) = Consumed (f x)
fmap f (Empty x) = Empty (f x)
instance Functor (Reply s u) where
fmap f (Ok x s e) = Ok (f x) s e
fmap _ (Error e) = Error e
instance Functor (ParsecT s u m) where
fmap f p = parsecMap f p
parsecMap :: (a -> b) -> ParsecT s u m a -> ParsecT s u m b
parsecMap f p
= ParsecT $ \s cok cerr eok eerr ->
unParser p s (cok . f) cerr (eok . f) eerr
instance Applicative.Applicative (ParsecT s u m) where
pure = parserReturn
(<*>) = ap
p1 *> p2 = p1 `parserBind` const p2
p1 <* p2 = do { x1 <- p1 ; void p2 ; return x1 }
instance Applicative.Alternative (ParsecT s u m) where
empty = mzero
(<|>) = mplus
instance Monad (ParsecT s u m) where
return = Applicative.pure
p >>= f = parserBind p f
(>>) = (Applicative.*>)
#if !MIN_VERSION_base(4,13,0)
fail = Fail.fail
#endif
instance Fail.MonadFail (ParsecT s u m) where
fail = parserFail
instance (MonadIO m) => MonadIO (ParsecT s u m) where
liftIO = lift . liftIO
instance (MonadReader r m) => MonadReader r (ParsecT s u m) where
ask = lift ask
local f p = mkPT $ \s -> local f (runParsecT p s)
instance (MonadState s m) => MonadState s (ParsecT s' u m) where
get = lift get
put = lift . put
instance (MonadCont m) => MonadCont (ParsecT s u m) where
callCC f = mkPT $ \s ->
callCC $ \c ->
runParsecT (f (\a -> mkPT $ \s' -> c (pack s' a))) s
where pack s a= Empty $ return (Ok a s (unknownError s))
instance (MonadError e m) => MonadError e (ParsecT s u m) where
throwError = lift . throwError
p `catchError` h = mkPT $ \s ->
runParsecT p s `catchError` \e ->
runParsecT (h e) s
parserReturn :: a -> ParsecT s u m a
parserReturn x
= ParsecT $ \s _ _ eok _ ->
eok x s (unknownError s)
parserBind :: ParsecT s u m a -> (a -> ParsecT s u m b) -> ParsecT s u m b
parserBind m k
= ParsecT $ \s cok cerr eok eerr ->
let
mcok x s err
| errorIsUnknown err = unParser (k x) s cok cerr cok cerr
| otherwise =
let
pcok = cok
pcerr = cerr
peok x s err' = cok x s (mergeError err err')
peerr err' = cerr (mergeError err err')
in unParser (k x) s pcok pcerr peok peerr
meok x s err
| errorIsUnknown err = unParser (k x) s cok cerr eok eerr
| otherwise =
let
pcok = cok
peok x s err' = eok x s (mergeError err err')
pcerr = cerr
peerr err' = eerr (mergeError err err')
in unParser (k x) s pcok pcerr peok peerr
mcerr = cerr
meerr = eerr
in unParser m s mcok mcerr meok meerr
mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
mergeErrorReply err1 reply
= case reply of
Ok x state err2 -> Ok x state (mergeError err1 err2)
Error err2 -> Error (mergeError err1 err2)
parserFail :: String -> ParsecT s u m a
parserFail msg
= ParsecT $ \s _ _ _ eerr ->
eerr $ newErrorMessage (Message msg) (statePos s)
instance MonadPlus (ParsecT s u m) where
mzero = parserZero
mplus p1 p2 = parserPlus p1 p2
parserZero :: ParsecT s u m a
parserZero
= ParsecT $ \s _ _ _ eerr ->
eerr $ unknownError s
parserPlus :: ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
parserPlus m n
= ParsecT $ \s cok cerr eok eerr ->
let
meerr err =
let
neok y s' err' = eok y s' (mergeError err err')
neerr err' = eerr $ mergeError err err'
in unParser n s cok cerr neok neerr
in unParser m s cok cerr eok meerr
instance MonadTrans (ParsecT s u) where
lift amb = ParsecT $ \s _ _ eok _ -> do
a <- amb
eok a s $ unknownError s
infix 0 <?>
infixr 1 <|>
(<?>) :: (ParsecT s u m a) -> String -> (ParsecT s u m a)
p <?> msg = label p msg
(<|>) :: (ParsecT s u m a) -> (ParsecT s u m a) -> (ParsecT s u m a)
p1 <|> p2 = mplus p1 p2
label :: ParsecT s u m a -> String -> ParsecT s u m a
label p msg
= labels p [msg]
labels :: ParsecT s u m a -> [String] -> ParsecT s u m a
labels p msgs =
ParsecT $ \s cok cerr eok eerr ->
let eok' x s' error = eok x s' $ if errorIsUnknown error
then error
else setExpectErrors error msgs
eerr' err = eerr $ setExpectErrors err msgs
in unParser p s cok cerr eok' eerr'
where
setExpectErrors err [] = setErrorMessage (Expect "") err
setExpectErrors err [msg] = setErrorMessage (Expect msg) err
setExpectErrors err (msg:msgs)
= foldr (\msg' err' -> addErrorMessage (Expect msg') err')
(setErrorMessage (Expect msg) err) msgs
class (Monad m) => Stream s m t | s -> t where
uncons :: s -> m (Maybe (t,s))
instance (Monad m) => Stream [tok] m tok where
uncons [] = return $ Nothing
uncons (t:ts) = return $ Just (t,ts)
instance (Monad m) => Stream CL.ByteString m Char where
uncons = return . CL.uncons
instance (Monad m) => Stream C.ByteString m Char where
uncons = return . C.uncons
instance (Monad m) => Stream Text.Text m Char where
uncons = return . Text.uncons
instance (Monad m) => Stream TextL.Text m Char where
uncons = return . TextL.uncons
tokens :: (Stream s m t, Eq t)
=> ([t] -> String)
-> (SourcePos -> [t] -> SourcePos)
-> [t]
-> ParsecT s u m [t]
tokens _ _ []
= ParsecT $ \s _ _ eok _ ->
eok [] s $ unknownError s
tokens showTokens nextposs tts@(tok:toks)
= ParsecT $ \(State input pos u) cok cerr _eok eerr ->
let
errEof = (setErrorMessage (Expect (showTokens tts))
(newErrorMessage (SysUnExpect "") pos))
errExpect x = (setErrorMessage (Expect (showTokens tts))
(newErrorMessage (SysUnExpect (showTokens [x])) pos))
walk [] rs = ok rs
walk (t:ts) rs = do
sr <- uncons rs
case sr of
Nothing -> cerr $ errEof
Just (x,xs) | t == x -> walk ts xs
| otherwise -> cerr $ errExpect x
ok rs = let pos' = nextposs pos tts
s' = State rs pos' u
in cok tts s' (newErrorUnknown pos')
in do
sr <- uncons input
case sr of
Nothing -> eerr $ errEof
Just (x,xs)
| tok == x -> walk toks xs
| otherwise -> eerr $ errExpect x
try :: ParsecT s u m a -> ParsecT s u m a
try p =
ParsecT $ \s cok _ eok eerr ->
unParser p s cok eerr eok eerr
lookAhead :: (Stream s m t) => ParsecT s u m a -> ParsecT s u m a
lookAhead p =
ParsecT $ \s _ cerr eok eerr -> do
let eok' a _ _ = eok a s (newErrorUnknown (statePos s))
unParser p s eok' cerr eok' eerr
token :: (Stream s Identity t)
=> (t -> String)
-> (t -> SourcePos)
-> (t -> Maybe a)
-> Parsec s u a
token showToken tokpos test = tokenPrim showToken nextpos test
where
nextpos _ tok ts = case runIdentity (uncons ts) of
Nothing -> tokpos tok
Just (tok',_) -> tokpos tok'
tokenPrim :: (Stream s m t)
=> (t -> String)
-> (SourcePos -> t -> s -> SourcePos)
-> (t -> Maybe a)
-> ParsecT s u m a
tokenPrim showToken nextpos test = tokenPrimEx showToken nextpos Nothing test
tokenPrimEx :: (Stream s m t)
=> (t -> String)
-> (SourcePos -> t -> s -> SourcePos)
-> Maybe (SourcePos -> t -> s -> u -> u)
-> (t -> Maybe a)
-> ParsecT s u m a
tokenPrimEx showToken nextpos Nothing test
= ParsecT $ \(State input pos user) cok _cerr _eok eerr -> do
r <- uncons input
case r of
Nothing -> eerr $ unexpectError "" pos
Just (c,cs)
-> case test c of
Just x -> let newpos = nextpos pos c cs
newstate = State cs newpos user
in seq newpos $ seq newstate $
cok x newstate (newErrorUnknown newpos)
Nothing -> eerr $ unexpectError (showToken c) pos
tokenPrimEx showToken nextpos (Just nextState) test
= ParsecT $ \(State input pos user) cok _cerr _eok eerr -> do
r <- uncons input
case r of
Nothing -> eerr $ unexpectError "" pos
Just (c,cs)
-> case test c of
Just x -> let newpos = nextpos pos c cs
newUser = nextState pos c cs user
newstate = State cs newpos newUser
in seq newpos $ seq newstate $
cok x newstate $ newErrorUnknown newpos
Nothing -> eerr $ unexpectError (showToken c) pos
unexpectError :: String -> SourcePos -> ParseError
unexpectError msg pos = newErrorMessage (SysUnExpect msg) pos
many :: ParsecT s u m a -> ParsecT s u m [a]
many p
= do xs <- manyAccum (:) p
return (reverse xs)
skipMany :: ParsecT s u m a -> ParsecT s u m ()
skipMany p
= do _ <- manyAccum (\_ _ -> []) p
return ()
manyAccum :: (a -> [a] -> [a])
-> ParsecT s u m a
-> ParsecT s u m [a]
manyAccum acc p =
ParsecT $ \s cok cerr eok _eerr ->
let walk xs x s' _err =
unParser p s'
(seq xs $ walk $ acc x xs)
cerr
manyErr
(\e -> cok (acc x xs) s' e)
in unParser p s (walk []) cerr manyErr (\e -> eok [] s e)
manyErr :: a
manyErr = error "Text.ParserCombinators.Parsec.Prim.many: combinator 'many' is applied to a parser that accepts an empty string."
runPT :: (Stream s m t)
=> ParsecT s u m a -> u -> SourceName -> s -> m (Either ParseError a)
runPT p u name s
= do res <- runParsecT p (State s (initialPos name) u)
r <- parserReply res
case r of
Ok x _ _ -> return (Right x)
Error err -> return (Left err)
where
parserReply res
= case res of
Consumed r -> r
Empty r -> r
runP :: (Stream s Identity t)
=> Parsec s u a -> u -> SourceName -> s -> Either ParseError a
runP p u name s = runIdentity $ runPT p u name s
runParserT :: (Stream s m t)
=> ParsecT s u m a -> u -> SourceName -> s -> m (Either ParseError a)
runParserT = runPT
runParser :: (Stream s Identity t)
=> Parsec s u a -> u -> SourceName -> s -> Either ParseError a
runParser = runP
parse :: (Stream s Identity t)
=> Parsec s () a -> SourceName -> s -> Either ParseError a
parse p = runP p ()
parseTest :: (Stream s Identity t, Show a)
=> Parsec s () a -> s -> IO ()
parseTest p input
= case parse p "" input of
Left err -> do putStr "parse error at "
print err
Right x -> print x
getPosition :: (Monad m) => ParsecT s u m SourcePos
getPosition = do state <- getParserState
return (statePos state)
getInput :: (Monad m) => ParsecT s u m s
getInput = do state <- getParserState
return (stateInput state)
setPosition :: (Monad m) => SourcePos -> ParsecT s u m ()
setPosition pos
= do _ <- updateParserState (\(State input _ user) -> State input pos user)
return ()
setInput :: (Monad m) => s -> ParsecT s u m ()
setInput input
= do _ <- updateParserState (\(State _ pos user) -> State input pos user)
return ()
getParserState :: (Monad m) => ParsecT s u m (State s u)
getParserState = updateParserState id
setParserState :: (Monad m) => State s u -> ParsecT s u m (State s u)
setParserState st = updateParserState (const st)
updateParserState :: (State s u -> State s u) -> ParsecT s u m (State s u)
updateParserState f =
ParsecT $ \s _ _ eok _ ->
let s' = f s
in eok s' s' $ unknownError s'
getState :: (Monad m) => ParsecT s u m u
getState = stateUser `liftM` getParserState
putState :: (Monad m) => u -> ParsecT s u m ()
putState u = do _ <- updateParserState $ \s -> s { stateUser = u }
return ()
modifyState :: (Monad m) => (u -> u) -> ParsecT s u m ()
modifyState f = do _ <- updateParserState $ \s -> s { stateUser = f (stateUser s) }
return ()
setState :: (Monad m) => u -> ParsecT s u m ()
setState = putState
updateState :: (Monad m) => (u -> u) -> ParsecT s u m ()
updateState = modifyState