{-# LANGUAGE FlexibleContexts #-}
module Atomo.Parser where
import Control.Monad.Identity
import Control.Monad.State
import Text.Parsec
import Atomo.Environment
import Atomo.Lexer
import Atomo.Lexer.Base
import Atomo.Parser.Base
import Atomo.Parser.Expr
import Atomo.Parser.Expand
import Atomo.Types hiding (keyword, string)
-- | Parses an input file, performs macro expansion, and returns an AST.
parseFile :: FilePath -> VM [Expr]
parseFile fn =
liftIO (readFile fn)
>>= continue fileLexer parser fn
>>= nextPhase
-- | Parses an input string, performs macro expansion, and returns an AST.
parseInput :: String -> VM [Expr]
parseInput s = continue lexer parser "" s >>= nextPhase
-- | Given a Parser action, a source, and the input, perform that action
-- passing the parser state between VM and Parser.
continue :: Stream x Identity t => Lexer x -> ParserOf x a -> String -> String -> VM a
continue l p s i = do
ps <- gets parserState
case runParser l (LexerState []) s i of
Left e -> throwError (ParseError e)
Right ts ->
case runParser (p >>= \r -> getState >>= \ps' -> return (r, ps')) ps s ts of
Left e -> throwError (ParseError e)
Right (ok, ps') -> do
modify $ \e -> e { parserState = ps' }
return ok
-- | Parse input i from source s, maintaining parser state between parses.
continuedParse :: String -> String -> VM [Expr]
continuedParse i s = continue lexer parser s i
-- | Run an arbitrary Parser action with the VM's parser state.
withParser :: Parser a -> VM a
withParser x = continue lexer x "" ""