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