2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[ParseUtils]{Help the interface parser}
7 #include "HsVersions.h"
9 module ParseUtils where
13 import HsSyn -- quite a bit of stuff
14 import RdrHsSyn -- oodles of synonyms
15 import HsPragmas ( noDataPragmas, noClassPragmas, noClassOpPragmas,
19 import ErrUtils ( Error(..) )
20 import FiniteMap ( unitFM, listToFM, lookupFM, plusFM, FiniteMap )
21 import Maybes ( maybeToBool, MaybeErr(..) )
22 import Name ( isLexConId, isLexVarId, isLexConSym,
24 RdrName(..){-instance Outputable:ToDo:rm-}
26 import PprStyle ( PprStyle(..) ) -- ToDo: rm debugging
27 import PrelMods ( fromPrelude )
28 import Pretty ( ppCat, ppPStr, ppInt, ppShow, ppStr )
29 import SrcLoc ( mkIfaceSrcLoc )
30 import Util ( startsWith, isIn, panic, assertPanic )
34 type LocalVersionsMap = FiniteMap FAST_STRING Version
35 type ExportsMap = FiniteMap FAST_STRING (RdrName, ExportFlag)
36 type FixitiesMap = FiniteMap FAST_STRING RdrNameFixityDecl
37 type LocalTyDefsMap = FiniteMap FAST_STRING RdrIfaceDecl -- for TyCon/Class
38 type LocalValDefsMap = FiniteMap FAST_STRING RdrIfaceDecl -- for values incl DataCon
39 type LocalPragmasMap = FiniteMap FAST_STRING PragmaStuff
41 type PragmaStuff = String
46 Version -- Module version number
47 (Maybe Version) -- Source version number
48 LocalVersionsMap -- Local version numbers
49 ExportsMap -- Exported names
50 (Bag Module) -- Special instance modules
51 FixitiesMap -- fixities of local things
52 LocalTyDefsMap -- Local TyCon/Class names defined
53 LocalValDefsMap -- Local value names defined
54 (Bag RdrIfaceInst)-- Local instance declarations
55 LocalPragmasMap -- Pragmas for local names
57 -----------------------------------------------------------------
60 = TypeSig RdrName SrcLoc RdrNameTyDecl
61 | NewTypeSig RdrName RdrName SrcLoc RdrNameTyDecl
62 | DataSig RdrName [RdrName] [RdrName] SrcLoc RdrNameTyDecl
63 | ClassSig RdrName [RdrName] SrcLoc RdrNameClassDecl
64 | ValSig RdrName SrcLoc RdrNamePolyType
67 = InstSig RdrName RdrName SrcLoc RdrNameInstDecl
71 -----------------------------------------------------------------
73 = ITinterface -- keywords
90 | ITbang -- magic symbols
106 | ITinteger Integer -- numbers and names
107 | ITvarid FAST_STRING
108 | ITconid FAST_STRING
109 | ITvarsym FAST_STRING
110 | ITconsym FAST_STRING
115 deriving Text -- debugging
117 instance Text RdrName where -- debugging
118 showsPrec _ rn = showString (ppShow 80 (ppr PprDebug rn))
120 -----------------------------------------------------------------
121 de_qual (Unqual n) = n
122 de_qual (Qual _ n) = n
124 en_mono :: FAST_STRING -> RdrNameMonoType
125 en_mono tv = MonoTyVar (Unqual tv)
127 type2context (MonoTupleTy tys) = map type2class_assertion tys
128 type2context other_ty = [ type2class_assertion other_ty ]
130 type2class_assertion (MonoTyApp clas [MonoTyVar tyvar]) = (clas, tyvar)
131 type2class_assertion _ = panic "type2class_assertion: bad format"
133 -----------------------------------------------------------------
134 mk_type :: (RdrName, [FAST_STRING])
138 mk_type (qtycon, tyvars) ty
140 tycon = de_qual qtycon
141 qtyvars = map Unqual tyvars
143 unitFM tycon (TypeSig qtycon mkIfaceSrcLoc (
144 TySynonym qtycon qtyvars ty mkIfaceSrcLoc))
146 mk_data :: RdrNameContext
147 -> (RdrName, [FAST_STRING])
148 -> [(RdrName, RdrNameConDecl)]
149 -> (LocalTyDefsMap, LocalValDefsMap)
151 mk_data ctxt (qtycon, tyvars) names_and_constrs
153 (qconnames, constrs) = unzip names_and_constrs
154 qfieldnames = [] -- ToDo ...
155 tycon = de_qual qtycon
156 connames = map de_qual qconnames
157 fieldnames = map de_qual qfieldnames
158 qtyvars = map Unqual tyvars
160 decl = DataSig qtycon qconnames qfieldnames mkIfaceSrcLoc (
161 TyData ctxt qtycon qtyvars constrs Nothing noDataPragmas mkIfaceSrcLoc)
163 (unitFM tycon decl, listToFM [(c,decl) | c <- connames]
165 listToFM [(f,decl) | f <- fieldnames])
167 mk_new :: RdrNameContext
168 -> (RdrName, [FAST_STRING])
169 -> (RdrName, RdrNameMonoType)
170 -> (LocalTyDefsMap, LocalValDefsMap)
172 mk_new ctxt (qtycon, tyvars) (qconname, ty)
174 tycon = de_qual qtycon
175 conname = de_qual qconname
176 qtyvars = map Unqual tyvars
177 constr = NewConDecl qconname ty mkIfaceSrcLoc
179 decl = NewTypeSig qtycon qconname mkIfaceSrcLoc (
180 TyNew ctxt qtycon qtyvars [constr] Nothing noDataPragmas mkIfaceSrcLoc)
182 (unitFM tycon decl, unitFM conname decl)
184 mk_class :: RdrNameContext
185 -> (RdrName, RdrName)
186 -> [(FAST_STRING, RdrNameSig)]
187 -> (LocalTyDefsMap, LocalValDefsMap)
189 mk_class ctxt (qclas, tyvar) ops_and_sigs
190 = case (unzip ops_and_sigs) of { (opnames, sigs) ->
192 qopnames = map Unqual opnames
194 op_sigs = map opify sigs
196 decl = ClassSig qclas qopnames mkIfaceSrcLoc (
197 ClassDecl ctxt qclas tyvar op_sigs EmptyMonoBinds noClassPragmas mkIfaceSrcLoc)
199 (unitFM clas decl, listToFM [(o,decl) | o <- opnames]) }
201 opify (Sig f ty _ loc) = ClassOpSig f ty noClassOpPragmas loc
203 mk_inst :: RdrNameContext
205 -> RdrNameMonoType -- fish the tycon out yourself...
208 mk_inst ctxt clas mono_ty
209 = InstSig clas (tycon_name mono_ty) mkIfaceSrcLoc (
210 InstDecl clas (HsPreForAllTy ctxt mono_ty)
211 EmptyMonoBinds False Nothing{-lying-} [{-sigs-}]
212 noInstancePragmas mkIfaceSrcLoc)
214 tycon_name (MonoTyApp tc _) = tc
215 tycon_name (MonoListTy _) = Unqual SLIT("[]")
216 tycon_name (MonoFunTy _ _) = Unqual SLIT("->")
217 tycon_name (MonoTupleTy ts) = Unqual (mkTupNameStr (length ts))
219 -----------------------------------------------------------------
220 lexIface :: String -> [IfaceToken]
226 -- whitespace and comments
227 ' ' : cs -> lexIface cs
228 '\t' : cs -> lexIface cs
229 '\n' : cs -> lexIface cs
230 '-' : '-' : cs -> lex_comment cs
231 '{' : '-' : cs -> lex_nested_comment 1{-one seen-} cs
233 '(' : '.' : '.' : ')' : cs -> ITdotdot : lexIface cs
234 '(' : cs -> IToparen : lexIface cs
235 ')' : cs -> ITcparen : lexIface cs
236 '[' : cs -> ITobrack : lexIface cs
237 ']' : cs -> ITcbrack : lexIface cs
238 '{' : cs -> ITocurly : lexIface cs
239 '}' : cs -> ITccurly : lexIface cs
240 ',' : cs -> ITcomma : lexIface cs
241 ';' : cs -> ITsemi : lexIface cs
242 '`' : cs -> ITbquote : lexIface cs
244 '_' : cs -> lex_name Nothing is_var_sym str
245 c : cs | isUpper c -> lex_word str -- don't know if "Module." on front or not
246 | isDigit c -> lex_num str
247 | isAlpha c -> lex_name Nothing is_var_sym str
248 | is_sym_sym c -> lex_name Nothing is_sym_sym str
250 other -> error ("lexing:"++other)
253 = case (span ((/=) '\n') str) of { (junk, rest) ->
257 lex_nested_comment lvl [] = error "EOF in nested comment in interface"
258 lex_nested_comment lvl str
260 '{' : '-' : xs -> lex_nested_comment (lvl+1) xs
261 '-' : '}' : xs -> if lvl == 1
263 else lex_nested_comment (lvl-1) xs
264 _ : xs -> lex_nested_comment lvl xs
268 = case (span isDigit str) of { (num, rest) ->
269 ITinteger (read num) : lexIface rest }
272 is_var_sym '_' = True
273 is_var_sym c = isAlphanum c
275 is_sym_sym c = c `elem` ":!#$%&*+./<=>?@\\^|-~" -- ToDo: add ISOgraphic
278 lex_word str@(c:cs) -- we know we have a capital letter to start
279 = -- we first try for "<module>." on the front...
280 case (module_dot str) of
281 Nothing -> lex_name Nothing is_var_sym str
282 Just (m,rest) -> lex_name (Just m) (in_the_club rest) rest
284 in_the_club [] = panic "lex_word:in_the_club"
285 in_the_club (c:_) | isAlpha c = is_var_sym
286 | is_sym_sym c = is_sym_sym
287 | otherwise = panic ("lex_word:in_the_club="++[c])
290 = if not (isUpper c) then
293 case (span is_var_sym cs) of { (word, rest) ->
296 (r:rs) | r == '.' -> Just (_PK_ (c:word), rs)
300 lex_name module_dot in_the_club str
301 = case (span in_the_club str) of { (word, rest) ->
302 case (lookupFM keywordsFM word) of
303 Just xx -> ASSERT( not (maybeToBool module_dot) )
307 f = head word -- first char
312 categ n (ITconid n) (ITvarid n) (ITconsym n) (ITvarsym n)
315 q = if fromPrelude m then Unqual n else Qual m n
317 categ n (ITqconid q) (ITqvarid q) (ITqconsym q) (ITqvarsym q)
322 categ n conid varid consym varsym
323 = if isLexConId n then conid
324 else if isLexVarId n then varid
325 else if isLexConSym n then consym
329 keywordsFM :: FiniteMap String IfaceToken
330 keywordsFM = listToFM [
331 ("interface", ITinterface)
333 ,("__versions__", ITversions)
334 ,("__exports__", ITexports)
335 ,("__instance_modules__",ITinstance_modules)
336 ,("__instances__", ITinstances)
337 ,("__fixities__", ITfixities)
338 ,("__declarations__", ITdeclarations)
339 ,("__pragmas__", ITpragmas)
343 ,("newtype", ITnewtype)
346 ,("instance", ITinstance)
347 ,("infixl", ITinfixl)
348 ,("infixr", ITinfixr)
359 -----------------------------------------------------------------
360 type IfM a = MaybeErr a Error
362 returnIf :: a -> IfM a
363 thenIf :: IfM a -> (a -> IfM b) -> IfM b
364 happyError :: Int -> [IfaceToken] -> IfM a
366 returnIf a = Succeeded a
368 thenIf (Succeeded a) k = k a
369 thenIf (Failed err) _ = Failed err
371 happyError ln toks = Failed (ifaceParseErr ln toks)
372 -----------------------------------------------------------------
374 ifaceParseErr ln toks sty
375 = ppCat [ppPStr SLIT("Interface-file parse error: line"), ppInt ln, ppStr "toks=", ppStr (show toks)]