{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleContexts,
UndecidableInstances #-}
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 qualified Control.Applicative as Applicative ( Applicative(..), Alternative(..) )
import Control.Monad()
import Control.Monad.Trans
import Control.Monad.Identity
import Control.Monad.Reader.Class
import Control.Monad.State.Class
import Control.Monad.Cont.Class
import Control.Monad.Error.Class
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
}
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
data Reply s u a = Ok a !(State s u) ParseError
| Error ParseError
data State s u = State {
stateInput :: s,
statePos :: !SourcePos,
stateUser :: !u
}
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 = return
(<*>) = ap
instance Applicative.Alternative (ParsecT s u m) where
empty = mzero
(<|>) = mplus
instance Monad (ParsecT s u m) where
return x = parserReturn x
p >>= f = parserBind p f
fail msg = parserFail msg
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
{-# INLINE parserBind #-}
parserBind m k
= ParsecT $ \s cok cerr eok eerr ->
let
mcok x s err =
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 =
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
{-# INLINE parserPlus #-}
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))
tokens :: (Stream s m t, Eq t)
=> ([t] -> String)
-> (SourcePos -> [t] -> SourcePos)
-> [t]
-> ParsecT s u m [t]
{-# INLINE tokens #-}
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 = do{ state <- getParserState
; x <- p'
; setParserState state
; return x
}
where
p' = ParsecT $ \s cok cerr eok eerr ->
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
{-# INLINE tokenPrim #-}
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
{-# INLINE tokenPrimEx #-}
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 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 = 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