elm-compiler-0.14: src/Parse/Module.hs
module Parse.Module (header, headerAndImports, getModuleName) where
import Control.Applicative ((<$>), (<*>))
import Data.List (intercalate)
import Text.Parsec hiding (newline, spaces)
import Parse.Helpers
import qualified AST.Module as Module
import qualified AST.Variable as Var
getModuleName :: String -> Maybe String
getModuleName source =
case iParse getModuleName source of
Right name -> Just name
Left _ -> Nothing
where
getModuleName = do
optional freshLine
(names, _) <- header
return (intercalate "." names)
headerAndImports :: IParser Module.HeaderAndImports
headerAndImports =
do optional freshLine
(names, exports) <-
option (["Main"], Var.openListing) (header `followedBy` freshLine)
imports' <- commitToImports <|> return []
return $ Module.HeaderAndImports names exports imports'
where
commitToImports =
do try (lookAhead $ reserved "import")
imports `followedBy` freshLine
header :: IParser ([String], Var.Listing Var.Value)
header = do
try (reserved "module")
whitespace
names <- dotSep1 capVar <?> "name of module"
whitespace
exports <- option Var.openListing (listing value)
whitespace <?> "reserved word 'where'"
reserved "where"
return (names, exports)
imports :: IParser [(Module.Name, Module.ImportMethod)]
imports = option [] ((:) <$> import' <*> many (try (freshLine >> import')))
import' :: IParser (Module.Name, Module.ImportMethod)
import' =
do reserved "import"
whitespace
names <- dotSep1 capVar
(,) names <$> option (Module.As (intercalate "." names)) method
where
method :: IParser Module.ImportMethod
method = as' <|> importing'
as' :: IParser Module.ImportMethod
as' = do
try (whitespace >> reserved "as")
whitespace
Module.As <$> capVar <?> "alias for module"
importing' :: IParser Module.ImportMethod
importing' = Module.Open <$> listing value
listing :: IParser a -> IParser (Var.Listing a)
listing item =
do try (whitespace >> char '(')
whitespace
listing <- choice [ const Var.openListing <$> string ".."
, Var.Listing <$> commaSep1 item <*> return False
] <?> "listing of values (x,y,z)"
whitespace
char ')'
return listing
value :: IParser Var.Value
value = val <|> tipe
where
val = Var.Value <$> (lowVar <|> parens symOp)
tipe = do
name <- capVar
maybeCtors <- optionMaybe (listing capVar)
case maybeCtors of
Nothing -> return (Var.Alias name)
Just ctors -> return (Var.Union name ctors)