ampersand-3.1.0: src/Database/Design/Ampersand/Input/ADL1/LexerMonad.hs
{-| Module : LexerMonad
License : GPL
Maintainer : helium@cs.uu.nl
Stability : experimental
Portability : portable
-}
module Database.Design.Ampersand.Input.ADL1.LexerMonad
( LexerMonad
, addPos
, lexerError, lexerWarning
, runLexerMonad
) where
import Database.Design.Ampersand.Input.ADL1.LexerMessage
import Database.Design.Ampersand.Input.ADL1.FilePos
import Database.Design.Ampersand.Misc
import Control.Applicative
import Control.Monad
type Bracket = (FilePos, Char)
-- | The type of the Lexer Monad
-- Output monad: [LexerWarning]
-- State monad: FilePos and [Bracket]
newtype LexerMonad a =
LM ([Options] -- The command line options
-> FilePos -- The position in the file
-> [Bracket] -- List of brackets
-> Either LexerError (a, [LexerWarning], FilePos, [Bracket]) -- The result is either an error or the result with a list of warnings, a file position and a list of brackets
)
unLM :: LexerMonad t -> [Options] -> FilePos -> [Bracket]
-> Either LexerError (t, [LexerWarning], FilePos, [Bracket])
unLM (LM x) = x
bindLM :: LexerMonad a -> (a -> LexerMonad b) -> LexerMonad b
bindLM (LM f) g =
LM (\opts pos brackets ->
case f opts pos brackets of
Left err -> Left err
Right (a, warnings, pos2, brackets2) ->
case unLM (g a) opts pos2 brackets2 of
Left err -> Left err
Right (b, moreWarnings, pos3, brackets3) ->
Right (b, warnings ++ moreWarnings, pos3, brackets3))
returnLM :: a -> LexerMonad a
returnLM x = LM (\_ pos brackets -> Right (x, [], pos, brackets))
instance Monad LexerMonad where
(>>=) = bindLM
return = returnLM
instance Functor LexerMonad where
-- fmap :: (a -> b) -> LexerMonad a -> LexerMonad b
fmap ab la = do { a <- la; return (ab a) }
instance Applicative LexerMonad where
pure = returnLM
(<*>) = ap
-- | Runs the lexer monad
runLexerMonad :: [Options] -- ^ The command line options
-> FilePath -- ^ The file to be read (used for error messages)
-> LexerMonad a -- ^ The lexer monad to run
-> Either LexerError (a, [LexerWarning]) -- ^ Result is either an error or a result and a list of warnings
runLexerMonad opts file (LM f) =
case f opts (initPos file) [] of
Left err -> Left err
Right (a, warnings, _, _) -> Right (a, keepOneTabWarning warnings)
-- | Generates a monad with an error message
lexerError :: LexerErrorInfo -- ^ The generated error
-> FilePos -- ^ The location where the error is originated
-> LexerMonad a -- ^ The resulting monad
lexerError err pos =
LM (\_ _ _ -> Left (LexerError pos err))
-- | Generates a monad with a warning message
lexerWarning :: LexerWarningInfo -- ^ The generated warning
-> FilePos -- ^ The location where the warning is originated
-> LexerMonad () -- ^ The resulting monad
lexerWarning warning warningPos =
LM (\_ pos brackets ->
Right ((), [LexerWarning warningPos warning], pos, brackets))