b2f04b04ff14a9e80ddf573f555df325938932d2
[ghc-hetmet.git] / ghc / compiler / parser / Lex.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[Lexical analysis]{Lexical analysis}
5
6 --------------------------------------------------------
7 [Jan 98]
8 There's a known bug in here:
9
10         If an interface file ends prematurely, Lex tries to
11         do headFS of an empty FastString.
12
13 An example that provokes the error is
14
15         f _:_ _forall_ [a] <<<END OF FILE>>>
16 --------------------------------------------------------
17
18 \begin{code}
19 {-# OPTIONS -#include "ctypes.h" #-}
20
21 module Lex (
22
23         ifaceParseErr,
24
25         -- Monad for parser
26         Token(..), lexer, ParseResult(..), PState(..),
27         checkVersion, 
28         StringBuffer,
29
30         P, thenP, thenP_, returnP, mapP, failP, failMsgP,
31         getSrcLocP, getSrcFile,
32         layoutOn, layoutOff, pushContext, popContext
33     ) where
34
35 #include "HsVersions.h"
36
37 import Char             ( ord, isSpace, toUpper )
38 import List             ( isSuffixOf )
39
40 import IdInfo           ( InlinePragInfo(..), CprInfo(..) )
41 import Name             ( isLowerISO, isUpperISO )
42 import PrelMods         ( mkTupNameStr, mkUbxTupNameStr )
43 import CmdLineOpts      ( opt_IgnoreIfacePragmas, opt_HiVersion, opt_NoHiCheck )
44 import Demand           ( Demand(..) {- instance Read -} )
45 import UniqFM           ( UniqFM, listToUFM, lookupUFM)
46 import BasicTypes       ( NewOrData(..) )
47 import SrcLoc           ( SrcLoc, incSrcLine, srcLocFile, srcLocLine,
48                           replaceSrcLine, mkSrcLoc )
49
50 import Maybes           ( MaybeErr(..) )
51 import ErrUtils         ( Message )
52 import Outputable
53
54 import FastString
55 import StringBuffer
56 import GlaExts
57 import ST               ( runST )
58
59 #if __GLASGOW_HASKELL__ >= 303
60 import Bits
61 import Word
62 #endif
63
64 import Char             ( chr )
65 import Addr
66 import PrelRead         ( readRational__ ) -- Glasgow non-std
67 \end{code}
68
69 %************************************************************************
70 %*                                                                      *
71 \subsection{Data types}
72 %*                                                                      *
73 %************************************************************************
74
75 The token data type, fairly un-interesting except from one
76 constructor, @ITidinfo@, which is used to lazily lex id info (arity,
77 strictness, unfolding etc).
78
79 The Idea/Observation here is that the renamer needs to scan through
80 all of an interface file before it can continue. But only a fraction
81 of the information contained in the file turns out to be useful, so
82 delaying as much as possible of the scanning and parsing of an
83 interface file Makes Sense (Heap profiles of the compiler 
84 show a reduction in heap usage by at least a factor of two,
85 post-renamer). 
86
87 Hence, the interface file lexer spots when value declarations are
88 being scanned and return the @ITidinfo@ and @ITtype@ constructors
89 for the type and any other id info for that binding (unfolding, strictness
90 etc). These constructors are applied to the result of lexing these sub-chunks.
91
92 The lexing of the type and id info is all done lazily, of course, so
93 the scanning (and subsequent parsing) will be done *only* on the ids the
94 renamer finds out that it is interested in. The rest will just be junked.
95 Laziness, you know it makes sense :-)
96
97 \begin{code}
98 data Token
99   = ITas                        -- Haskell keywords
100   | ITcase
101   | ITclass
102   | ITdata
103   | ITdefault
104   | ITderiving
105   | ITdo
106   | ITelse
107   | IThiding
108   | ITif
109   | ITimport
110   | ITin
111   | ITinfix
112   | ITinfixl
113   | ITinfixr
114   | ITinstance
115   | ITlet
116   | ITmodule
117   | ITnewtype
118   | ITof
119   | ITqualified
120   | ITthen
121   | ITtype
122   | ITwhere
123   | ITscc
124
125   | ITforall                    -- GHC extension keywords
126   | ITforeign
127   | ITexport
128   | ITlabel
129   | ITdynamic
130   | ITunsafe
131   | ITwith
132   | ITstdcallconv
133   | ITccallconv
134
135   | ITinterface                 -- interface keywords
136   | IT__export
137   | ITdepends
138   | IT__forall
139   | ITletrec 
140   | ITcoerce
141   | ITinlineMe
142   | ITinlineCall
143   | ITccall (Bool,Bool,Bool)    -- (is_dyn, is_casm, may_gc)
144   | ITdefaultbranch
145   | ITbottom
146   | ITinteger_lit 
147   | ITfloat_lit
148   | ITrational_lit
149   | ITaddr_lit
150   | ITlit_lit
151   | ITstring_lit
152   | ITtypeapp
153   | ITusage
154   | ITfuall
155   | ITarity 
156   | ITspecialise
157   | ITnocaf
158   | ITunfold InlinePragInfo
159   | ITstrict ([Demand], Bool)
160   | ITrules
161   | ITdeprecated
162   | ITcprinfo (CprInfo)
163   | IT__scc
164   | ITsccAllCafs
165
166   | ITspecialise_prag           -- Pragmas
167   | ITsource_prag
168   | ITinline_prag
169   | ITnoinline_prag
170   | ITrules_prag
171   | ITdeprecated_prag
172   | ITline_prag
173   | ITclose_prag
174
175   | ITdotdot                    -- reserved symbols
176   | ITdcolon
177   | ITequal
178   | ITlam
179   | ITvbar
180   | ITlarrow
181   | ITrarrow
182   | ITat
183   | ITtilde
184   | ITdarrow
185   | ITminus
186   | ITbang
187   | ITdot
188
189   | ITbiglam                    -- GHC-extension symbols
190
191   | ITocurly                    -- special symbols
192   | ITccurly
193   | ITvccurly
194   | ITobrack
195   | ITcbrack
196   | IToparen
197   | ITcparen
198   | IToubxparen
199   | ITcubxparen
200   | ITsemi
201   | ITcomma
202   | ITunderscore
203   | ITbackquote
204
205   | ITvarid   FAST_STRING       -- identifiers
206   | ITconid   FAST_STRING
207   | ITvarsym  FAST_STRING
208   | ITconsym  FAST_STRING
209   | ITqvarid  (FAST_STRING,FAST_STRING)
210   | ITqconid  (FAST_STRING,FAST_STRING)
211   | ITqvarsym (FAST_STRING,FAST_STRING)
212   | ITqconsym (FAST_STRING,FAST_STRING)
213
214   | ITipvarid FAST_STRING       -- GHC extension: implicit param: ?x
215
216   | ITpragma StringBuffer
217
218   | ITchar       Char 
219   | ITstring     FAST_STRING
220   | ITinteger    Integer 
221   | ITrational   Rational
222
223   | ITprimchar   Char
224   | ITprimstring FAST_STRING
225   | ITprimint    Integer
226   | ITprimfloat  Rational
227   | ITprimdouble Rational
228   | ITlitlit     FAST_STRING
229
230   | ITunknown String            -- Used when the lexer can't make sense of it
231   | ITeof                       -- end of file token
232   deriving Text -- debugging
233 \end{code}
234
235 -----------------------------------------------------------------------------
236 Keyword Lists
237
238 \begin{code}
239 pragmaKeywordsFM = listToUFM $
240       map (\ (x,y) -> (_PK_ x,y))
241        [( "SPECIALISE", ITspecialise_prag ),
242         ( "SPECIALIZE", ITspecialise_prag ),
243         ( "SOURCE",     ITsource_prag ),
244         ( "INLINE",     ITinline_prag ),
245         ( "NOINLINE",   ITnoinline_prag ),
246         ( "NOTINLINE",  ITnoinline_prag ),
247         ( "LINE",       ITline_prag ),
248         ( "RULES",      ITrules_prag ),
249         ( "RULEZ",      ITrules_prag ), -- american spelling :-)
250         ( "DEPRECATED", ITdeprecated_prag )
251         ]
252
253 haskellKeywordsFM = listToUFM $
254       map (\ (x,y) -> (_PK_ x,y))
255        [( "_",          ITunderscore ),
256         ( "as",         ITas ),
257         ( "case",       ITcase ),     
258         ( "class",      ITclass ),    
259         ( "data",       ITdata ),     
260         ( "default",    ITdefault ),  
261         ( "deriving",   ITderiving ), 
262         ( "do",         ITdo ),       
263         ( "else",       ITelse ),     
264         ( "hiding",     IThiding ),
265         ( "if",         ITif ),       
266         ( "import",     ITimport ),   
267         ( "in",         ITin ),       
268         ( "infix",      ITinfix ),    
269         ( "infixl",     ITinfixl ),   
270         ( "infixr",     ITinfixr ),   
271         ( "instance",   ITinstance ), 
272         ( "let",        ITlet ),      
273         ( "module",     ITmodule ),   
274         ( "newtype",    ITnewtype ),  
275         ( "of",         ITof ),       
276         ( "qualified",  ITqualified ),
277         ( "then",       ITthen ),     
278         ( "type",       ITtype ),     
279         ( "where",      ITwhere ),
280         ( "_scc_",      ITscc )
281      ]
282
283 -- IMPORTANT: Keep this in synch with ParseIface.y's var_fs production! (SUP)
284 ghcExtensionKeywordsFM = listToUFM $
285         map (\ (x,y) -> (_PK_ x,y))
286      [  ( "forall",     ITforall ),
287         ( "foreign",    ITforeign ),
288         ( "export",     ITexport ),
289         ( "label",      ITlabel ),
290         ( "dynamic",    ITdynamic ),
291         ( "unsafe",     ITunsafe ),
292         ( "with",       ITwith ),
293         ( "stdcall",    ITstdcallconv),
294         ( "ccall",      ITccallconv),
295         ("_ccall_",     ITccall (False, False, False)),
296         ("_ccall_GC_",  ITccall (False, False, True)),
297         ("_casm_",      ITccall (False, True,  False)),
298         ("_casm_GC_",   ITccall (False, True,  True)),
299
300         -- interface keywords
301         ("__interface",         ITinterface),
302         ("__export",            IT__export),
303         ("__depends",           ITdepends),
304         ("__forall",            IT__forall),
305         ("__letrec",            ITletrec),
306         ("__coerce",            ITcoerce),
307         ("__inline_me",         ITinlineMe),
308         ("__inline_call",       ITinlineCall),
309         ("__depends",           ITdepends),
310         ("__DEFAULT",           ITdefaultbranch),
311         ("__bot",               ITbottom),
312         ("__integer",           ITinteger_lit),
313         ("__float",             ITfloat_lit),
314         ("__rational",          ITrational_lit),
315         ("__addr",              ITaddr_lit),
316         ("__litlit",            ITlit_lit),
317         ("__string",            ITstring_lit),
318         ("__a",                 ITtypeapp),
319         ("__u",                 ITusage),
320         ("__fuall",             ITfuall),
321         ("__A",                 ITarity),
322         ("__P",                 ITspecialise),
323         ("__C",                 ITnocaf),
324         ("__R",                 ITrules),
325         ("__D",                 ITdeprecated),
326         ("__U",                 ITunfold NoInlinePragInfo),
327         
328         ("__ccall",             ITccall (False, False, False)),
329         ("__ccall_GC",          ITccall (False, False, True)),
330         ("__dyn_ccall",         ITccall (True,  False, False)),
331         ("__dyn_ccall_GC",      ITccall (True,  False, True)),
332         ("__casm",              ITccall (False, True,  False)),
333         ("__dyn_casm",          ITccall (True,  True,  False)),
334         ("__casm_GC",           ITccall (False, True,  True)),
335         ("__dyn_casm_GC",       ITccall (True,  True,  True)),
336
337         ("/\\",                 ITbiglam)
338      ]
339
340
341 haskellKeySymsFM = listToUFM $
342         map (\ (x,y) -> (_PK_ x,y))
343       [ ("..",          ITdotdot)
344        ,("::",          ITdcolon)
345        ,("=",           ITequal)
346        ,("\\",          ITlam)
347        ,("|",           ITvbar)
348        ,("<-",          ITlarrow)
349        ,("->",          ITrarrow)
350        ,("@",           ITat)
351        ,("~",           ITtilde)
352        ,("=>",          ITdarrow)
353        ,("-",           ITminus)
354        ,("!",           ITbang)
355        ,(".",           ITdot)          -- sadly, for 'forall a . t'
356        ]
357 \end{code}
358
359 -----------------------------------------------------------------------------
360 The lexical analyser
361
362 Lexer state:
363
364         - (glaexts) lexing an interface file or -fglasgow-exts
365         - (bol)   pointer to beginning of line (for column calculations)
366         - (buf)   pointer to beginning of token
367         - (buf)   pointer to current char
368         - (atbol) flag indicating whether we're at the beginning of a line
369
370 \begin{code}
371 lexer :: (Token -> P a) -> P a
372 lexer cont buf s@(PState{
373                     loc = loc,
374                     glasgow_exts = glaexts,
375                     bol = bol,
376                     atbol = atbol,
377                     context = ctx
378                 })
379
380         -- first, start a new lexeme and lose all the whitespace
381   =  _scc_ "Lexer" 
382   tab line bol atbol (stepOverLexeme buf)
383   where
384         line = srcLocLine loc
385
386         tab y bol atbol buf = --trace ("tab: " ++ show (I# y) ++ " : " ++ show (currentChar buf)) $
387           case currentChar# buf of
388
389             '\NUL'# ->
390                    if bufferExhausted (stepOn buf)
391                         then cont ITeof buf s'
392                         else trace "lexer: misplaced NUL?" $ 
393                              tab y bol atbol (stepOn buf)
394
395             '\n'# -> let buf' = stepOn buf
396                      in tab (y +# 1#) (currentIndex# buf') 1# buf'
397
398                 -- find comments.  This got harder in Haskell 98.
399             '-'# ->  let trundle n = 
400                           let next = lookAhead# buf n in
401                           if next `eqChar#` '-'# then trundle (n +# 1#)
402                           else if is_symbol next || n <# 2#
403                                 then is_a_token
404                                 else case untilChar# (stepOnBy# buf n) '\n'# of 
405                                     { buf' -> tab y bol atbol (stepOverLexeme buf')
406                                     }
407                     in trundle 1#
408
409                 -- comments and pragmas.  We deal with LINE pragmas here,
410                 -- and throw out any unrecognised pragmas as comments.  Any
411                 -- pragmas we know about are dealt with later (after any layout
412                 -- processing if necessary).
413
414             '{'# | lookAhead# buf 1# `eqChar#` '-'# ->
415                 if lookAhead# buf 2# `eqChar#` '#'# then
416                   if lookAhead# buf 3# `eqChar#` '#'# then is_a_token else
417                   case expandWhile# is_space (setCurrentPos# buf 3#) of { buf1->
418                   case expandWhile# is_ident (stepOverLexeme buf1)   of { buf2->
419                   let lexeme = mkFastString -- ToDo: too slow
420                                   (map toUpper (lexemeToString buf2)) in
421                   case lookupUFM pragmaKeywordsFM lexeme of
422                         Just ITline_prag -> line_prag (lexer cont) buf2 s'
423                         Just other -> is_a_token
424                         Nothing -> skip_to_end (stepOnBy# buf 2#)
425                   }}
426                 
427                 else skip_to_end (stepOnBy# buf 2#)
428                 where
429                     skip_to_end buf = nested_comment (lexer cont) buf s'
430
431                 -- tabs have been expanded beforehand
432             c | is_space c -> tab y bol atbol (stepOn buf)
433               | otherwise  -> is_a_token
434
435            where s' = s{loc = replaceSrcLine loc y, 
436                         bol = bol,
437                        atbol = atbol}
438
439                  is_a_token | atbol /=# 0# = lexBOL cont buf s'
440                             | otherwise    = lexToken cont glaexts buf s'
441
442 -- {-# LINE .. #-} pragmas.  yeuch.
443 line_prag cont buf =
444   case expandWhile# is_space buf                of { buf1 ->
445   case scanNumLit 0 (stepOverLexeme buf1)       of { (line,buf2) ->
446   -- subtract one: the line number refers to the *following* line.
447   let real_line = line - 1 in
448   case fromInteger real_line                    of { i@(I# l) -> 
449   case expandWhile# is_space buf2               of { buf3 ->
450   case currentChar# buf3                        of
451      '\"'#{-"-} -> 
452         case untilEndOfString# (stepOn (stepOverLexeme buf3)) of { buf4 ->
453         let file = lexemeToFastString buf4 in
454         \s@PState{loc=loc} -> skipToEnd buf4 s{loc = mkSrcLoc file i}
455         }
456      other -> \s@PState{loc=loc} -> skipToEnd buf3 s{loc = replaceSrcLine loc l}
457   }}}}
458   where
459         skipToEnd buf = nested_comment cont buf
460
461 nested_comment :: P a -> P a
462 nested_comment cont buf = loop buf
463  where
464    loop buf = 
465      case currentChar# buf of
466         '\NUL'# | bufferExhausted (stepOn buf) -> 
467                 lexError "unterminated `{-'" buf
468
469         '-'# | lookAhead# buf 1# `eqChar#` '}'# ->
470                 cont (stepOnBy# buf 2#)
471
472         '{'# | lookAhead# buf 1# `eqChar#` '-'# ->
473               nested_comment (nested_comment cont) (stepOnBy# buf 2#)
474
475         '\n'# -> \ s@PState{loc=loc} ->
476                  let buf' = stepOn buf in
477                  nested_comment cont buf'
478                         s{loc = incSrcLine loc, bol = currentIndex# buf',
479                           atbol = 1#}
480
481         _   -> nested_comment cont (stepOn buf)
482
483 -- When we are lexing the first token of a line, check whether we need to
484 -- insert virtual semicolons or close braces due to layout.
485
486 lexBOL :: (Token -> P a) -> P a
487 lexBOL cont buf s@(PState{
488                     loc = loc,
489                     glasgow_exts = glaexts,
490                     bol = bol,
491                     atbol = atbol,
492                     context = ctx
493                   }) =
494         if need_close_curly then 
495                 --trace ("col = " ++ show (I# col) ++ ", layout: inserting '}'") $
496                 cont ITvccurly buf s{atbol = 1#, context = tail ctx}
497         else if need_semi_colon then
498                 --trace ("col = " ++ show (I# col) ++ ", layout: inserting ';'") $
499                 cont ITsemi buf s{atbol = 0#}
500         else
501                 lexToken cont glaexts buf s{atbol = 0#}
502   where
503         col = currentIndex# buf -# bol
504
505         need_close_curly =
506                 case ctx of
507                         [] -> False
508                         (i:_) -> case i of
509                                     NoLayout -> False
510                                     Layout n -> col <# n
511         need_semi_colon =
512                 case ctx of
513                         [] -> False
514                         (i:_) -> case i of
515                                     NoLayout -> False
516                                     Layout n -> col ==# n
517
518
519 lexToken :: (Token -> P a) -> Int# -> P a
520 lexToken cont glaexts buf =
521  --trace "lexToken" $
522   case currentChar# buf of
523
524     -- special symbols ----------------------------------------------------
525     '('# | flag glaexts && lookAhead# buf 1# `eqChar#` '#'# 
526                 -> cont IToubxparen (setCurrentPos# buf 2#)
527          | otherwise
528                 -> cont IToparen (incLexeme buf)
529
530     ')'# -> cont ITcparen    (incLexeme buf)
531     '['# -> cont ITobrack    (incLexeme buf)
532     ']'# -> cont ITcbrack    (incLexeme buf)
533     ','# -> cont ITcomma     (incLexeme buf)
534     ';'# -> cont ITsemi      (incLexeme buf)
535
536     '}'# -> \ s@PState{context = ctx} ->
537             case ctx of 
538                 (_:ctx') -> cont ITccurly (incLexeme buf) s{context=ctx'}
539                 _        -> lexError "too many '}'s" buf s
540
541     '#'# -> case lookAhead# buf 1# of
542                 ')'#  | flag glaexts -> cont ITcubxparen (setCurrentPos# buf 2#)
543                 '-'# -> case lookAhead# buf 2# of
544                            '}'# -> cont ITclose_prag (setCurrentPos# buf 3#)
545                            _    -> lex_sym cont (incLexeme buf)
546                 _    -> lex_sym cont (incLexeme buf)
547
548     '`'# | flag glaexts && lookAhead# buf 1# `eqChar#` '`'#
549                 -> lex_cstring cont (setCurrentPos# buf 2#)
550          | otherwise
551                 -> cont ITbackquote (incLexeme buf)
552
553     '{'# ->     -- look for "{-##" special iface pragma
554         case lookAhead# buf 1# of
555            '-'# -> case lookAhead# buf 2# of
556                     '#'# -> case lookAhead# buf 3# of
557                                 '#'# ->  
558                                    let (lexeme, buf') 
559                                           = doDiscard False (stepOnBy# (stepOverLexeme buf) 4#) in
560                                    cont (ITpragma lexeme) buf'
561                                 _ -> lex_prag cont (setCurrentPos# buf 3#)
562                     _    -> cont ITocurly (incLexeme buf)
563            _ -> (layoutOff `thenP_` cont ITocurly)  (incLexeme buf)
564
565     -- strings/characters -------------------------------------------------
566     '\"'#{-"-} -> lex_string cont glaexts "" (incLexeme buf)
567     '\''#      -> lex_char (char_end cont) glaexts (incLexeme buf)
568
569     -- strictness and cpr pragmas and __scc treated specially.
570     '_'# | flag glaexts ->
571          case lookAhead# buf 1# of
572            '_'# -> case lookAhead# buf 2# of
573                     'S'# -> 
574                         lex_demand cont (stepOnUntil (not . isSpace) 
575                                         (stepOnBy# buf 3#)) -- past __S
576                     'M'# -> 
577                         lex_cpr cont (stepOnUntil (not . isSpace) 
578                                      (stepOnBy# buf 3#)) -- past __M
579                     's'# -> 
580                         case prefixMatch (stepOnBy# buf 3#) "cc" of
581                                Just buf' -> lex_scc cont (stepOverLexeme buf')
582                                Nothing   -> lex_id cont glaexts buf
583                     _ -> lex_id cont glaexts buf
584            _    -> lex_id cont glaexts buf
585
586         -- Hexadecimal and octal constants
587     '0'# | (ch `eqChar#` 'x'# || ch `eqChar#` 'X'#) && is_hexdigit ch2
588                 -> readNum (after_lexnum cont glaexts) buf' is_hexdigit 16 hex
589          | (ch `eqChar#` 'o'# || ch `eqChar#` 'O'#) && is_octdigit ch2
590                 -> readNum (after_lexnum cont glaexts) buf' is_octdigit  8 oct_or_dec
591         where ch   = lookAhead# buf 1#
592               ch2  = lookAhead# buf 2#
593               buf' = setCurrentPos# buf 2#
594
595     '\NUL'# ->
596             if bufferExhausted (stepOn buf) then
597                cont ITeof buf
598             else
599                trace "lexIface: misplaced NUL?" $ 
600                cont (ITunknown "\NUL") (stepOn buf)
601
602     '?'# | flag glaexts && is_lower (lookAhead# buf 1#) ->
603             lex_ip cont (incLexeme buf)
604     c | is_digit  c -> lex_num cont glaexts 0 buf
605       | is_symbol c -> lex_sym cont buf
606       | is_upper  c -> lex_con cont glaexts buf
607       | is_ident  c -> lex_id  cont glaexts buf
608       | otherwise   -> lexError "illegal character" buf
609
610 -- Int# is unlifted, and therefore faster than Bool for flags.
611 {-# INLINE flag #-}
612 flag :: Int# -> Bool
613 flag 0# = False
614 flag _  = True
615
616 -------------------------------------------------------------------------------
617 -- Pragmas
618
619 lex_prag cont buf
620   = case expandWhile# is_space buf of { buf1 ->
621     case expandWhile# is_ident (stepOverLexeme buf1) of { buf2 -> 
622     let lexeme = mkFastString (map toUpper (lexemeToString buf2)) in
623     case lookupUFM pragmaKeywordsFM lexeme of
624         Just kw -> cont kw (mergeLexemes buf buf2)
625         Nothing -> panic "lex_prag"
626   }}
627
628 -------------------------------------------------------------------------------
629 -- Strings & Chars
630
631 lex_string cont glaexts s buf
632   = case currentChar# buf of
633         '"'#{-"-} -> 
634            let buf' = incLexeme buf; s' = mkFastString (reverse s) in
635            case currentChar# buf' of
636                 '#'# | flag glaexts -> cont (ITprimstring s') (incLexeme buf')
637                 _                   -> cont (ITstring s') buf'
638
639         -- ignore \& in a string, deal with string gaps
640         '\\'# | next_ch `eqChar#` '&'# 
641                 -> lex_string cont glaexts s buf'
642               | is_space next_ch
643                 -> lex_stringgap cont glaexts s (incLexeme buf)
644
645             where next_ch = lookAhead# buf 1#
646                   buf' = setCurrentPos# buf 2#
647
648         _ -> lex_char (lex_next_string cont s) glaexts buf
649
650 lex_stringgap cont glaexts s buf
651   = let buf' = incLexeme buf in
652     case currentChar# buf of
653         '\n'# -> \st@PState{loc = loc} -> lex_stringgap cont glaexts s buf' 
654                   st{loc = incSrcLine loc}
655         '\\'# -> lex_string cont glaexts s buf'
656         c | is_space c -> lex_stringgap cont glaexts s buf'
657         other -> charError buf'
658
659 lex_next_string cont s glaexts c buf = lex_string cont glaexts (c:s) buf
660
661 lex_char :: (Int# -> Char -> P a) -> Int# -> P a
662 lex_char cont glaexts buf
663   = case currentChar# buf of
664         '\\'# -> lex_escape (cont glaexts) (incLexeme buf)
665         c | is_any c -> cont glaexts (C# c) (incLexeme buf)
666         other -> charError buf
667
668 char_end cont glaexts c buf
669   = case currentChar# buf of
670         '\''# -> let buf' = incLexeme buf in
671                  case currentChar# buf' of
672                         '#'# | flag glaexts 
673                                 -> cont (ITprimchar c) (incLexeme buf')
674                         _       -> cont (ITchar c) buf'
675         _     -> charError buf
676
677 lex_escape cont buf
678   = let buf' = incLexeme buf in
679     case currentChar# buf of
680         'a'#       -> cont '\a' buf'
681         'b'#       -> cont '\b' buf'
682         'f'#       -> cont '\f' buf'
683         'n'#       -> cont '\n' buf'
684         'r'#       -> cont '\r' buf'
685         't'#       -> cont '\t' buf'
686         'v'#       -> cont '\v' buf'
687         '\\'#      -> cont '\\' buf'
688         '"'#       -> cont '\"' buf'
689         '\''#      -> cont '\'' buf'
690         '^'#       -> let c = currentChar# buf' in
691                       if c `geChar#` '@'# && c `leChar#` '_'#
692                         then cont (C# (chr# (ord# c -# ord# '@'#))) (incLexeme buf')
693                         else charError buf'
694
695         'x'#      -> readNum (after_charnum cont) buf' is_hexdigit 16 hex
696         'o'#      -> readNum (after_charnum cont) buf' is_octdigit  8 oct_or_dec
697         x | is_digit x 
698                   -> readNum (after_charnum cont) buf is_digit    10 oct_or_dec
699
700         _          -> case [ (c,buf2) | (p,c) <- silly_escape_chars,
701                                        Just buf2 <- [prefixMatch buf p] ] of
702                             (c,buf2):_ -> cont c buf2
703                             [] -> charError buf'
704
705 after_charnum cont i buf 
706   = let int = fromInteger i in
707     if i >= 0 && i <= 255 
708         then cont (chr int) buf
709         else charError buf
710
711 readNum cont buf is_digit base conv = read buf 0
712   where read buf i 
713           = case currentChar# buf of { c ->
714             if is_digit c
715                 then read (incLexeme buf) (i*base + (toInteger (I# (conv c))))
716                 else cont i buf
717             }
718
719 is_hexdigit c 
720         =  is_digit c 
721         || (c `geChar#` 'a'# && c `leChar#` 'f'#)
722         || (c `geChar#` 'A'# && c `leChar#` 'F'#)
723
724 hex c | is_digit c = ord# c -# ord# '0'#
725       | otherwise  = ord# (to_lower c) -# ord# 'a'# +# 10#
726 oct_or_dec c = ord# c -# ord# '0'#
727
728 is_octdigit c = c `geChar#` '0'# && c `leChar#` '7'#
729
730 to_lower c 
731   | c `geChar#` 'A'# && c `leChar#` 'Z'#  
732         = chr# (ord# c -# (ord# 'A'# -# ord# 'a'#))
733   | otherwise = c
734
735 charError buf = lexError "error in character literal" buf
736
737 silly_escape_chars = [
738         ("NUL", '\NUL'),
739         ("SOH", '\SOH'),
740         ("STX", '\STX'),
741         ("ETX", '\ETX'),
742         ("EOT", '\EOT'),
743         ("ENQ", '\ENQ'),
744         ("ACK", '\ACK'),
745         ("BEL", '\BEL'),
746         ("BS", '\BS'),
747         ("HT", '\HT'),
748         ("LF", '\LF'),
749         ("VT", '\VT'),
750         ("FF", '\FF'),
751         ("CR", '\CR'),
752         ("SO", '\SO'),
753         ("SI", '\SI'),
754         ("DLE", '\DLE'),
755         ("DC1", '\DC1'),
756         ("DC2", '\DC2'),
757         ("DC3", '\DC3'),
758         ("DC4", '\DC4'),
759         ("NAK", '\NAK'),
760         ("SYN", '\SYN'),
761         ("ETB", '\ETB'),
762         ("CAN", '\CAN'),
763         ("EM", '\EM'),
764         ("SUB", '\SUB'),
765         ("ESC", '\ESC'),
766         ("FS", '\FS'),
767         ("GS", '\GS'),
768         ("RS", '\RS'),
769         ("US", '\US'),
770         ("SP", '\SP'),
771         ("DEL", '\DEL')
772         ]
773
774 -------------------------------------------------------------------------------
775
776 lex_demand cont buf = 
777  case read_em [] buf of { (ls,buf') -> 
778  case currentChar# buf' of
779    'B'# -> cont (ITstrict (ls, True )) (incLexeme buf')
780    _    -> cont (ITstrict (ls, False)) buf'
781  }
782  where
783    -- code snatched from Demand.lhs
784   read_em acc buf = 
785    case currentChar# buf of
786     'L'# -> read_em (WwLazy False : acc) (stepOn buf)
787     'A'# -> read_em (WwLazy True  : acc) (stepOn buf)
788     'S'# -> read_em (WwStrict     : acc) (stepOn buf)
789     'P'# -> read_em (WwPrim       : acc) (stepOn buf)
790     'E'# -> read_em (WwEnum       : acc) (stepOn buf)
791     ')'# -> (reverse acc, stepOn buf)
792     'U'# -> do_unpack DataType True  acc (stepOnBy# buf 2#)
793     'u'# -> do_unpack DataType False acc (stepOnBy# buf 2#)
794     'N'# -> do_unpack NewType True  acc (stepOnBy# buf 2#)
795     'n'# -> do_unpack NewType False acc (stepOnBy# buf 2#)
796     _    -> (reverse acc, buf)
797
798   do_unpack new_or_data wrapper_unpacks acc buf
799    = case read_em [] buf of
800       (stuff, rest) -> read_em (WwUnpack new_or_data wrapper_unpacks stuff : acc) rest
801
802 lex_cpr cont buf = 
803  case read_em [] buf of { (cpr_inf,buf') -> 
804    ASSERT ( null (tail cpr_inf) )
805    cont (ITcprinfo $ head cpr_inf) buf'
806  }
807  where
808    -- code snatched from lex_demand above
809   read_em acc buf = 
810    case currentChar# buf of
811     '-'# -> read_em (NoCPRInfo : acc) (stepOn buf)
812     '('# -> do_unpack acc (stepOn buf)
813     ')'# -> (reverse acc, stepOn buf)
814     _    -> (reverse acc, buf)
815
816   do_unpack acc buf
817    = case read_em [] buf of
818       (stuff, rest) -> read_em ((CPRInfo stuff)  : acc) rest
819
820 ------------------
821 lex_scc cont buf =
822  case currentChar# buf of
823   'C'# -> cont ITsccAllCafs (incLexeme buf)
824   other -> cont ITscc buf
825
826 -----------------------------------------------------------------------------
827 -- Numbers
828
829 lex_num :: (Token -> P a) -> Int# -> Integer -> P a
830 lex_num cont glaexts acc buf =
831  case scanNumLit acc buf of
832      (acc',buf') ->
833        case currentChar# buf' of
834          '.'# | is_digit (lookAhead# buf' 1#) ->
835              -- this case is not optimised at all, as the
836              -- presence of floating point numbers in interface
837              -- files is not that common. (ToDo)
838             case expandWhile# is_digit (incLexeme buf') of
839               buf2 -> -- points to first non digit char
840
841                 let l = case currentChar# buf2 of
842                           'E'# -> do_exponent
843                           'e'# -> do_exponent
844                           _ -> buf2
845
846                     do_exponent 
847                         = let buf3 = incLexeme buf2 in
848                           case currentChar# buf3 of
849                                 '-'# -> expandWhile# is_digit (incLexeme buf3)
850                                 '+'# -> expandWhile# is_digit (incLexeme buf3)
851                                 x | is_digit x -> expandWhile# is_digit buf3
852                                 _ -> buf2
853
854                     v = readRational__ (lexemeToString l)
855
856                 in case currentChar# l of -- glasgow exts only
857                       '#'# | flag glaexts -> let l' = incLexeme l in
858                               case currentChar# l' of
859                                 '#'# -> cont (ITprimdouble v) (incLexeme l')
860                                 _    -> cont (ITprimfloat  v) l'
861                       _ -> cont (ITrational v) l
862
863          _ -> after_lexnum cont glaexts acc' buf'
864                 
865 after_lexnum cont glaexts i buf
866   = case currentChar# buf of
867         '#'# | flag glaexts -> cont (ITprimint i) (incLexeme buf)
868         _    -> cont (ITinteger i) buf
869
870 -----------------------------------------------------------------------------
871 -- C "literal literal"s  (i.e. things like ``NULL'', ``stdout'' etc.)
872
873 -- we lexemeToFastString on the bit between the ``''s, but include the
874 -- quotes in the full lexeme.
875
876 lex_cstring cont buf =
877  case expandUntilMatch (stepOverLexeme buf) "\'\'" of
878    Just buf' -> cont (ITlitlit (lexemeToFastString 
879                                 (setCurrentPos# buf' (negateInt# 2#))))
880                    (mergeLexemes buf buf')
881    Nothing   -> lexError "unterminated ``" buf
882
883 ------------------------------------------------------------------------------
884 -- Character Classes
885
886 is_ident, is_symbol, is_any, is_upper, is_digit :: Char# -> Bool
887
888 {-# INLINE is_ctype #-}
889 #if __GLASGOW_HASKELL__ >= 303
890 is_ctype :: Word8 -> Char# -> Bool
891 is_ctype mask = \c ->
892    (indexWord8OffAddr (``char_types'' :: Addr) (ord (C# c)) .&. mask) /= 0
893 #else
894 is_ctype :: Int -> Char# -> Bool
895 is_ctype (I# mask) = \c ->
896     let (A# ctype) = ``char_types'' :: Addr
897         flag_word  = int2Word# (ord# (indexCharOffAddr# ctype (ord# c)))
898     in
899         (flag_word `and#` (int2Word# mask)) `neWord#` (int2Word# 0#)
900 #endif
901
902 is_ident  = is_ctype 1
903 is_symbol = is_ctype 2
904 is_any    = is_ctype 4
905 is_space  = is_ctype 8
906 is_lower  = is_ctype 16
907 is_upper  = is_ctype 32
908 is_digit  = is_ctype 64
909
910 -----------------------------------------------------------------------------
911 -- identifiers, symbols etc.
912
913 lex_ip cont buf =
914  case expandWhile# is_ident buf of
915    buf' -> cont (ITipvarid lexeme) buf'
916            where lexeme = lexemeToFastString buf'
917
918 lex_id cont glaexts buf =
919  case expandWhile# is_ident buf of { buf1 -> 
920
921  case (if flag glaexts 
922         then expandWhile# (eqChar# '#'#) buf1 -- slurp trailing hashes
923         else buf1)                              of { buf' ->
924
925  let lexeme  = lexemeToFastString buf' in
926
927  case _scc_ "Lex.haskellKeyword" lookupUFM haskellKeywordsFM lexeme of {
928         Just kwd_token -> --trace ("hkeywd: "++_UNPK_(lexeme)) $
929                           cont kwd_token buf';
930         Nothing        -> 
931
932  let var_token = cont (mk_var_token lexeme) buf' in
933
934  if not (flag glaexts)
935    then var_token
936    else
937
938  case lookupUFM ghcExtensionKeywordsFM lexeme of {
939         Just kwd_token -> cont kwd_token buf';
940         Nothing        -> var_token
941
942  }}}}
943
944 lex_sym cont buf =
945  case expandWhile# is_symbol buf of
946    buf' -> case lookupUFM haskellKeySymsFM lexeme of {
947                 Just kwd_token -> --trace ("keysym: "++unpackFS lexeme) $
948                                   cont kwd_token buf' ;
949                 Nothing        -> --trace ("sym: "++unpackFS lexeme) $
950                                   cont (mk_var_token lexeme) buf'
951            }
952         where lexeme = lexemeToFastString buf'
953
954
955 lex_con cont glaexts buf = 
956  case expandWhile# is_ident buf          of { buf1 ->
957  case slurp_trailing_hashes buf1 glaexts of { buf' ->
958
959  case currentChar# buf' of
960      '.'# -> munch
961      _    -> just_a_conid
962  
963    where
964     just_a_conid = --trace ("con: "++unpackFS lexeme) $
965                    cont (ITconid lexeme) buf'
966     lexeme = lexemeToFastString buf'
967     munch = lex_qid cont glaexts lexeme (incLexeme buf') just_a_conid
968  }}
969
970 lex_qid cont glaexts mod buf just_a_conid =
971  case currentChar# buf of
972   '['# ->       -- Special case for []
973     case lookAhead# buf 1# of
974      ']'# -> cont (ITqconid  (mod,SLIT("[]"))) (setCurrentPos# buf 2#)
975      _    -> just_a_conid
976
977   '('# ->  -- Special case for (,,,)
978            -- This *is* necessary to deal with e.g. "instance C PrelBase.(,,)"
979     case lookAhead# buf 1# of
980      '#'# | flag glaexts -> case lookAhead# buf 2# of
981                 ','# -> lex_ubx_tuple cont mod (setCurrentPos# buf 3#) 
982                                 just_a_conid
983                 _    -> just_a_conid
984      ')'# -> cont (ITqconid (mod,SLIT("()"))) (setCurrentPos# buf 2#)
985      ','# -> lex_tuple cont mod (setCurrentPos# buf 2#) just_a_conid
986      _    -> just_a_conid
987
988   '-'# -> case lookAhead# buf 1# of
989             '>'# -> cont (ITqconid (mod,SLIT("->"))) (setCurrentPos# buf 2#)
990             _    -> lex_id3 cont glaexts mod buf just_a_conid
991   _    -> lex_id3 cont glaexts mod buf just_a_conid
992
993 lex_id3 cont glaexts mod buf just_a_conid
994   | is_symbol (currentChar# buf) =
995      let 
996         start_new_lexeme = stepOverLexeme buf
997      in
998      case expandWhile# is_symbol start_new_lexeme of { buf' ->
999      let
1000        lexeme  = lexemeToFastString buf'
1001         -- real lexeme is M.<sym>
1002        new_buf = mergeLexemes buf buf'
1003      in
1004      cont (mk_qvar_token mod lexeme) new_buf
1005         -- wrong, but arguably morally right: M... is now a qvarsym
1006      }
1007
1008   | otherwise   =
1009      let 
1010         start_new_lexeme = stepOverLexeme buf
1011      in
1012      case expandWhile# is_ident start_new_lexeme of { buf1 ->
1013      if emptyLexeme buf1 
1014             then just_a_conid
1015             else
1016
1017      case slurp_trailing_hashes buf1 glaexts of { buf' ->
1018
1019      let
1020       lexeme  = lexemeToFastString buf'
1021       new_buf = mergeLexemes buf buf'
1022       is_a_qvarid = cont (mk_qvar_token mod lexeme) new_buf
1023      in
1024      case _scc_ "Lex.haskellKeyword" lookupUFM haskellKeywordsFM lexeme of {
1025             Just kwd_token -> just_a_conid; -- avoid M.where etc.
1026             Nothing        -> is_a_qvarid
1027         -- TODO: special ids (as, qualified, hiding) shouldn't be
1028         -- recognised as keywords here.  ie.  M.as is a qualified varid.
1029      }}}
1030
1031
1032 slurp_trailing_hashes buf glaexts
1033   | flag glaexts = expandWhile# (`eqChar#` '#'#) buf
1034   | otherwise    = buf
1035
1036
1037 mk_var_token pk_str
1038   | is_upper f          = ITconid pk_str
1039         -- _[A-Z] is treated as a constructor in interface files.
1040   | f `eqChar#` '_'# && not (_NULL_ tl) 
1041         && (case _HEAD_ tl of { C# g -> is_upper g }) = ITconid pk_str
1042   | is_ident f          = ITvarid pk_str
1043   | f `eqChar#` ':'#    = ITconsym pk_str
1044   | otherwise           = ITvarsym pk_str
1045   where
1046       (C# f) = _HEAD_ pk_str
1047       tl     = _TAIL_ pk_str
1048
1049 mk_qvar_token m token =
1050  case mk_var_token token of
1051    ITconid n  -> ITqconid  (m,n)
1052    ITvarid n  -> ITqvarid  (m,n)
1053    ITconsym n -> ITqconsym (m,n)
1054    ITvarsym n -> ITqvarsym (m,n)
1055    _          -> ITunknown (show token)
1056 \end{code}
1057
1058 ----------------------------------------------------------------------------
1059 Horrible stuff for dealing with M.(,,,)
1060
1061 \begin{code}
1062 lex_tuple cont mod buf back_off =
1063   go 2 buf
1064   where
1065    go n buf =
1066     case currentChar# buf of
1067       ','# -> go (n+1) (stepOn buf)
1068       ')'# -> cont (ITqconid (mod, snd (mkTupNameStr n))) (stepOn buf)
1069       _    -> back_off
1070
1071 lex_ubx_tuple cont mod buf back_off =
1072   go 2 buf
1073   where
1074    go n buf =
1075     case currentChar# buf of
1076       ','# -> go (n+1) (stepOn buf)
1077       '#'# -> case lookAhead# buf 1# of
1078                 ')'# -> cont (ITqconid (mod, snd (mkUbxTupNameStr n)))
1079                                  (stepOnBy# buf 2#)
1080                 _    -> back_off
1081       _    -> back_off
1082 \end{code}
1083
1084 -----------------------------------------------------------------------------
1085 doDiscard rips along really fast, looking for a '#-}', 
1086 indicating the end of the pragma we're skipping
1087
1088 \begin{code}
1089 doDiscard inStr buf =
1090  case currentChar# buf of
1091    '#'# | not inStr ->
1092        case lookAhead# buf 1# of { '#'# -> 
1093        case lookAhead# buf 2# of { '-'# ->
1094        case lookAhead# buf 3# of { '}'# -> 
1095            (lexemeToBuffer buf, stepOverLexeme (setCurrentPos# buf 4#));
1096         _    -> doDiscard inStr (incLexeme buf) };
1097         _    -> doDiscard inStr (incLexeme buf) };
1098         _    -> doDiscard inStr (incLexeme buf) }
1099    '"'# ->
1100        let
1101         odd_slashes buf flg i# =
1102           case lookAhead# buf i# of
1103            '\\'# -> odd_slashes buf (not flg) (i# -# 1#)
1104            _     -> flg
1105        in
1106        case lookAhead# buf (negateInt# 1#) of --backwards, actually
1107          '\\'# -> -- escaping something..
1108            if odd_slashes buf True (negateInt# 2#) then
1109                -- odd number of slashes, " is escaped.
1110               doDiscard inStr (incLexeme buf)
1111            else
1112                -- even number of slashes, \ is escaped.
1113               doDiscard (not inStr) (incLexeme buf)
1114          _ -> case inStr of -- forced to avoid build-up
1115                True  -> doDiscard False (incLexeme buf)
1116                False -> doDiscard True  (incLexeme buf)
1117    _ -> doDiscard inStr (incLexeme buf)
1118
1119 \end{code}
1120
1121 -----------------------------------------------------------------------------
1122
1123 \begin{code}
1124 data LayoutContext
1125   = NoLayout
1126   | Layout Int#
1127
1128 data ParseResult a
1129   = POk PState a
1130   | PFailed Message
1131
1132 data PState = PState { 
1133         loc           :: SrcLoc,
1134         glasgow_exts  :: Int#,
1135         bol           :: Int#,
1136         atbol         :: Int#,
1137         context       :: [LayoutContext]
1138      }
1139
1140 type P a = StringBuffer         -- Input string
1141         -> PState
1142         -> ParseResult a
1143
1144 returnP   :: a -> P a
1145 returnP a buf s = POk s a
1146
1147 thenP      :: P a -> (a -> P b) -> P b
1148 m `thenP` k = \ buf s ->
1149         case m buf s of
1150                 POk s1 a -> k a buf s1
1151                 PFailed err  -> PFailed err
1152
1153 thenP_     :: P a -> P b -> P b
1154 m `thenP_` k = m `thenP` \_ -> k
1155
1156 mapP :: (a -> P b) -> [a] -> P [b]
1157 mapP f [] = returnP []
1158 mapP f (a:as) = 
1159      f a `thenP` \b ->
1160      mapP f as `thenP` \bs ->
1161      returnP (b:bs)
1162
1163 failP :: String -> P a
1164 failP msg buf s = PFailed (text msg)
1165
1166 failMsgP :: Message -> P a
1167 failMsgP msg buf s = PFailed msg
1168
1169 lexError :: String -> P a
1170 lexError str buf s@PState{ loc = loc } 
1171   = failMsgP (hcat [ppr loc, text ": ", text str]) buf s
1172
1173 getSrcLocP :: P SrcLoc
1174 getSrcLocP buf s@(PState{ loc = loc }) = POk s loc
1175
1176 getSrcFile :: P FAST_STRING
1177 getSrcFile buf s@(PState{ loc = loc }) = POk s (srcLocFile loc)
1178
1179 getContext :: P [LayoutContext]
1180 getContext buf s@(PState{ context = ctx }) = POk s ctx
1181
1182 pushContext :: LayoutContext -> P ()
1183 pushContext ctxt buf s@(PState{ context = ctx }) = POk s{context = ctxt:ctx} ()
1184
1185 {-
1186
1187 This special case in layoutOn is to handle layout contexts with are
1188 indented the same or less than the current context.  This is illegal
1189 according to the Haskell spec, so we have to arrange to close the
1190 current context.  eg.
1191
1192 class Foo a where
1193 class Bar a
1194
1195 after the first 'where', the sequence of events is:
1196
1197         - layout system inserts a ';' (column 0)
1198         - parser begins a new context at column 0
1199         - parser shifts ';' (legal empty declaration)
1200         - parser sees 'class': parse error (we're still in the inner context)
1201
1202 trouble is, by the time we know we need a new context, the lexer has
1203 already generated the ';'.  Hacky solution is as follows: since we
1204 know the column of the next token (it's the column number of the new
1205 context), we set the ACTUAL column number of the new context to this
1206 numer plus one.  Hence the next time the lexer is called, a '}' will
1207 be generated to close the new context straight away.  Furthermore, we
1208 have to set the atbol flag so that the ';' that the parser shifted as
1209 part of the new context is re-generated.
1210
1211 when the new context is *less* indented than the current one:
1212
1213 f = f where g = g where
1214 h = h
1215
1216         - current context: column 12.
1217         - on seeing 'h' (column 0), the layout system inserts '}'
1218         - parser starts a new context, column 0
1219         - parser sees '}', uses it to close new context
1220         - we still need to insert another '}' followed by a ';',
1221           hence the atbol trick.
1222
1223 There's also a special hack in here to deal with
1224
1225         do
1226            ....
1227            e $ do
1228            blah
1229
1230 i.e. the inner context is at the same indentation level as the outer
1231 context.  This is strictly illegal according to Haskell 98, but
1232 there's a lot of existing code using this style and it doesn't make
1233 any sense to disallow it, since empty 'do' lists don't make sense.
1234 -}
1235
1236 layoutOn :: Bool -> P ()
1237 layoutOn strict buf s@(PState{ bol = bol, context = ctx }) =
1238     let offset = lexemeIndex buf -# bol in
1239     case ctx of
1240         Layout prev_off : _ 
1241            | if strict then prev_off >=# offset else prev_off ># offset ->
1242                 --trace ("layout on, column: " ++  show (I# offset)) $
1243                 POk s{ context = Layout (offset +# 1#) : ctx, atbol = 1# } ()
1244         other -> 
1245                 --trace ("layout on, column: " ++  show (I# offset)) $
1246                 POk s{ context = Layout offset : ctx } ()
1247
1248 layoutOff :: P ()
1249 layoutOff buf s@(PState{ context = ctx }) =
1250     POk s{ context = NoLayout:ctx } ()
1251
1252 popContext :: P ()
1253 popContext = \ buf s@(PState{ context = ctx }) ->
1254   case ctx of
1255         (_:tl) -> POk s{ context = tl } ()
1256         []    -> panic "Lex.popContext: empty context"
1257
1258 {- 
1259  Note that if the name of the file we're processing ends
1260  with `hi-boot', we accept it on faith as having the right
1261  version. This is done so that .hi-boot files that comes
1262  with hsc don't have to be updated before every release,
1263  *and* it allows us to share .hi-boot files with versions
1264  of hsc that don't have .hi version checking (e.g., ghc-2.10's)
1265
1266  If the version number is 0, the checking is also turned off.
1267  (needed to deal with GHC.hi only!)
1268
1269  Once we can assume we're compiling with a version of ghc that
1270  supports interface file checking, we can drop the special
1271  pleading
1272 -}
1273 checkVersion :: Maybe Integer -> P ()
1274 checkVersion mb@(Just v) buf s@(PState{loc = loc})
1275  | (v==0) || (v == fromInt opt_HiVersion) || opt_NoHiCheck = POk s ()
1276  | otherwise = PFailed (ifaceVersionErr mb loc ([]::[Token]){-Todo-})
1277 checkVersion mb@Nothing  buf s@(PState{loc = loc})
1278  | "hi-boot" `isSuffixOf` (_UNPK_ (srcLocFile loc)) = POk s ()
1279  | otherwise = PFailed (ifaceVersionErr mb loc ([]::[Token]){-Todo-})
1280
1281 -----------------------------------------------------------------
1282
1283 ifaceParseErr :: StringBuffer -> SrcLoc -> Message
1284 ifaceParseErr s l
1285   = hsep [ppr l, ptext SLIT("Interface file parse error; on input `"),
1286           text (lexemeToString s), char '\'']
1287
1288 ifaceVersionErr hi_vers l toks
1289   = hsep [ppr l, ptext SLIT("Interface file version error;"),
1290           ptext SLIT("Expected"), int opt_HiVersion, 
1291           ptext SLIT("found "), pp_version]
1292     where
1293      pp_version =
1294       case hi_vers of
1295         Nothing -> ptext SLIT("pre ghc-3.02 version")
1296         Just v  -> ptext SLIT("version") <+> integer v
1297
1298 \end{code}