[project @ 1997-09-03 10:43:01 by simonm]
[ghc-hetmet.git] / ghc / compiler / reader / Lex.lhs
index edc6f05..0fda696 100644 (file)
@@ -19,30 +19,44 @@ module Lex (
     ) where
 
 
-IMPORT_1_3(Char(isDigit, isAlpha, isAlphanum, isUpper))
+IMPORT_1_3(Char(isDigit, isAlpha, isAlphanum, isUpper,isLower, isSpace, ord))
+
+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
 IMPORT_DELOOPER(Ubiq)
 IMPORT_DELOOPER(IdLoop)    -- get the CostCentre type&constructors from here
+#else
+import {-# SOURCE #-} CostCentre
+# if __GLASGOW_HASKELL__ == 202
+import PrelBase ( Char(..) )
+# endif
+#endif
 
 import CmdLineOpts     ( opt_IgnoreIfacePragmas )
 import Demand          ( Demand(..) {- instance Read -} )
 import UniqFM           ( UniqFM, listToUFM, lookupUFM)
---import FiniteMap     ( FiniteMap, listToFM, lookupFM )
+import BasicTypes      ( NewOrData(..), IfaceFlavour(..) )
+
+#if __GLASGOW_HASKELL__ >= 202
+import Maybes          ( MaybeErr(..) )
+#else
 import Maybes          ( Maybe(..), MaybeErr(..) )
+#endif
 import Pretty
-import CharSeq         ( CSeq )
 
 
 
 import ErrUtils                ( Error(..) )
-import Outputable      ( Outputable(..) )
-import PprStyle                ( PprStyle(..) )
+import Outputable      ( Outputable(..), PprStyle(..) )
 import Util            ( nOfThem, panic )
 
 import FastString
 import StringBuffer
 
+#if __GLASGOW_HASKELL__ <= 201
 import PreludeGlaST 
-
+#else
+import GlaExts
+#endif
 \end{code}
 
 %************************************************************************
@@ -191,18 +205,18 @@ data IfaceToken
   | ITconid   FAST_STRING
   | ITvarsym  FAST_STRING
   | ITconsym  FAST_STRING
-  | ITqvarid  (FAST_STRING,FAST_STRING)
-  | ITqconid  (FAST_STRING,FAST_STRING)
-  | ITqvarsym (FAST_STRING,FAST_STRING)
-  | ITqconsym (FAST_STRING,FAST_STRING)
+  | ITqvarid  (FAST_STRING,FAST_STRING,IfaceFlavour)
+  | ITqconid  (FAST_STRING,FAST_STRING,IfaceFlavour)
+  | ITqvarsym (FAST_STRING,FAST_STRING,IfaceFlavour)
+  | ITqconsym (FAST_STRING,FAST_STRING,IfaceFlavour)
 
-  | ITidinfo [IfaceToken]  -- lazily return the stream of tokens for
-                          -- the info attached to an id.
-  | ITtysig [IfaceToken]   -- lazily return the stream of tokens for
+  | ITtysig StringBuffer (Maybe StringBuffer)
+                          -- lazily return the stream of tokens for
                           -- the info attached to an id.
        -- Stuff for reading unfoldings
-  | ITarity | ITstrict | ITunfold
-  | ITdemand [Demand] | ITbottom
+  | ITarity 
+  | ITunfold Bool              -- True <=> there's an INLINE pragma on this Id
+  | ITstrict [Demand] | ITbottom
   | ITlam | ITbiglam | ITcase | ITprim_case | ITlet | ITletrec | ITin | ITof
   | ITcoerce_in | ITcoerce_out | ITatsign
   | ITccall (Bool,Bool)                -- (is_casm, may_gc)
@@ -211,6 +225,7 @@ data IfaceToken
   | ITinteger Integer | ITdouble Double
   | ITinteger_lit | ITfloat_lit | ITrational_lit | ITaddr_lit | ITlit_lit | ITstring_lit
   | ITunknown String           -- Used when the lexer can't make sense of it
+  | ITeof                              -- end of file token
   deriving Text -- debugging
 
 instance Text CostCentre -- cheat!
@@ -224,8 +239,8 @@ instance Text CostCentre -- cheat!
 %************************************************************************
 
 \begin{code}
-lexIface :: StringBuffer -> [IfaceToken]
-lexIface buf =
+lexIface :: (IfaceToken -> IfM a) -> IfM a
+lexIface cont buf =
  _scc_ "Lexer" 
 -- if bufferExhausted buf then
 --  []
@@ -233,49 +248,49 @@ lexIface buf =
 --  _trace ("Lexer: "++[C# (currentChar# buf)]) $
   case currentChar# buf of
       -- whitespace and comments, ignore.
-    ' '#  -> lexIface (stepOn buf)
-    '\t'# -> lexIface (stepOn buf)
-    '\n'# -> lexIface (stepOn buf)
+    ' '#  -> lexIface cont (stepOn buf)
+    '\t'# -> lexIface cont (stepOn buf)
+    '\n'# -> \line -> lexIface cont (stepOn buf) (line+1)
 
 -- Numbers and comments
     '-'#  ->
       case lookAhead# buf 1# of
-        '-'# -> lex_comment (stepOnBy# buf 2#)
+        '-'# -> lex_comment cont (stepOnBy# buf 2#)
         c    -> 
          if isDigit (C# c)
-          then lex_num (negate) (ord# c -# ord# '0'#) (incLexeme (incLexeme buf))
-         else lex_id buf
+          then lex_num cont (negate) (ord# c -# ord# '0'#) (incLexeme (incLexeme buf))
+         else lex_id cont buf
 
 -- Leave out nested comments for now; danger of finding { and - juxtaposed by mistake?
 --    '{' : '-' : cs -> lex_nested_comment 1{-one seen-} cs
 
     '('# -> 
         case prefixMatch (stepOn buf) "..)" of
-          Just buf' ->  ITdotdot : lexIface (stepOverLexeme buf')
+          Just buf' ->  cont ITdotdot (stepOverLexeme buf')
            Nothing ->
             case lookAhead# buf 1# of
-              ','# -> lex_tuple Nothing  (stepOnBy# buf 2#)
-              ')'# -> ITconid SLIT("()") : lexIface (stepOnBy# buf 2#)
-             _    -> IToparen : lexIface (stepOn buf)
+              ','# -> lex_tuple cont Nothing  (stepOnBy# buf 2#)
+              ')'# -> cont (ITconid SLIT("()")) (stepOnBy# buf 2#)
+             _    -> cont IToparen (stepOn buf)
 
-    '{'# -> ITocurly : lexIface (stepOn buf)
-    '}'# -> ITccurly : lexIface (stepOn buf)
-    ')'# -> ITcparen : lexIface (stepOn buf)
+    '{'# -> cont ITocurly (stepOn buf)
+    '}'# -> cont ITccurly (stepOn buf)
+    ')'# -> cont ITcparen (stepOn buf)
     '['# -> 
       case lookAhead# buf 1# of
-       ']'# -> ITconid SLIT("[]") : lexIface (stepOnBy# buf 2#)
-        _    -> ITobrack : lexIface (stepOn buf)
-    ']'# -> ITcbrack    : lexIface (stepOn buf)
-    ','# -> ITcomma     : lexIface (stepOn buf)
+       ']'# -> cont (ITconid SLIT("[]")) (stepOnBy# buf 2#)
+        _    -> cont ITobrack (stepOn buf)
+    ']'# -> cont ITcbrack (stepOn buf)
+    ','# -> cont ITcomma  (stepOn buf)
     ':'# -> case lookAhead# buf 1# of
-              ':'# -> ITdcolon  : lexIface (stepOnBy# buf 2#)
-              _    -> lex_id (incLexeme buf)
-    ';'#  -> ITsemi    : lexIface (stepOn buf)
+              ':'# -> cont ITdcolon (stepOnBy# buf 2#)
+              _    -> lex_id cont (incLexeme buf)
+    ';'#  -> cont ITsemi (stepOn buf)
     '\"'# -> case untilEndOfString# (stepOn buf) of
              buf' ->
                  -- the string literal does *not* include the dquotes
                case lexemeToFastString buf' of
-                v -> ITstring v : lexIface (stepOn (stepOverLexeme buf'))
+                v -> cont (ITstring v) (stepOn (stepOverLexeme buf'))
 
     '\''# -> --
             -- untilEndOfChar# extends the current lexeme until
@@ -286,47 +301,46 @@ lexIface buf =
             --
             case untilEndOfChar# (stepOn buf) of
               buf' -> case reads ('\'':lexemeToString (incLexeme buf')) of
-                       [  (ch, rest)] -> ITchar ch : lexIface (stepOverLexeme (incLexeme buf'))
+                       [  (ch, rest)] -> cont (ITchar ch) (stepOverLexeme (incLexeme buf'))
 
 -- ``thingy'' form for casm
     '`'# ->
            case lookAhead# buf 1# of
-             '`'# -> lex_cstring (stepOnBy# buf 2#) -- remove the `` and go.
-             _    -> lex_id (incLexeme buf)         -- add ` to lexeme and assume
+             '`'# -> lex_cstring cont (stepOnBy# buf 2#) -- remove the `` and go.
+             _    -> lex_id cont (incLexeme buf)         -- add ` to lexeme and assume
                                                     -- scanning an id of some sort.
 -- Keywords
     '_'# ->
         case lookAhead# buf 1# of
           'S'# -> case lookAhead# buf 2# of
-                   '_'# -> ITstrict : 
-                           lex_demand (stepOnUntil (not . isSpace) 
-                                                   (stepOnBy# buf 3#)) -- past _S_
+                   '_'# ->
+                           lex_demand cont (stepOnUntil (not . isSpace) 
+                                           (stepOnBy# buf 3#)) -- past _S_
           's'# -> case prefixMatch (stepOnBy# buf 2#) "cc_" of
-                    Just buf' -> lex_scc (stepOnUntil (not . isSpace) 
-                                                      (stepOverLexeme buf'))
-                    Nothing   -> lex_keyword (stepOnBy# buf 1#) -- drop the '_' and assume
+                    Just buf' -> lex_scc cont (stepOnUntil (not . isSpace) (stepOverLexeme buf'))
+                    Nothing   -> lex_keyword cont (stepOnBy# buf 1#) -- drop the '_' and assume
                                                                 -- it is a keyword.
-          _    -> lex_keyword (stepOn buf)
+          _    -> lex_keyword cont (stepOn buf)
 
     '\NUL'# ->
            if bufferExhausted (stepOn buf) then
-              []
+              cont ITeof buf
            else
-              lex_id buf
+              lex_id cont buf
     c ->
        if isDigit (C# c) then
-          lex_num (id) (ord# c -# ord# '0'#) (incLexeme buf)
+          lex_num cont (id) (ord# c -# ord# '0'#) (incLexeme buf)
         else
-          lex_id buf
+          lex_id cont buf
 --  where
-lex_comment buf = 
+lex_comment cont buf = 
 --   _trace ("comment: "++[C# (currentChar# buf)]) $
-   case untilChar# buf '\n'# of {buf' -> lexIface (stepOverLexeme buf')}
+   case untilChar# buf '\n'# of {buf' -> lexIface cont (stepOverLexeme buf')}
 
 ------------------
-lex_demand buf = 
+lex_demand cont buf = 
 -- _trace ("demand: "++[C# (currentChar# buf)]) $
- case read_em [] buf of { (ls,buf') -> ITdemand ls : lexIface (stepOverLexeme buf')}
+ case read_em [] buf of { (ls,buf') -> cont (ITstrict ls) (stepOverLexeme buf')}
  where
    -- code snatched from Demand.lhs
   read_em acc buf = 
@@ -338,68 +352,94 @@ lex_demand buf =
     'P'# -> read_em (WwPrim       : acc) (stepOn buf)
     'E'# -> read_em (WwEnum       : acc) (stepOn buf)
     ')'# -> (reverse acc, stepOn buf)
-    'U'# -> do_unpack True  acc (stepOnBy# buf 2#)
-    'u'# -> do_unpack False acc (stepOnBy# buf 2#)
+    'U'# -> do_unpack DataType True  acc (stepOnBy# buf 2#)
+    'u'# -> do_unpack DataType False acc (stepOnBy# buf 2#)
+    'N'# -> do_unpack NewType True  acc (stepOnBy# buf 2#)
+    'n'# -> do_unpack NewType False acc (stepOnBy# buf 2#)
     _    -> (reverse acc, buf)
 
-  do_unpack wrapper_unpacks acc buf
+  do_unpack new_or_data wrapper_unpacks acc buf
    = case read_em [] buf of
-      (stuff, rest) -> read_em (WwUnpack wrapper_unpacks stuff : acc) rest
+      (stuff, rest) -> read_em (WwUnpack new_or_data wrapper_unpacks stuff : acc) rest
 
 ------------------
-lex_scc buf =
+lex_scc cont buf =
 -- _trace ("scc: "++[C# (currentChar# buf)]) $
  case currentChar# buf of
   '"'# ->
       -- YUCK^2
      case prefixMatch (stepOn buf) "NO_CC\"" of
-      Just buf' -> ITscc noCostCentre : lexIface (stepOverLexeme buf')
+      Just buf' -> cont (ITscc noCostCentre) (stepOverLexeme buf')
       Nothing -> 
        case prefixMatch (stepOn buf) "CURRENT_CC\"" of
-        Just buf' -> ITscc useCurrentCostCentre : lexIface (stepOverLexeme buf')
+        Just buf' -> cont (ITscc useCurrentCostCentre) (stepOverLexeme buf')
         Nothing   ->
          case prefixMatch (stepOn buf) "OVERHEAD\"" of
-         Just buf' -> ITscc overheadCostCentre : lexIface (stepOverLexeme buf')
+         Just buf' -> cont (ITscc overheadCostCentre) (stepOverLexeme buf')
          Nothing   ->
           case prefixMatch (stepOn buf) "DONT_CARE\"" of
-           Just buf' -> ITscc dontCareCostCentre : lexIface (stepOverLexeme buf')
+           Just buf' -> cont (ITscc dontCareCostCentre) (stepOverLexeme buf')
            Nothing   ->
             case prefixMatch (stepOn buf) "SUBSUMED\"" of
-             Just buf' -> ITscc subsumedCosts : lexIface (stepOverLexeme buf')
+             Just buf' -> cont (ITscc subsumedCosts) (stepOverLexeme buf')
              Nothing ->
               case prefixMatch (stepOn buf) "CAFs_in_...\"" of
-               Just buf' -> ITscc preludeCafsCostCentre : lexIface (stepOverLexeme buf')
+               Just buf' -> cont (ITscc preludeCafsCostCentre) (stepOverLexeme buf')
                Nothing ->
                 case prefixMatch (stepOn buf) "CC_CAFs_in_..." of
                  Just buf' ->
                  case untilChar# (stepOverLexeme buf') '\"'# of
-                  buf'' -> ITscc (mkAllCafsCC ({-module-}lexemeToFastString buf'') _NIL_): 
-                           lexIface (stepOverLexeme buf'')
+                  buf'' -> cont (ITscc (mkAllCafsCC ({-module-}lexemeToFastString buf'') _NIL_)) (stepOn (stepOverLexeme buf''))
                  Nothing ->
                   case prefixMatch (stepOn buf) "DICTs_in_...\"" of
-                   Just buf' -> ITscc (preludeDictsCostCentre True) : lexIface (stepOverLexeme buf')
+                   Just buf' -> cont (ITscc (preludeDictsCostCentre True)) (stepOverLexeme buf')
                    Nothing ->
                     case prefixMatch (stepOn buf) "CC_DICTs_in_..." of
                      Just buf' ->
                      case untilChar# (stepOverLexeme buf') '\"'# of
-                      buf'' -> ITscc (mkAllDictsCC (lexemeToFastString buf'') _NIL_ True): 
-                               lexIface (stepOverLexeme buf'')
+                      buf'' -> cont (ITscc (mkAllDictsCC (lexemeToFastString buf'') _NIL_ True)) 
+                               (stepOn (stepOverLexeme buf''))
                      Nothing ->
+                     let
+                      match_user_cc buf =
+                       case untilChar# buf '/'# of
+                        buf' -> 
+                          let mod_name = lexemeToFastString buf' in
+--                       case untilChar# (stepOn (stepOverLexeme buf')) '/'# of
+--                        buf'' -> 
+--                            let grp_name = lexemeToFastString buf'' in
+                           case untilChar# (stepOn (stepOverLexeme buf')) '\"'# of
+                            buf'' ->
+                              -- The label may contain arbitrary characters, so it
+                              -- may have been escaped etc., hence we `read' it in to get
+                              -- rid of these meta-chars in the string and then pack it (again.)
+                              -- ToDo: do the same for module name (single quotes allowed in m-names).
+                              -- BTW, the code in this module is totally gruesome..
+                              let upk_label = _UNPK_ (lexemeToFastString buf'') in
+                              case reads ('"':upk_label++"\"") of
+                               ((cc_label,_):_) -> 
+                                   let cc_name = _PK_ cc_label in
+                                   (mkUserCC cc_name mod_name _NIL_{-grp_name-}, 
+                                    stepOn (stepOverLexeme buf''))
+                               _ -> 
+                                 trace ("trouble lexing scc label: " ++ upk_label ++ " , ignoring") 
+                                 (mkUserCC _NIL_ mod_name _NIL_{-grp_name-}, 
+                                  stepOn (stepOverLexeme buf''))
+                      in
                       case prefixMatch (stepOn buf) "CAF:" of
-                       Just buf' ->              
-                       case untilChar# (stepOverLexeme buf') '\"'# of
-                        buf'' -> ITscc (cafifyCC (mkUserCC (lexemeToFastString buf'') _NIL_ _NIL_)): 
-                                 lexIface (stepOverLexeme buf'')
+                       Just buf' ->
+                        case match_user_cc (stepOverLexeme buf') of
+                         (cc, buf'') -> cont (ITscc (cafifyCC cc)) buf''
                        Nothing ->
-                       case untilChar# (stepOn buf) '\"'# of
-                          buf' -> ITscc (mkUserCC (lexemeToFastString buf') _NIL_ _NIL_): 
-                                  lexIface (stepOverLexeme buf')
-  c -> ITunknown [C# c] : lexIface (stepOn buf)
+                        case match_user_cc (stepOn buf) of
+                         (cc, buf'') -> cont (ITscc cc) buf''
+  c -> cont (ITunknown [C# c]) (stepOn buf)
 
 
 -----------
-lex_num :: (Int -> Int) -> Int# -> StringBuffer -> [IfaceToken]
-lex_num minus acc# buf =
+lex_num :: (IfaceToken -> IfM a) -> 
+       (Int -> Int) -> Int# -> IfM a
+lex_num cont minus acc# buf =
 -- _trace ("lex_num: "++[C# (currentChar# buf)]) $
  case scanNumLit (I# acc#) buf of
      (acc',buf') ->
@@ -411,59 +451,60 @@ lex_num minus acc# buf =
            case expandWhile (isDigit) (incLexeme buf') of
               buf'' -> -- points to first non digit char
                case reads (lexemeToString buf'') of
-                 [(v,_)] -> ITdouble v : lexIface (stepOverLexeme buf'')
-         _ -> ITinteger (fromInt (minus acc')) : lexIface (stepOverLexeme buf')
+                 [(v,_)] -> cont (ITdouble v) (stepOverLexeme buf'')
+         _ -> cont (ITinteger (fromInt (minus acc'))) (stepOverLexeme buf')
 
 --        case reads (lexemeToString buf') of
---          [(i,_)] -> ITinteger i : lexIface (stepOverLexeme buf')
+--          [(i,_)] -> cont (ITinteger i) (stepOverLexeme buf')
 
 ------------
-lex_keyword buf =
+lex_keyword cont buf =
 -- _trace ("lex_keyword: "++[C# (currentChar# buf)]) $
  case currentChar# buf of
   ':'# -> case lookAhead# buf 1# of
            '_'# -> -- a binding, type (and other id-info) follows,
                    -- to make the parser ever so slightly, we push
                    -- 
-               lex_decl (stepOnBy# buf 2#)
-           v# -> ITunknown (['_',':',C# v#]) : lexIface (stepOnBy# buf 2#)
+               lex_decl cont (stepOnBy# buf 2#)
+           v# -> cont (ITunknown (['_',':',C# v#])) (stepOnBy# buf 2#)
   _ ->
     case expandWhile (is_kwd_char) buf of
      buf' ->
       let kw = lexemeToFastString buf' in
 --    _trace ("kw: "++lexemeToString buf') $
       case lookupUFM ifaceKeywordsFM kw of
-       Nothing -> ITunknown (_UNPK_ kw) : -- (minor) sigh 
-                 lexIface (stepOverLexeme buf')
-       Just xx -> xx : lexIface (stepOverLexeme buf')
+       Nothing -> cont (ITunknown (_UNPK_ kw)) -- (minor) sigh 
+                 (stepOverLexeme buf')
+       Just xx -> cont xx (stepOverLexeme buf')
 
-lex_decl buf =
+lex_decl cont buf =
  case doDiscard False buf of -- spin until ;; is found
    buf' ->
       {- _trace (show (lexemeToString buf')) $ -}
       case currentChar# buf' of
        '\n'# -> -- newline, no id info.
-          ITtysig (lexIface (lexemeToBuffer (decLexeme buf'))) : 
-          lexIface (stepOverLexeme buf')
+          cont (ITtysig (lexemeToBuffer (decLexeme buf')) Nothing)
+               (stepOverLexeme buf')
        '\r'# -> -- just to be sure for those Win* boxes..
-          ITtysig (lexIface (lexemeToBuffer (decLexeme buf'))) : 
-          lexIface (stepOverLexeme buf')
+          cont (ITtysig (lexemeToBuffer (decLexeme buf')) Nothing)
+               (stepOverLexeme buf')
        '\NUL'# ->
-          ITtysig (lexIface (lexemeToBuffer (decLexeme buf'))) : 
-          lexIface (stepOverLexeme buf')
+          cont (ITtysig (lexemeToBuffer (decLexeme buf')) Nothing)
+               (stepOverLexeme buf')
        c     -> -- run all over the id info
         case doDiscard False (stepOverLexeme buf') of -- spin until ;; is found (outside a string!)
           buf'' -> 
                    --_trace ((C# c):show (lexemeToString (decLexeme buf')))  $
                    --_trace (show (lexemeToString (decLexeme buf''))) $
-                   ITtysig (lexIface (lexemeToBuffer (decLexeme buf'))):
-                   let ls = lexIface (stepOverLexeme buf'') in
-                   if opt_IgnoreIfacePragmas then
-                       ls
-                   else
-                       let is = lexIface (lexemeToBuffer (decLexeme buf'')) in
+                   let idinfo = 
+                           if opt_IgnoreIfacePragmas then
+                               Nothing
+                           else
+                               Just (lexemeToBuffer (decLexeme buf''))
                        --_trace (show is) $
-                       ITidinfo is : ls
+                   in
+                    cont (ITtysig (lexemeToBuffer (decLexeme buf')) idinfo)
+                       (stepOverLexeme buf'')
                    
 -- ToDo: hammer!
 is_kwd_char c@(C# c#) = 
@@ -478,22 +519,22 @@ is_kwd_char c@(C# c#) =
 
 
 -----------
-lex_cstring buf =
+lex_cstring cont buf =
 -- _trace ("lex_cstring: "++[C# (currentChar# buf)]) $
  case expandUntilMatch buf "\'\'" of
-   buf' -> ITstring (lexemeToFastString (setCurrentPos# buf' (negateInt# 2#))) :
-           lexIface (stepOverLexeme buf')
+   buf' -> cont (ITstring (lexemeToFastString (setCurrentPos# buf' (negateInt# 2#))))
+           (stepOverLexeme buf')
        
 -----------
-lex_tuple module_dot buf =
+lex_tuple cont module_dot buf =
 -- _trace ("lex_tuple: "++[C# (currentChar# buf)]) $
   go 2 buf
   where
    go n buf =
     case currentChar# buf of
       ','# -> go (n+1) (stepOn buf)
-      ')'# -> end_lex_id module_dot (ITconid (mkTupNameStr n)) (stepOn buf)
-      _    -> ITunknown ("tuple " ++ show n) : lexIface buf
+      ')'# -> end_lex_id cont module_dot (ITconid (mkTupNameStr n)) (stepOn buf)
+      _    -> cont (ITunknown ("tuple " ++ show n)) buf
 
 -- Similarly ' itself is ok inside an identifier, but not at the start
 
@@ -526,12 +567,12 @@ is_id_char (C# c#) =
 
 is_sym c#=
  case c# of {
-   ':'# -> True; '_'# -> True; '\''# -> True; '!'# -> True; 
-   '#'# -> True; '$'# -> True; ':'# -> True;  '%'# -> True; 
-   '&'# -> True; '*'# -> True; '+'# -> True; '.'# -> True; 
-   '/'# -> True; '<'# -> True; '='# -> True; '>'# -> True; 
-   '?'# -> True; '\\'# -> True; '^'# -> True; '|'# -> True; 
-   '-'# -> True; '~'# -> True; '@'# -> True; _ -> False }
+   ':'# -> True; '_'#  -> True; '\''# -> True; '!'# -> True; 
+   '#'# -> True; '$'#  -> True; ':'#  -> True; '%'# -> True; 
+   '&'# -> True; '*'#  -> True; '+'#  -> True; '.'# -> True; 
+   '/'# -> True; '<'#  -> True; '='#  -> True; '>'# -> True; 
+   '?'# -> True; '\\'# -> True; '^'#  -> True; '|'# -> True; 
+   '-'# -> True; '~'#  -> True; '@'#  -> True; _    -> False }
 
 --isAlphanum c || c `elem` ":_'!#$%&*+./<=>?@\\^|-~" -- ToDo: add ISOgraphic
 
@@ -591,52 +632,64 @@ lex_id cs =
 
 -}
 
-lex_id buf = 
+lex_id cont buf = 
 -- _trace ("lex_id: "++[C# (currentChar# buf)]) $
  case expandWhile (is_mod_char) buf of
    buf' ->
     case currentChar# buf' of
-     '.'# ->
+     '.'# -> munch buf' HiFile
+     '!'# -> munch buf' HiBootFile
+     _    -> lex_id2 cont Nothing buf'
+   where
+    munch buf' hif = 
        if not (emptyLexeme buf') then
 --        _trace ("lex_id: "++(C# (currentChar# (stepOverLexeme buf'))):show (lexemeToFastString buf')) $ 
           case lexemeToFastString buf' of
-            l@(FastString u# l# ba#) -> lex_id2 (Just (FastString u# l# ba#)) 
+            l@(FastString u# l# ba#) -> lex_id2 cont (Just (FastString u# l# ba#, hif)) 
                                                 (stepOn (stepOverLexeme buf'))
        else
-          lex_id2 Nothing buf'         
-     _  -> lex_id2 Nothing buf'
+          lex_id2 cont Nothing buf'            
+       
 
 -- Dealt with the Module.part
-lex_id2 module_dot buf =
+lex_id2 cont module_dot buf =
 -- _trace ("lex_id2: "++[C# (currentChar# buf)]) $
  case currentChar# buf of
   '['# -> 
     case lookAhead# buf 1# of
-     ']'# -> end_lex_id module_dot (ITconid SLIT("[]")) (stepOnBy# buf 2#)
-     _    -> lex_id3 module_dot buf
+     ']'# -> end_lex_id cont module_dot (ITconid SLIT("[]")) (stepOnBy# buf 2#)
+     _    -> lex_id3 cont module_dot buf
   '('# ->
     case lookAhead# buf 1# of
-     ')'# -> end_lex_id module_dot (ITconid SLIT("()")) (stepOnBy# buf 2#)
-     ','# -> lex_tuple module_dot (stepOnBy# buf 2#)
-     _    -> lex_id3 module_dot buf
-  ':'# -> lex_id3 module_dot (incLexeme buf)
-  _    -> lex_id3 module_dot buf
+     ')'# -> end_lex_id cont module_dot (ITconid SLIT("()")) (stepOnBy# buf 2#)
+     ','# -> lex_tuple cont module_dot (stepOnBy# buf 2#)
+     _    -> lex_id3 cont module_dot buf
+  ':'# -> lex_id3 cont module_dot (incLexeme buf)
+  '-'# ->
+     case module_dot of
+       Nothing  -> lex_id3 cont module_dot buf
+       Just ghc -> -- this should be "GHC" (current home of (->))
+         case lookAhead# buf 1# of
+          '>'# -> end_lex_id cont module_dot (ITconid SLIT("->")) 
+                       (stepOnBy# buf 2#)
+          _    -> lex_id3 cont module_dot buf
+  _    -> lex_id3 cont module_dot buf
 
 
 
 -- Dealt with [], (), : special cases
 
-lex_id3 module_dot buf =
+lex_id3 cont module_dot buf =
 -- _trace ("lex_id3: "++[C# (currentChar# buf)]) $
  case expandWhile (is_id_char) buf of
   buf' ->
     case module_dot of
      Just _ ->
-       end_lex_id module_dot (mk_var_token lexeme) (stepOverLexeme buf')
+       end_lex_id cont module_dot (mk_var_token lexeme) (stepOverLexeme buf')
      Nothing ->
        case _scc_ "Lex.haskellKeyword" lookupUFM haskellKeywordsFM lexeme of
-         Just kwd_token -> kwd_token           : lexIface new_buf
-        Nothing        -> mk_var_token lexeme : lexIface new_buf
+         Just kwd_token -> cont kwd_token new_buf
+        Nothing        -> cont (mk_var_token lexeme) new_buf
     where
      lexeme  = lexemeToFastString buf'
      new_buf = stepOverLexeme buf'
@@ -650,7 +703,6 @@ lex_id2 module_dot [] (':' : cs)     = lex_id3 module_dot [':'] cs
 lex_id2 module_dot xs cs            = lex_id3 module_dot xs cs
 -}
 
-
 -- Dealt with [], (), : special cases
 
 {-
@@ -690,15 +742,15 @@ mk_var_token pk_str =
                      n = _PK_ xs
 -}
                            
-end_lex_id Nothing token buf  = token : lexIface buf
-end_lex_id (Just m) token buf =
+end_lex_id cont Nothing token buf  = cont token buf
+end_lex_id cont (Just (m,hif)) token buf =
  case token of
-   ITconid n  -> ITqconid  (m,n)         : lexIface buf
-   ITvarid n  -> ITqvarid  (m,n)         : lexIface buf
-   ITconsym n -> ITqconsym (m,n)         : lexIface buf
-   ITvarsym n -> ITqvarsym (m,n)         : lexIface buf
-   ITbang     -> ITqvarsym (m,SLIT("!")) : lexIface buf
-   _         -> ITunknown (show token)  : lexIface buf
+   ITconid n  -> cont (ITqconid  (m,n,hif))         buf
+   ITvarid n  -> cont (ITqvarid  (m,n,hif))         buf
+   ITconsym n -> cont (ITqconsym (m,n,hif))         buf
+   ITvarsym n -> cont (ITqvarsym (m,n,hif))         buf
+   ITbang     -> cont (ITqvarsym (m,SLIT("!"),hif)) buf
+   _         -> cont (ITunknown (show token))      buf
 
 ------------
 ifaceKeywordsFM :: UniqFM IfaceToken
@@ -706,6 +758,7 @@ ifaceKeywordsFM = listToUFM $
       map (\ (x,y) -> (_PK_ x,y))
        [("/\\_",               ITbiglam)
        ,("@_",                 ITatsign)
+       ,("letrec_",            ITletrec)
        ,("interface_",         ITinterface)
        ,("usages_",            ITusages)
        ,("versions_",          ITversions)
@@ -716,7 +769,8 @@ ifaceKeywordsFM = listToUFM $
        ,("declarations_",      ITdeclarations)
        ,("pragmas_",           ITpragmas)
        ,("forall_",            ITforall)
-       ,("U_",                 ITunfold)
+       ,("U_",                 ITunfold False)
+       ,("U!_",                        ITunfold True)
        ,("A_",                 ITarity)
        ,("coerce_in_",         ITcoerce_in)
        ,("coerce_out_",                ITcoerce_out)
@@ -749,7 +803,6 @@ haskellKeywordsFM = listToUFM $
        ,("of",                 ITof)
        ,("in",                 ITin)
        ,("let",                        ITlet)
-       ,("letrec",             ITletrec)
        ,("deriving",           ITderiving)
 
        ,("->",                 ITrarrow)
@@ -774,9 +827,20 @@ doDiscard inStr buf =
      else
        doDiscard inStr (incLexeme buf)
    '"'# ->
+       let
+        odd_slashes buf flg i# =
+          case lookAhead# buf i# of
+          '\\'# -> odd_slashes buf (not flg) (i# -# 1#)
+          _     -> flg
+       in
        case lookAhead# buf (negateInt# 1#) of --backwards, actually
-        '\\'# -> -- false alarm, escaped. 
-           doDiscard inStr (incLexeme buf)
+        '\\'# -> -- escaping something..
+          if odd_slashes buf True (negateInt# 2#) then
+              -- odd number of slashes, " is escaped.
+             doDiscard inStr (incLexeme buf)
+          else
+              -- even number of slashes, \ is escaped.
+             doDiscard (not inStr) (incLexeme buf)
          _ -> case inStr of -- forced to avoid build-up
               True  -> doDiscard False (incLexeme buf)
                False -> doDiscard True  (incLexeme buf)
@@ -806,21 +870,22 @@ end{code}
 %************************************************************************
 
 \begin{code}
-type IfM a = MaybeErr a Error
+type IfM a = StringBuffer -> Int -> MaybeErr a Error
 
 returnIf   :: a -> IfM a
-thenIf    :: IfM a -> (a -> IfM b) -> IfM b
-happyError :: Int -> [IfaceToken] -> IfM a
+returnIf a s l = Succeeded a
 
-returnIf a = Succeeded a
-
-thenIf (Succeeded a) k = k a
-thenIf (Failed  err) _ = Failed err
+thenIf    :: IfM a -> (a -> IfM b) -> IfM b
+m `thenIf` k = \s l ->
+       case m s l of
+               Succeeded a -> k a s l
+               Failed err  -> Failed err
 
-happyError ln toks = Failed (ifaceParseErr ln toks)
+happyError :: IfM a
+happyError s l = Failed (ifaceParseErr l ([]::[IfaceToken]){-Todo-})
 
 -----------------------------------------------------------------
 
-ifaceParseErr ln toks sty
-  = ppCat [ppPStr SLIT("Interface-file parse error: line"), ppInt ln, ppPStr SLIT("toks="), ppStr (show (take 10 toks))]
+ifaceParseErr l toks sty
+  = hsep [ptext SLIT("Interface-file parse error: line"), int l, ptext SLIT("toks="), text (show (take 10 toks))]
 \end{code}