41a18a5c3084aedeebf89b832c2114bda9e2d43f
[ghc-hetmet.git] / utils / ext-core / ParsecParser.hs
1 {-# OPTIONS -Wall -fno-warn-missing-signatures #-}
2
3 module ParsecParser (parseCore) where
4
5 import Core
6 import ParseGlue
7 import Check
8 import PrimCoercions
9
10 import Text.ParserCombinators.Parsec
11 import qualified Text.ParserCombinators.Parsec.Token as P
12 import Text.ParserCombinators.Parsec.Language
13 import Data.Char
14 import Data.Ratio
15
16 parseCore :: FilePath -> IO (Either ParseError Module)
17 parseCore = parseFromFile coreModule
18
19 coreModule :: Parser Module
20 coreModule = do
21    whiteSpace
22    reserved "module"
23    mName      <- coreModuleName
24    whiteSpace
25    tdefs      <- option [] coreTdefs
26    vdefGroups <- coreVdefGroups
27    eof
28    return $ Module mName tdefs vdefGroups
29
30 coreModuleName :: Parser AnMname
31 coreModuleName = do
32    pkgName      <- corePackageName
33    char ':'
34    (modHierarchy,baseName) <- coreHierModuleNames
35    return $ M (pkgName, modHierarchy, baseName)
36
37 corePackageName :: Parser Pname
38 -- Package names can be lowercase or uppercase!
39 corePackageName = (identifier <|> upperName) >>= (return . P)
40
41 coreHierModuleNames :: Parser ([Id], Id)
42 coreHierModuleNames = do
43    parentName <- upperName
44    return $ splitModuleName parentName
45
46 upperName :: Parser Id
47 upperName = do
48    firstChar <- upper
49    rest <- many (identLetter extCoreDef)
50    return $ firstChar:rest
51
52 coreTdefs :: Parser [Tdef]
53 coreTdefs = many coreTdef 
54
55 coreTdef :: Parser Tdef
56 coreTdef = withSemi (try (try coreDataDecl <|> try coreNewtypeDecl))
57             
58
59 withSemi p = try p `withTerminator` ";"
60
61 withTerminator p term = do
62    x <- try p
63    try $ symbol term
64    return x
65
66 coreDataDecl :: Parser Tdef
67 coreDataDecl = do
68   reserved "data"
69   tyCon  <- coreQualifiedCon
70   whiteSpace -- important
71   tBinds <- coreTbinds
72   whiteSpace
73   symbol "="
74   whiteSpace
75   cDefs  <- braces coreCdefs
76   return $ Data tyCon tBinds cDefs
77
78 coreNewtypeDecl :: Parser Tdef
79 coreNewtypeDecl = do
80   reserved "newtype"
81   tyCon  <- coreQualifiedCon
82   whiteSpace
83   coercionName <- coreQualifiedCon
84   whiteSpace
85   tBinds <- coreTbinds
86   tyRep  <- try coreTRep
87   return $ Newtype tyCon coercionName tBinds tyRep
88
89 coreQualifiedCon :: Parser (Mname, Id)
90 coreQualifiedCon = coreQualifiedGen upperName
91  
92 coreQualifiedName = coreQualifiedGen identifier
93
94 coreQualifiedGen :: Parser String -> Parser (Mname, Id) 
95 coreQualifiedGen p = (try (do
96   packageIdOrVarName <- corePackageName
97   maybeRest <- optionMaybe (char ':' >> coreHierModuleNames)
98   case maybeRest of
99                -- unqualified id, so backtrack
100     Nothing -> pzero
101                -- qualified name, so look for the id part
102     Just (modHierarchy, baseName) -> do
103                char '.'
104                theId <- p
105                return
106                  (Just $ M (packageIdOrVarName, modHierarchy, baseName),
107                   theId))) <|> 
108    -- unqualified name
109    (p >>= (\ res -> return (Nothing, res)))
110
111 coreTbinds :: Parser [Tbind]
112 coreTbinds = many coreTbind 
113
114 coreTbindsGen :: CharParser () String -> Parser [Tbind]
115 -- The "try" here is important. Otherwise, when parsing:
116 -- "Node (^base:DataziTuple.Z3T)" (a cdef), we commit to
117 -- parsing (^base...) as a tbind rather than a type.
118 coreTbindsGen separator = many (try $ coreTbindGen separator)
119
120 coreTbind :: Parser Tbind
121 coreTbind = coreTbindGen whiteSpace
122
123 coreTbindGen :: CharParser () a -> Parser Tbind
124 coreTbindGen sep = (parens (do
125                      sep
126                      tyVar <- identifier
127                      kind <- symbol "::" >> coreKind
128                      return (tyVar, kind))) <|>
129                     (sep >> identifier >>= (return . (\ tv -> (tv,Klifted))))
130
131 coreCdefs :: Parser [Cdef]
132 coreCdefs = sepBy1 coreCdef (symbol ";")
133
134 coreCdef :: Parser Cdef
135 coreCdef = do
136   dataConName <- coreQualifiedCon
137   whiteSpace -- important!
138   tBinds      <- try $ coreTbindsGen (symbol "@")
139   -- This should be equivalent to (many coreAty)
140   -- But it isn't. WHY??
141   tys         <- sepBy coreAtySaturated whiteSpace
142   return $ Constr dataConName tBinds tys
143
144 coreTRep :: Parser Ty
145 -- note that the "=" is inside here since if there's
146 -- no rhs for the newtype, there's no "="
147 coreTRep = symbol "=" >> try coreType
148
149 coreType :: Parser Ty
150 coreType = coreForallTy <|> (do
151              hd <- coreBty
152              -- whiteSpace is important!
153              whiteSpace
154              -- This says: If there is at least one ("-> ty"..) thing,
155              -- use it. If not, don't consume any input.
156              maybeRest <- option [] (many1 (symbol "->" >> coreType))
157              return $ case maybeRest of
158                          [] -> hd
159                          stuff -> foldl Tapp (Tcon tcArrow) (hd:stuff))
160
161 coreBty :: Parser Ty
162 coreBty = do
163   hd <- coreAty
164                          -- The "try" is necessary:
165                          -- otherwise, parsing "T " fails rather
166                          -- than returning "T".
167   maybeRest <- option [] (many1 (try (whiteSpace >> coreAtySaturated)))
168   return $ (case hd of
169              -- so I'm not sure I like this... it's basically doing
170              -- typechecking (kind-checking?) in the parser.
171              -- However, the type syntax as defined in Core.hs sort of
172              -- forces it.
173              ATy t     -> foldl Tapp t maybeRest
174              Trans k   -> app k 2 maybeRest "trans"
175              Sym k     -> app k 1 maybeRest "sym"
176              Unsafe k  -> app k 2 maybeRest "unsafe"
177              LeftCo k  -> app k 1 maybeRest "left"
178              RightCo k -> app k 1 maybeRest "right"
179              InstCo k  -> app k 2 maybeRest "inst")
180                  where app k arity args _ | length args == arity = k args
181                        app _ _ args err = 
182                            primCoercionError (err ++ 
183                              ("Args were: " ++ show args))
184
185 coreAtySaturated :: Parser Ty
186 coreAtySaturated = do
187    t <- coreAty
188    case t of
189      ATy ty -> return ty
190      _     -> unexpected "coercion ty"
191
192 coreAty :: Parser ATyOp
193 coreAty = try coreTcon <|> ((try coreTvar <|> parens coreType)
194                              >>= return . ATy)
195 coreTvar :: Parser Ty
196 coreTvar = try identifier >>= (return . Tvar)
197
198 coreTcon :: Parser ATyOp
199 -- TODO: Change the grammar
200 -- A Tcon can be an uppercase type constructor
201 -- or a lowercase (always qualified) coercion variable
202 coreTcon =  
203          -- Special case is first so that (CoUnsafe .. ..) gets parsed as
204          -- a prim. coercion app and not a Tcon app.
205          -- But the whole thing is so bogus.
206         try (do
207                                     -- the "try"s are crucial; they force
208                                     -- backtracking
209            maybeCoercion <- choice [try symCo, try transCo, try unsafeCo,
210                                     try instCo, try leftCo, rightCo]
211            return $ case maybeCoercion of
212               TransC  -> Trans (\ [x,y] -> TransCoercion x y)
213               SymC    -> Sym (\ [x] -> SymCoercion x)
214               UnsafeC -> Unsafe (\ [x,y] -> UnsafeCoercion x y)
215               LeftC   -> LeftCo (\ [x] -> LeftCoercion x)
216               RightC  -> RightCo (\ [x] -> RightCoercion x)
217               InstC   -> InstCo (\ [x,y] -> InstCoercion x y))
218     <|> (coreQualifiedCon >>= (return . ATy . Tcon))
219
220 data CoercionTy = TransC | InstC | SymC | UnsafeC | LeftC | RightC
221
222 symCo, transCo, unsafeCo, instCo, leftCo, rightCo :: Parser CoercionTy
223 symCo    = string "%sym"    >> return SymC
224 transCo  = string "%trans"  >> return TransC
225 unsafeCo = string "%unsafe" >> return UnsafeC
226 leftCo   = string "%left"   >> return LeftC
227 rightCo  = string "%right"  >> return RightC
228 instCo   = string "%inst"   >> return InstC
229
230 coreForallTy :: Parser Ty
231 coreForallTy = do
232   reserved "forall"
233   tBinds <- many1 coreTbind
234   symbol "."
235   bodyTy <- coreType
236   return $ foldr Tforall bodyTy tBinds
237
238 -- TODO: similar to coreType. should refactor
239 coreKind :: Parser Kind
240 coreKind = do
241   hd <- coreAtomicKind 
242   maybeRest <- option [] (many1 (symbol "->" >> coreKind))
243   return $ foldl Karrow hd maybeRest
244
245 coreAtomicKind = try liftedKind <|> try unliftedKind 
246        <|> try openKind <|> try (do
247                     (from,to) <- parens equalityKind
248                     return $ Keq from to)
249        <|> try (parens coreKind)
250
251 liftedKind = do
252   symbol "*"
253   return Klifted
254
255 unliftedKind = do
256   symbol "#"
257   return Kunlifted
258
259 openKind = do
260   symbol "?"
261   return Kopen
262
263 equalityKind = do
264   ty1 <- coreBty
265   symbol ":=:"
266   ty2 <- coreBty
267   return (ty1, ty2)
268
269 -- Only used internally within the parser:
270 -- represents either a Tcon, or a continuation
271 -- for a primitive coercion
272 data ATyOp = 
273    ATy Ty
274  | Trans ([Ty] -> Ty)
275  | Sym ([Ty] -> Ty)
276  | Unsafe ([Ty] -> Ty)
277  | LeftCo ([Ty] -> Ty)
278  | RightCo ([Ty] -> Ty)
279  | InstCo ([Ty] -> Ty)
280
281 coreVdefGroups :: Parser [Vdefg]
282 coreVdefGroups = option [] (do
283   theFirstVdef <- coreVdefg
284   symbol ";"
285   others <- coreVdefGroups
286   return $ theFirstVdef:others)
287
288 coreVdefg :: Parser Vdefg
289 coreVdefg = coreRecVdef <|> coreNonrecVdef
290
291 coreRecVdef = do
292   reserved "rec"
293   braces (sepBy1 coreVdef (symbol ";")) >>= (return . Rec)
294
295 coreNonrecVdef = coreVdef >>= (return . Nonrec)
296
297 coreVdef = do
298   (vdefLhs, vdefTy) <- try topVbind <|> (do
299                         (v, ty) <- lambdaBind
300                         return (unqual v, ty))
301   whiteSpace
302   symbol "="
303   whiteSpace
304   vdefRhs  <- coreFullExp
305   return $ Vdef (vdefLhs, vdefTy, vdefRhs) 
306
307 coreAtomicExp :: Parser Exp
308 coreAtomicExp = do
309 -- For stupid reasons, the whiteSpace is necessary.
310 -- Without it, (pt coreAppExp "w a:B.C ") doesn't work.
311   whiteSpace
312   res <- choice [try coreDconOrVar,
313                     try coreLit,
314                     parens coreFullExp ]
315   whiteSpace
316   return res
317
318 coreFullExp = (choice [coreLam, coreLet,
319   coreCase, coreCast, coreNote, coreExternal, coreLabel]) <|> (try coreAppExp)
320 -- The "try" is necessary so that we backtrack
321 -- when we see a var (that is not an app)
322     <|> coreAtomicExp
323
324 coreAppExp = do
325 -- notes:
326 -- it's important to have a separate coreAtomicExp (that any app exp
327 -- begins with) and to define the args in terms of many1.
328 -- previously, coreAppExp could parse either an atomic exp (an app with
329 -- 0 arguments) or an app with >= 1 arguments, but that led to ambiguity.
330     oper <- try coreAtomicExp
331     whiteSpace
332     args <- many1 (whiteSpace >> ((coreAtomicExp >>= (return . Left)) <|>
333              -- note this MUST be coreAty, not coreType, because otherwise:
334              -- "A @ B c" gets parsed as "A @ (B c)"
335              ((symbol "@" >> coreAtySaturated) >>= (return . Right))))
336     return $ foldl (\ op ->
337                      either (App op) (Appt op)) oper args
338
339 coreDconOrVar = do
340   theThing <- coreQualifiedGen (try upperName <|> identifier)
341   return $ case theThing of
342     -- note that data constructors must be qualified
343     (Just _, idItself) | isUpper (head idItself)
344       -> Dcon theThing
345     _ -> Var theThing
346
347 coreLit :: Parser Exp
348 coreLit = parens (coreLiteral >>= (return . Lit))
349
350 coreLiteral :: Parser Lit
351 coreLiteral = do
352   l <- try aLit
353   symbol "::"
354   t <- coreType
355   return $ Literal l t
356
357 coreLam = do
358   symbol "\\"
359   binds <- coreLambdaBinds
360   symbol "->"
361   body <- coreFullExp
362   return $ foldr Lam body binds
363 coreLet = do
364   reserved "let"
365   vdefg <- coreVdefg
366   whiteSpace
367   reserved "in"
368   body <- coreFullExp
369   return $ Let vdefg body 
370 coreCase = do
371   reserved "case"
372   ty <- coreAtySaturated
373   scrut <- coreAtomicExp
374   reserved "of"
375   vBind <- parens lambdaBind
376   alts <- coreAlts
377   return $ Case scrut vBind ty alts
378 coreCast = do
379   reserved "cast"
380   whiteSpace
381 -- The parens are CRUCIAL, o/w it's ambiguous
382   body <- try (parens coreFullExp)
383   whiteSpace
384   ty <- try coreAtySaturated
385   return $ Cast body ty
386 coreNote = do
387   reserved "note"
388   s <- stringLiteral
389   e <- coreFullExp
390   return $ Note s e
391 coreExternal = (do
392   reserved "external"
393   -- TODO: This isn't in the grammar, but GHC
394   -- always prints "external ccall". investigate...
395   symbol "ccall"
396   s <- stringLiteral
397   t <- coreAtySaturated
398   return $ External s t) <|>
399     -- TODO: I don't really understand what this does
400                 (do
401     reserved "dynexternal"
402     symbol "ccall"
403     t <- coreAtySaturated
404     return $ External "[dynamic]" t)
405 coreLabel = do
406 -- TODO: Totally punting this, but it needs to go in the grammar
407 -- or not at all
408   reserved "label"
409   s <- stringLiteral
410   return $ External s tAddrzh
411
412 coreLambdaBinds = many1 coreBind
413
414 coreBind = coreTbinding <|> coreVbind
415
416 coreTbinding = try coreAtTbind >>= (return . Tb)
417 coreVbind = parens (lambdaBind >>= (return . Vb))
418
419 coreAtTbind = (symbol "@") >> coreTbind
420
421 topVbind :: Parser (Qual Var, Ty)
422 topVbind   = aCoreVbind coreQualifiedName
423 lambdaBind :: Parser (Var, Ty)
424 lambdaBind = aCoreVbind identifier
425
426 aCoreVbind idP =  do
427   nm <- idP
428   symbol "::"
429   t <- coreType
430   return (nm, t)
431
432
433 aLit :: Parser CoreLit
434 aLit = intOrRatLit <|> charLit <|> stringLit
435
436 intOrRatLit :: Parser CoreLit
437 intOrRatLit = do
438  -- Int and lit combined into one to avoid ambiguity.
439  -- Argh....
440   lhs <- intLit
441   maybeRhs <- optionMaybe (symbol "%" >> anIntLit)
442   case maybeRhs of
443     Nothing  -> return $ Lint lhs
444     Just rhs -> return $ Lrational (lhs % rhs)
445
446 intLit :: Parser Integer
447 intLit = anIntLit <|> parens anIntLit
448
449 anIntLit :: Parser Integer
450 anIntLit = do
451   sign <- option 1 (symbol "-" >> return (-1)) 
452   n <- natural
453   return (sign * n)
454
455 charLit :: Parser CoreLit
456 charLit = charLiteral >>= (return . Lchar)
457  -- make sure this is right
458    
459 stringLit :: Parser CoreLit
460 stringLit = stringLiteral >>= (return . Lstring)
461  -- make sure this is right
462
463 coreAlts :: Parser [Alt]
464 coreAlts = braces $ sepBy1 coreAlt (symbol ";")
465
466 coreAlt :: Parser Alt
467 coreAlt = conAlt <|> litAlt <|> defaultAlt
468
469 conAlt :: Parser Alt
470 conAlt = do
471   conName <- coreQualifiedCon
472   tBinds  <- many (parens coreAtTbind)
473   whiteSpace -- necessary b/c otherwise we parse the next list as empty
474   vBinds  <- many (parens lambdaBind)
475   whiteSpace
476   try (symbol "->")
477   rhs     <- try coreFullExp
478   return $ Acon conName tBinds vBinds rhs
479
480 litAlt :: Parser Alt
481 litAlt = do
482   l <- parens coreLiteral
483   symbol "->"
484   rhs <- coreFullExp
485   return $ Alit l rhs
486
487 defaultAlt :: Parser Alt
488 defaultAlt = do
489   reserved "_"
490   symbol "->"
491   rhs <- coreFullExp
492   return $ Adefault rhs
493 ----------------
494 extCore = P.makeTokenParser extCoreDef
495
496 parens          = P.parens extCore    
497 braces          = P.braces extCore    
498 -- newlines are allowed anywhere
499 whiteSpace      = P.whiteSpace extCore <|> (newline >> return ())
500 symbol          = P.symbol extCore    
501 identifier      = P.identifier extCore    
502 -- Keywords all begin with '%'
503 reserved  s     = P.reserved extCore ('%':s) 
504 natural         = P.natural extCore    
505 charLiteral     = P.charLiteral extCore    
506 stringLiteral   = P.stringLiteral extCore    
507
508 -- dodgy since Core doesn't really allow comments,
509 -- but we'll pretend...
510 extCoreDef = LanguageDef { 
511       commentStart    = "{-"
512     , commentEnd      = "-}"
513     , commentLine     = "--"
514     , nestedComments  = True
515     , identStart      = lower
516     , identLetter     = lower <|> upper <|> digit <|> (char '\'')
517     , opStart         = opLetter extCoreDef
518     , opLetter        = oneOf ";=@:\\%_.*#?%"
519     , reservedNames   = map ('%' :)
520                           ["module", "data", "newtype", "rec",
521                            "let", "in", "case", "of", "cast",
522                            "note", "external", "forall"]
523     , reservedOpNames = [";", "=", "@", "::", "\\", "%_",
524                           ".", "*", "#", "?"]
525     , caseSensitive   = True
526     }       
527
528 {-
529 -- Stuff to help with testing in ghci.
530 pTest (Left a) = error (show a)
531 pTest (Right t) = print t
532
533 pTest1 :: Show a => CharParser () a -> String -> IO ()
534 pTest1 pr s = do
535   let res = parse pr "" s
536   pTest res
537
538 pt :: Show a => CharParser () a -> String -> IO ()
539 pt pr s = do
540   x <- parseTest pr s
541   print x
542
543 try_ = try
544 many_ = many
545 option_ = option
546 many1_ = many1
547 il = identLetter
548
549 andThenSym a b = do
550   p <- a
551   symbol b
552   return p
553 -}