{-# LANGUAGE DeriveDataTypeable #-} module Control.Pipe.Attoparsec ( ParseError(..), pipeParser, ) where import qualified Control.Exception as E import Control.Pipe import Control.Pipe.Combinators import Control.Pipe.Exception import Data.Attoparsec.Types import Data.Maybe import Data.Monoid import Data.Typeable -- | A parse error as returned by Attoparsec. data ParseError = ParseError { errorContexts :: [String], -- ^ Contexts where the error occurred. errorMessage :: String -- ^ Error message. } | DivergentParser -- ^ Returned if a parser does not terminate -- when its input is exhausted. deriving (Show, Typeable) instance E.Exception ParseError -- | Convert a parser continuation into a Pipe. -- -- To get a parser continuation from a 'Parser', use the @parse@ function of the -- appropriate Attoparsec module. pipeParser :: (Monoid a, Monad m) => (a -> IResult a r) -> Pipe a x m (a, Either ParseError r) pipeParser p = go p where go p = do chunk <- tryAwait case p (maybe mempty id chunk) of Fail leftover contexts msg -> return (leftover, Left $ ParseError contexts msg) Partial p' -> if isNothing chunk then return (mempty, Left DivergentParser) else go p' Done leftover result -> return (leftover, Right result)