on dc356df help sign in
elk/src/Parse/Module.hs
297 lines 7.0 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Parse.Module
4 ( module_
5 , chompImports
6 , freshLine
7 )
8 where
11import qualified Data.ByteString as B
12import Data.Text (Text)
14import qualified AST.Source as Src
15import qualified Elm.Compiler.Imports as Imports
16import qualified Elm.Name as N
17import qualified Elm.Package as Pkg
18import Parse.Primitives (Parser, oneOf)
19import qualified Parse.Primitives as P
20import qualified Parse.Primitives.Keyword as Keyword
21import qualified Parse.Primitives.Symbol as Symbol
22import qualified Parse.Primitives.Variable as Var
23import qualified Parse.Primitives.Whitespace as W
24import qualified Reporting.Annotation as A
25import qualified Reporting.Error.Syntax as E
26import qualified Reporting.Region as R
30-- MODULE
33module_ :: Pkg.Name -> Parser decls -> Parser (Src.Module decls)
34module_ pkgName chompDecls =
35 do freshLine
36 header <- oneOf [ Just <$> chompHeader, return Nothing ]
37 imports <- Imports.addDefaults pkgName <$> chompImports []
38 decls <- chompDecls
39 return (Src.Module header imports decls)
42chompHeader :: Parser Src.Header
43chompHeader =
44 do start <- P.getPosition
45 P.pushContext start E.Module
46 (name, effects) <- chompNameAndEffects
47 P.hint E.Exposing $ Keyword.exposing_
48 P.spaces
49 exports <- exposing
50 P.popContext ()
51 docs <- maybeDocComment
52 return (Src.Header name effects exports docs)
56-- MODULE NAME
57--
58-- module MyThing
59-- port module MyThing
60-- effect module MyThing where { command = MyCmd }
61--
62chompNameAndEffects :: Parser (N.Name, Src.Effects)
63chompNameAndEffects =
64 oneOf
65 [
66 do Keyword.module_
67 P.spaces
68 name <- Var.moduleName
69 P.spaces
70 return ( name, Src.NoEffects )
71 ,
72 do start <- P.getPosition
73 Keyword.port_
74 P.spaces
75 Keyword.module_
76 end <- P.getPosition
77 P.spaces
78 name <- Var.moduleName
79 P.spaces
80 return ( name, Src.Ports (R.Region start end) )
81 ,
82 do start <- P.getPosition
83 Keyword.effect_
84 P.spaces
85 Keyword.module_
86 end <- P.getPosition
87 P.spaces
88 name <- Var.moduleName
89 P.spaces
90 manager <- chompManager
91 return ( name, Src.Manager (R.Region start end) manager )
92 ]
96-- MANAGER
97--
98-- where { command = MyCmd }
99-- where { subscription = MySub }
100-- where { command = MyCmd, subscription = MySub }
101--
102chompManager :: Parser Src.Manager
103chompManager =
104 do Keyword.where_
105 P.spaces
106 Symbol.leftCurly
107 P.spaces
108 oneOf
109 [ do cmd <- chompCommand
110 P.spaces
111 oneOf
112 [ do Symbol.rightCurly
113 P.spaces
114 return (Src.Cmd cmd)
115 , do Symbol.comma
116 P.spaces
117 sub <- chompSubscription
118 P.spaces
119 Symbol.rightCurly
120 P.spaces
121 return (Src.Fx cmd sub)
122 ]
123 , do sub <- chompSubscription
124 P.spaces
125 oneOf
126 [ do Symbol.rightCurly
127 P.spaces
128 return (Src.Sub sub)
129 , do Symbol.comma
130 P.spaces
131 cmd <- chompCommand
132 P.spaces
133 Symbol.rightCurly
134 P.spaces
135 return (Src.Fx cmd sub)
136 ]
137 ]
140chompCommand :: Parser (A.Located Text)
141chompCommand =
142 do Keyword.command_
143 P.spaces
144 Symbol.equals
145 P.spaces
146 P.addLocation Var.upper
149chompSubscription :: Parser (A.Located Text)
150chompSubscription =
151 do Keyword.subscription_
152 P.spaces
153 Symbol.equals
154 P.spaces
155 P.addLocation Var.upper
159-- DOC COMMENTS
162maybeDocComment :: Parser (Maybe (A.Located B.ByteString))
163maybeDocComment =
164 do freshLine
165 newStart <- P.getPosition
166 oneOf
167 [ do doc <- W.docComment
168 end <- P.getPosition
169 freshLine
170 return (Just (A.at newStart end doc))
171 , return Nothing
172 ]
176-- IMPORTS
179chompImports :: [Src.Import] -> Parser [Src.Import]
180chompImports imports =
181 oneOf
182 [ do start <- P.getPosition
183 Keyword.import_
184 P.pushContext start E.Import
185 P.spaces
186 name <- P.addLocation Var.moduleName
187 pos <- W.whitespace
188 oneOf
189 [ do P.checkFreshLine pos
190 P.popContext ()
191 chompImports $
192 Src.Import name Nothing (Src.Explicit []) : imports
193 , do P.checkSpace pos
194 oneOf
195 [ chompAs name imports
196 , chompExposing name Nothing imports
197 ]
198 ]
199 , return (reverse imports)
200 ]
203chompAs :: A.Located Text -> [Src.Import] -> Parser [Src.Import]
204chompAs name imports =
205 do Keyword.as_
206 P.spaces
207 alias <- Var.upper
208 pos <- W.whitespace
209 oneOf
210 [ do P.checkFreshLine pos
211 P.popContext ()
212 chompImports $
213 Src.Import name (Just alias) (Src.Explicit []) : imports
214 , do P.checkSpace pos
215 chompExposing name (Just alias) imports
216 ]
219chompExposing :: A.Located Text -> Maybe Text -> [Src.Import] -> Parser [Src.Import]
220chompExposing name maybeAlias imports =
221 do Keyword.exposing_
222 P.spaces
223 exposed <- exposing
224 freshLine
225 P.popContext ()
226 chompImports $
227 Src.Import name maybeAlias exposed : imports
231-- LISTING
234exposing :: Parser Src.Exposing
235exposing =
236 P.hint E.Listing $
237 do Symbol.leftParen
238 P.spaces
239 oneOf
240 [ do Symbol.doubleDot
241 P.spaces
242 Symbol.rightParen
243 return Src.Open
244 , do entry <- P.addLocation chompEntry
245 P.spaces
246 exposingHelp [entry]
247 ]
250exposingHelp :: [A.Located Src.Exposed] -> Parser Src.Exposing
251exposingHelp revEntries =
252 oneOf
253 [ do Symbol.comma
254 P.spaces
255 entry <- P.addLocation chompEntry
256 P.spaces
257 exposingHelp (entry:revEntries)
258 , do Symbol.rightParen
259 return (Src.Explicit (reverse revEntries))
260 ]
263chompEntry :: Parser Src.Exposed
264chompEntry =
265 oneOf
266 [ Src.Lower <$> Var.lower
267 , do Symbol.leftParen
268 op <- Symbol.binop
269 Symbol.rightParen
270 return (Src.Operator op)
271 , do name <- Var.upper
272 P.spaces
273 Src.Upper name <$> privacy
274 ]
277privacy :: Parser Src.Privacy
278privacy =
279 oneOf
280 [ do Symbol.leftParen
281 P.spaces
282 Symbol.doubleDot
283 P.spaces
284 Symbol.rightParen
285 return Src.Public
286 , return Src.Private
287 ]
291-- FRESH LINES
294freshLine :: Parser ()
295freshLine =
296 P.checkFreshLine =<< W.whitespace