module Language.JavaScript.Parser.ParserMonad
( P
, execParser
, execParserKeepComments
, runParser
, thenP
, returnP
, setLocation
, getLocation
, getInput
, setInput
, getLastToken
, setLastToken
, setLastEOL
, getLastEOL
, ParseError (..)
, ParseState (..)
, initialState
, addComment
, getComments
, spanError
) where
import Control.Applicative ((<$>))
import Control.Monad.Error as Error
import Control.Monad.State.Class
import Control.Monad.State.Strict as State
import Language.JavaScript.Parser.ParseError (ParseError (..))
import Language.JavaScript.Parser.SrcLocation (SrcLocation (..), SrcSpan (..), Span (..))
import Language.JavaScript.Parser.Token (Token (..))
import Prelude hiding (span)
internalError :: String -> P a
internalError = throwError . StrError
spanError :: Span a => a -> String -> P b
spanError x str = throwError $ StrError $ show ([show (getSpan x), str])
data ParseState =
ParseState
{ location :: !SrcLocation
, input :: !String
, previousToken :: !Token
, lastEOL :: !SrcSpan
, comments :: [Token]
}
deriving Show
initToken :: Token
initToken = CommentToken SpanEmpty ""
initialState :: SrcLocation -> String -> [Int] -> ParseState
initialState initLoc inp scStack
= ParseState
{ location = initLoc
, input = inp
, previousToken = initToken
, lastEOL = SpanEmpty
, comments = []
}
type P a = StateT ParseState (Either ParseError) a
execParser :: P a -> ParseState -> Either ParseError a
execParser = evalStateT
execParserKeepComments :: P a -> ParseState -> Either ParseError (a, [Token])
execParserKeepComments parser state =
evalStateT (parser >>= \x -> getComments >>= \c -> return (x, c)) state
runParser :: P a -> ParseState -> Either ParseError (a, ParseState)
runParser = runStateT
returnP :: a -> P a
returnP = return
thenP :: P a -> (a -> P b) -> P b
thenP = (>>=)
setLastEOL :: SrcSpan -> P ()
setLastEOL span = modify $ \s -> s { lastEOL = span }
getLastEOL :: P SrcSpan
getLastEOL = gets lastEOL
setLocation :: SrcLocation -> P ()
setLocation loc = modify $ \s -> s { location = loc }
getLocation :: P SrcLocation
getLocation = gets location
getInput :: P String
getInput = gets input
setInput :: String -> P ()
setInput inp = modify $ \s -> s { input = inp }
getLastToken :: P Token
getLastToken = gets previousToken
setLastToken :: Token -> P ()
setLastToken tok = modify $ \s -> s { previousToken = tok }
addComment :: Token -> P ()
addComment c = do
oldComments <- gets comments
modify $ \s -> s { comments = c : oldComments }
getComments :: P [Token]
getComments = reverse <$> gets comments