module Ast.Parser.PreProcessor where

import qualified Ast.Parser.PreProcessor.Define as PD
import qualified Ast.Parser.PreProcessor.Import as PI
import qualified Ast.Parser.State as PS
import qualified Ast.Parser.Utils as PU
import qualified Control.Monad.State as S
import qualified Text.Megaparsec as M

-- | Preprocesses a source file by handling imports, defines, and other preprocessing tasks.
-- It recursively resolves imports and applies preprocessing rules to the source.
-- Returns the fully preprocessed source code as a `String`.
preprocess :: String -> PU.Parser String
preprocess :: String -> Parser String
preprocess String
sourceFile = do
  (ParserState -> ParserState)
-> ParsecT ParseErrorCustom String (StateT ParserState IO) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
S.modify ((ParserState -> ParserState)
 -> ParsecT ParseErrorCustom String (StateT ParserState IO) ())
-> (ParserState -> ParserState)
-> ParsecT ParseErrorCustom String (StateT ParserState IO) ()
forall a b. (a -> b) -> a -> b
$ String -> ParserState -> ParserState
PS.insertImport String
sourceFile
  [String]
sources <-
    Parser String
-> ParsecT ParseErrorCustom String (StateT ParserState IO) [String]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
M.many (Parser String
 -> ParsecT
      ParseErrorCustom String (StateT ParserState IO) [String])
-> Parser String
-> ParsecT ParseErrorCustom String (StateT ParserState IO) [String]
forall a b. (a -> b) -> a -> b
$
      [Parser String] -> Parser String
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
M.choice
        [ String -> Parser String -> Parser String
PI.parseImport String
sourceFile (String -> Parser String
preprocess String
sourceFile),
          Parser String
PD.parseDefines,
          (Char -> String -> String
forall a. a -> [a] -> [a]
: []) (Char -> String)
-> ParsecT ParseErrorCustom String (StateT ParserState IO) Char
-> Parser String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT ParseErrorCustom String (StateT ParserState IO) Char
ParsecT
  ParseErrorCustom String (StateT ParserState IO) (Token String)
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
M.anySingle
        ]
  String -> Parser String
forall a.
a -> ParsecT ParseErrorCustom String (StateT ParserState IO) a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Parser String) -> String -> Parser String
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
sources