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