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
)
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
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