-- |
-- Module      : Aihc.Parser.Internal.Module
-- Description : Internal module parser
-- License     : Unlicense
--
-- Internal module containing the core module parser.
-- This is used by both 'Aihc.Parser' and 'Aihc.Parser.Internal.FromTokens'.
module Aihc.Parser.Internal.Module
  ( moduleParser,
  )
where

import Aihc.Parser.Internal.Common (TokParser, expectedTok, skipSemicolons, withSpan)
import Aihc.Parser.Internal.Decl (declParser, importDeclParser, languagePragmaParser, moduleHeaderParser)
import Aihc.Parser.Lex (LexTokenKind (..))
import Aihc.Parser.Syntax (Decl, ImportDecl, Module (..))
import Text.Megaparsec qualified as MP

moduleParser :: TokParser Module
moduleParser :: TokParser Module
moduleParser = TokParser (SourceSpan -> Module) -> TokParser Module
forall a. TokParser (SourceSpan -> a) -> TokParser a
withSpan (TokParser (SourceSpan -> Module) -> TokParser Module)
-> TokParser (SourceSpan -> Module) -> TokParser Module
forall a b. (a -> b) -> a -> b
$ do
  languagePragmas <- ParsecT Void TokStream Identity [ExtensionSetting]
-> ParsecT Void TokStream Identity [[ExtensionSetting]]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
MP.many (ParsecT Void TokStream Identity [ExtensionSetting]
languagePragmaParser ParsecT Void TokStream Identity [ExtensionSetting]
-> ParsecT Void TokStream Identity [()]
-> ParsecT Void TokStream Identity [ExtensionSetting]
forall a b.
ParsecT Void TokStream Identity a
-> ParsecT Void TokStream Identity b
-> ParsecT Void TokStream Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT Void TokStream Identity ()
-> ParsecT Void TokStream Identity [()]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
MP.many (LexTokenKind -> ParsecT Void TokStream Identity ()
expectedTok LexTokenKind
TkSpecialSemicolon))
  mHeader <- MP.optional (moduleHeaderParser <* MP.many (expectedTok TkSpecialSemicolon))
  (imports, decls) <- moduleBodyParser
  pure $ \SourceSpan
span' ->
    Module
      { moduleSpan :: SourceSpan
moduleSpan = SourceSpan
span',
        moduleHead :: Maybe ModuleHead
moduleHead = Maybe ModuleHead
mHeader,
        moduleLanguagePragmas :: [ExtensionSetting]
moduleLanguagePragmas = [[ExtensionSetting]] -> [ExtensionSetting]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[ExtensionSetting]]
languagePragmas,
        moduleImports :: [ImportDecl]
moduleImports = [ImportDecl]
imports,
        moduleDecls :: [Decl]
moduleDecls = [Decl]
decls
      }

moduleBodyParser :: TokParser ([ImportDecl], [Decl])
moduleBodyParser :: TokParser ([ImportDecl], [Decl])
moduleBodyParser = TokParser ([ImportDecl], [Decl])
-> TokParser ([ImportDecl], [Decl])
forall a.
ParsecT Void TokStream Identity a
-> ParsecT Void TokStream Identity a
forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
MP.try TokParser ([ImportDecl], [Decl])
bracedModuleBodyParser TokParser ([ImportDecl], [Decl])
-> TokParser ([ImportDecl], [Decl])
-> TokParser ([ImportDecl], [Decl])
forall a.
ParsecT Void TokStream Identity a
-> ParsecT Void TokStream Identity a
-> ParsecT Void TokStream Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
MP.<|> TokParser ([ImportDecl], [Decl])
plainModuleBodyParser
  where
    plainModuleBodyParser :: TokParser ([ImportDecl], [Decl])
plainModuleBodyParser = do
      imports <- ParsecT Void TokStream Identity ImportDecl
-> ParsecT Void TokStream Identity [ImportDecl]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
MP.many (ParsecT Void TokStream Identity ImportDecl
importDeclParser ParsecT Void TokStream Identity ImportDecl
-> ParsecT Void TokStream Identity ()
-> ParsecT Void TokStream Identity ImportDecl
forall a b.
ParsecT Void TokStream Identity a
-> ParsecT Void TokStream Identity b
-> ParsecT Void TokStream Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT Void TokStream Identity ()
skipSemicolons)
      decls <- MP.many (declParser <* skipSemicolons)
      pure (imports, decls)

    bracedModuleBodyParser :: TokParser ([ImportDecl], [Decl])
bracedModuleBodyParser = do
      LexTokenKind -> ParsecT Void TokStream Identity ()
expectedTok LexTokenKind
TkSpecialLBrace
      ParsecT Void TokStream Identity ()
skipSemicolons
      imports <- ParsecT Void TokStream Identity ImportDecl
-> ParsecT Void TokStream Identity [ImportDecl]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
MP.many (ParsecT Void TokStream Identity ImportDecl
importDeclParser ParsecT Void TokStream Identity ImportDecl
-> ParsecT Void TokStream Identity ()
-> ParsecT Void TokStream Identity ImportDecl
forall a b.
ParsecT Void TokStream Identity a
-> ParsecT Void TokStream Identity b
-> ParsecT Void TokStream Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT Void TokStream Identity ()
skipSemicolons)
      decls <- MP.many (declParser <* skipSemicolons)
      skipSemicolons
      expectedTok TkSpecialRBrace
      pure (imports, decls)