1 % ----------------------------------------------------------------
4 % (c) The University of Glasgow, 1994-2000
8 {-# OPTIONS -fno-implicit-prelude #-}
12 ( LexP -- :: *; = ReadP Lexeme
13 , Lexeme(..) -- :: *; Show, Eq
17 , lexLitChar -- :: LexP
20 , Number -- :: *; Show, Eq
22 , numberToInt -- :: Number -> Maybe Int
23 , numberToInteger -- :: Number -> Maybe Integer
24 , numberToRational -- :: Number -> Maybe Integer
25 , numberToFloat -- :: Number -> Maybe Float
26 , numberToDouble -- :: Number -> Maybe Double
28 , readIntP -- :: Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadP a
29 , readOctP -- :: Num a => ReadP a
30 , readDecP -- :: Num a => ReadP a
31 , readHexP -- :: Num a => ReadP a
35 import Text.ParserCombinators.ReadP
38 import GHC.Num( Num(..), Integer )
39 import GHC.Show( Show(.. ), showChar, showString,
40 isSpace, isAlpha, isAlphaNum,
41 isOctDigit, isHexDigit, toUpper )
42 import GHC.Real( Ratio, Integral, Rational, (%), fromIntegral, fromRational,
43 toInteger, (^), (^^) )
44 import GHC.Float( Float, Double )
46 import GHC.Show( ShowS, shows )
47 import GHC.Enum( minBound, maxBound )
53 %*********************************************************
55 \subsection{Lexing types}
57 %*********************************************************
60 type LexP = ReadP Lexeme
71 instance Show Lexeme where
72 showsPrec n (Char c) = showsPrec n c
73 showsPrec n (String s) = showsPrec n s
74 showsPrec _ (Single c) = showChar c
75 showsPrec _ (Ident s) = showString s
76 showsPrec _ (Symbol s) = showString s
77 showsPrec n (Number x) = showsPrec n x
81 %*********************************************************
85 %*********************************************************
100 ------------------------------------------------------------------------
105 do s <- munch1 isSymbolChar
108 isSymbolChar c = c `elem` "!@#$%&*+./<=>?\\^|:-~"
110 ------------------------------------------------------------------------
115 do c <- satisfy isAlpha
119 isIdfChar c = isAlphaNum c || c `elem` "_'"
123 %*********************************************************
125 \subsection{Lexing characters and strings}
127 %*********************************************************
130 ------------------------------------------------------------------------
137 guard (esc || c /= '\'')
141 lexChar :: ReadP (Char, Bool) -- "escaped or not"?
145 then do c <- lexEsc; return (c, True)
146 else do return (c, False)
172 guard (n <= toInteger (ord maxBound))
173 return (chr (fromInteger n))
178 'o':_ -> do get; return 8
179 'O':_ -> do get; return 8
180 'x':_ -> do get; return 16
181 'X':_ -> do get; return 16
224 [ string "NUL" >> return '\NUL'
225 , string "SOH" >> return '\SOH'
226 , string "STX" >> return '\STX'
227 , string "ETX" >> return '\ETX'
228 , string "EOT" >> return '\EOT'
229 , string "ENQ" >> return '\ENQ'
230 , string "ACK" >> return '\ACK'
231 , string "BEL" >> return '\BEL'
232 , string "BS" >> return '\BS'
233 , string "HT" >> return '\HT'
234 , string "LF" >> return '\LF'
235 , string "VT" >> return '\VT'
236 , string "FF" >> return '\FF'
237 , string "CR" >> return '\CR'
238 , string "SO" >> return '\SO'
239 , string "SI" >> return '\SI'
240 , string "DLE" >> return '\DLE'
241 , string "DC1" >> return '\DC1'
242 , string "DC2" >> return '\DC2'
243 , string "DC3" >> return '\DC3'
244 , string "DC4" >> return '\DC4'
245 , string "NAK" >> return '\NAK'
246 , string "SYN" >> return '\SYN'
247 , string "ETB" >> return '\ETB'
248 , string "CAN" >> return '\CAN'
249 , string "EM" >> return '\EM'
250 , string "SUB" >> return '\SUB'
251 , string "ESC" >> return '\ESC'
252 , string "FS" >> return '\FS'
253 , string "GS" >> return '\GS'
254 , string "RS" >> return '\RS'
255 , string "US" >> return '\US'
256 , string "SP" >> return '\SP'
257 , string "DEL" >> return '\DEL'
260 ------------------------------------------------------------------------
269 do (c,esc) <- lexStrItem
272 else return (String (f ""))
275 (lexEmpty >> lexStrItem)
283 _ | isSpace c -> do skipSpaces; char '\\'; return ()
286 ------------------------------------------------------------------------
287 -- single character lexemes
291 do c <- satisfy isSingleChar
294 isSingleChar c = c `elem` ",;()[]{=}_`"
298 %*********************************************************
300 \subsection{Lexing numbers}
302 %*********************************************************
307 { value :: Either Integer Rational
310 , fraction :: Maybe Digits
311 , exponent :: Maybe Integer
318 instance Show Number where
321 . foldr (.) id (map showDigit (digits x))
322 . showsFrac (fraction x)
323 . showsExp (exponent x)
325 showsBase 8 = showString "0o"
327 showsBase 16 = showString "0x"
329 showsFrac Nothing = id
330 showsFrac (Just ys) =
332 . foldr (.) id (map showDigit ys)
334 showsExp Nothing = id
335 showsExp (Just exp) =
339 showDigit :: Int -> ShowS
340 showDigit n | n <= 9 = shows n
341 | otherwise = showChar (chr (n + ord 'A' - 10))
351 '0':'o':_ -> do get; get; return 8
352 '0':'O':_ -> do get; get; return 8
353 '0':'x':_ -> do get; get; return 16
354 '0':'X':_ -> do get; get; return 16
357 lexNumberBase :: Base -> LexP
359 do xs <- lexDigits base
360 mFrac <- lexFrac base
362 return (Number (MkNumber (value xs mFrac mExp) base xs mFrac mExp))
364 value xs mFrac mExp = valueFracExp (val (fromIntegral base) 0 xs) mFrac mExp
366 valueFracExp a Nothing mExp = Left (valueExp a mExp)
367 valueFracExp a (Just fs) mExp =
368 Right (valueExp (fromInteger a + frac (fromIntegral base) 0 1 fs) mExp)
370 valueExp a Nothing = a
371 valueExp a (Just exp) = a * (fromIntegral base ^ exp)
373 lexFrac :: Base -> ReadP (Maybe Digits)
379 frac <- lexDigits base
385 lexExp :: Base -> ReadP (Maybe Integer)
389 e : _ | e `elem` "eE" && base == 10 ->
394 do c <- char '-' +++ char '+'
396 return (Just (if c == '-' then -n else n))
399 do n <- lexInteger 10
405 lexDigits :: Int -> ReadP Digits
409 guard (not (null xs))
412 scan (c:cs) f = case valDig base c of
413 Just n -> do get; scan cs (f.(n:))
414 Nothing -> do return (f [])
415 scan [] f = do return (f [])
417 lexInteger :: Base -> ReadP Integer
419 do xs <- lexDigits base
420 return (val (fromIntegral base) 0 xs)
422 val :: Num a => a -> a -> Digits -> a
424 val base y (x:xs) = y' `seq` val base y' xs
426 y' = y * base + fromIntegral x
428 frac :: Integral a => a -> a -> a -> Digits -> Ratio a
429 frac base a b [] = a % b
430 frac base a b (x:xs) = a' `seq` b' `seq` frac base a' b' xs
432 a' = a * base + fromIntegral x
435 valDig :: Num a => a -> Char -> Maybe Int
437 | '0' <= c && c <= '7' = Just (ord c - ord '0')
438 | otherwise = Nothing
441 | '0' <= c && c <= '9' = Just (ord c - ord '0')
442 | otherwise = Nothing
445 | '0' <= c && c <= '9' = Just (ord c - ord '0')
446 | 'a' <= c && c <= 'f' = Just (ord c - ord 'a' + 10)
447 | 'A' <= c && c <= 'F' = Just (ord c - ord 'A' + 10)
448 | otherwise = Nothing
450 ------------------------------------------------------------------------
453 numberToInt :: Number -> Maybe Int
455 case numberToInteger x of
456 Just n | minBound' <= n && n <= maxBound' -> Just (fromInteger n)
459 minBound' = toInteger (minBound :: Int)
460 maxBound' = toInteger (maxBound :: Int)
462 numberToInteger :: Number -> Maybe Integer
468 numberToRational :: Number -> Maybe Rational
471 Left n -> Just (fromInteger n)
474 numberToFloat :: Number -> Maybe Float
477 Left n -> Just (fromInteger n)
478 Right r -> Just (fromRational r)
480 numberToDouble :: Number -> Maybe Double
483 Left n -> Just (fromInteger n)
484 Right r -> Just (fromRational r)
486 ------------------------------------------------------------------------
487 -- other numeric lexing functions
489 readIntP :: Num a => a -> (Char -> Bool) -> (Char -> Int) -> ReadP a
490 readIntP base isDigit valDigit =
491 do s <- munch1 isDigit
492 return (val base 0 (map valDigit s))
494 readIntP' :: Num a => a -> ReadP a
495 readIntP' base = readIntP base isDigit valDigit
497 isDigit c = maybe False (const True) (valDig base c)
498 valDigit c = maybe 0 id (valDig base c)
500 readOctP, readDecP, readHexP :: Num a => ReadP a
501 readOctP = readIntP' 8
502 readDecP = readIntP' 10
503 readHexP = readIntP' 16