on 2297bbf help sign in
elk/src/Parse/Module.hs
115 lines 3.1 kB history raw
1module Parse.Module (moduleDecl, header, getModuleName) where
3import Control.Applicative ((<$>), (<*>))
4import Text.Parsec hiding (newline, spaces)
6import Parse.Helpers
7import qualified AST.Module as Module
8import qualified AST.Module.Name as ModuleName
9import qualified AST.Variable as Var
10import Reporting.Annotation as A
13getModuleName :: String -> Maybe String
14getModuleName source =
15 case iParse getModuleName source of
16 Right name ->
17 Just name
19 Left _ ->
20 Nothing
21 where
22 getModuleName =
23 do optional freshLine
24 (names, _) <- moduleDecl
25 return (ModuleName.toString names)
28header :: IParser (Module.Header [Module.UserImport])
29header =
30 do optional freshLine
31 (names, exports) <-
32 option (["Main"], Var.openListing) (moduleDecl `followedBy` freshLine)
33 docs <-
34 choice
35 [ addLocation (Just <$> docComment) `followedBy` freshLine
36 , addLocation (return Nothing)
37 ]
38 imports' <- imports
39 return (Module.Header names docs exports imports')
42moduleDecl :: IParser ([String], Var.Listing (A.Located Var.Value))
43moduleDecl =
44 expecting "a module declaration" $
45 do try (reserved "module")
46 whitespace
47 names <- dotSep1 capVar <?> "the name of this module"
48 whitespace
49 exports <- option Var.openListing (listing (addLocation value))
50 whitespace
51 reserved "where"
52 return (names, exports)
55imports :: IParser [Module.UserImport]
56imports =
57 many (import' `followedBy` freshLine)
60import' :: IParser Module.UserImport
61import' =
62 expecting "an import" $
63 addLocation $
64 do try (reserved "import")
65 whitespace
66 names <- dotSep1 capVar
67 (,) names <$> method (ModuleName.toString names)
68 where
69 method :: String -> IParser Module.ImportMethod
70 method defaultAlias =
71 Module.ImportMethod
72 <$> option (Just defaultAlias) (Just <$> as' defaultAlias)
73 <*> option Var.closedListing exposing
75 as' :: String -> IParser String
76 as' moduleName =
77 do try (whitespace >> reserved "as")
78 whitespace
79 capVar <?> ("an alias for module `" ++ moduleName ++ "`")
81 exposing :: IParser (Var.Listing Var.Value)
82 exposing =
83 do try (whitespace >> reserved "exposing")
84 whitespace
85 listing value
88listing :: IParser a -> IParser (Var.Listing a)
89listing item =
90 expecting "a listing of values and types to expose, like (..)" $
91 do try (whitespace >> char '(')
92 whitespace
93 listing <-
94 choice
95 [ const Var.openListing <$> string ".."
96 , Var.Listing <$> commaSep1 item <*> return False
97 ]
98 whitespace
99 char ')'
100 return listing
103value :: IParser Var.Value
104value =
105 val <|> tipe <?> "a value or type to expose"
106 where
107 val =
108 Var.Value <$> (lowVar <|> parens symOp)
110 tipe =
111 do name <- capVar
112 maybeCtors <- optionMaybe (listing capVar)
113 case maybeCtors of
114 Nothing -> return (Var.Alias name)
115 Just ctors -> return (Var.Union name ctors)