egison-pattern-src-0.1.0.0: src/Language/Egison/Parser/Pattern/Prim/Parse.hs
-- |
--
-- Module: Language.Egison.Parser.Pattern.Prim.Parse
-- Description: Parser monad
-- Stability: experimental
--
-- This module defines a parser monad 'Parse'.
module Language.Egison.Parser.Pattern.Prim.Parse
( Parse
, runParse
)
where
import Control.Applicative ( Alternative )
import Control.Monad.Except ( MonadError(..) )
import Control.Monad.Reader ( ReaderT
, MonadReader(..)
, runReaderT
)
import Control.Monad.Fail ( MonadFail )
import Control.Monad ( MonadPlus )
import Text.Megaparsec ( Parsec
, MonadParsec
)
import qualified Text.Megaparsec as Parsec
( Stream
, parse
, eof
, getSourcePos
)
import Language.Egison.Parser.Pattern.Prim.Source
( Source )
import Language.Egison.Parser.Pattern.Prim.Location
( Locate(..)
, fromSourcePos
)
import Language.Egison.Parser.Pattern.Prim.ParseMode
( ParseMode )
import Language.Egison.Parser.Pattern.Prim.Error
( Errors
, CustomError
, fromParseErrorBundle
)
-- | Parser monad.
newtype Parse n v e s a = Parse { unParse :: ReaderT (ParseMode n v e s) (Parsec (CustomError s) s) a }
deriving newtype (Functor, Applicative, Alternative, Monad, MonadFail, MonadPlus)
deriving newtype (MonadReader (ParseMode n v e s))
deriving newtype (MonadParsec (CustomError s) s)
instance Parsec.Stream s => Locate (Parse n v e s) where
getPosition = fromSourcePos <$> Parsec.getSourcePos
-- | Run 'Parse' monad and produce a parse result.
runParse
:: (Source s, MonadError (Errors s) m)
=> Parse n v e s a
-> ParseMode n v e s
-> FilePath
-> s
-> m a
runParse parse mode filename content =
case Parsec.parse parsec filename content of
Left bundle -> throwError $ fromParseErrorBundle bundle
Right e -> pure e
where
parsec = runReaderT (unParse file) mode
file = parse <* Parsec.eof