[project @ 2001-08-04 06:19:54 by ken]
[ghc-hetmet.git] / ghc / lib / std / PrelRead.lhs
index 600bde0..f8a2636 100644 (file)
@@ -1,5 +1,7 @@
+% ------------------------------------------------------------------------------
+% $Id: PrelRead.lhs,v 1.20 2001/05/23 09:28:44 simonmar Exp $
 %
-% (c) The AQUA Project, Glasgow University, 1994-1998
+% (c) The University of Glasgow, 1994-2000
 %
 
 \section[PrelRead]{Module @PrelRead@}
@@ -11,18 +13,15 @@ Instances of the Read class.
 
 module PrelRead where
 
-import {-# SOURCE #-} PrelErr ( error )
+import {-# SOURCE #-} PrelErr          ( error )
+import PrelEnum                ( Enum(..), maxBound )
 import PrelNum
+import PrelReal
+import PrelFloat
 import PrelList
-import PrelTup
 import PrelMaybe
-import PrelEither
+import PrelShow                -- isAlpha etc
 import PrelBase
-import Monad
-
--- needed for readIO.
-import PrelIOBase ( IO, fail, userError )
-
 \end{code}
 
 %*********************************************************
@@ -56,6 +55,22 @@ class  Read a  where
     readList   = readList__ reads
 \end{code}
 
+In this module we treat [(a,String)] as a monad in MonadPlus
+But MonadPlus isn't defined yet, so we simply give local
+declarations for mzero and guard suitable for this particular
+type.  It would also be reasonably to move MonadPlus to PrelBase
+along with Monad and Functor, but that seems overkill for one 
+example
+
+\begin{code}
+mzero :: [a]
+mzero = []
+
+guard :: Bool -> [()]
+guard True  = [()]
+guard False = []
+\end{code}
+
 %*********************************************************
 %*                                                     *
 \subsection{Utility functions}
@@ -71,30 +86,17 @@ read s          =
    case read_s s of
 #ifndef NEW_READS_REP
       [x]     -> x
-      []      -> error "PreludeText.read: no parse"
-      _              -> error "PreludeText.read: ambiguous parse"
+      []      -> error "Prelude.read: no parse"
+      _              -> error "Prelude.read: ambiguous parse"
 #else
       Just x  -> x
-      Nothing -> error "PreludeText.read: no parse"
+      Nothing -> error "Prelude.read: no parse"
 #endif
  where
-  read_s s = do
-    (x,t)   <- reads s
-    ("","") <- lex t
+  read_s str = do
+    (x,str1) <- reads str
+    ("","")  <- lex str1
     return x
-
-  -- raises an exception instead of an error
-readIO          :: Read a => String -> IO a
-readIO s        =  case (do { (x,t) <- reads s ; ("","") <- lex t ; return x }) of
-#ifndef NEW_READS_REP
-                       [x]    -> return x
-                       []     -> fail (userError "PreludeIO.readIO: no parse")
-                       _      -> fail (userError "PreludeIO.readIO: ambiguous parse")
-#else
-                        Just x -> return x
-                        Nothing  -> fail (userError "PreludeIO.readIO: no parse")
-#endif
-
 \end{code}
 
 \begin{code}
@@ -172,35 +174,55 @@ lex (c:s) | isSingle c = return ([c],s)
                (nam,t) <- return (span isIdChar s)
                return (c:nam, t)
           | isDigit c  = do
+{- Removed, 13/03/2000 by SDM.
+   Doesn't work, and not required by Haskell report.
+                let
+                 (pred, s', isDec) =
+                   case s of
+                     ('o':rs) -> (isOctDigit, rs, False)
+                     ('O':rs) -> (isOctDigit, rs, False)
+                     ('x':rs) -> (isHexDigit, rs, False)
+                     ('X':rs) -> (isHexDigit, rs, False)
+                     _        -> (isDigit, s, True)
+-}
                 (ds,s)  <- return (span isDigit s)
                 (fe,t)  <- lexFracExp s
                 return (c:ds++fe,t)
-          | otherwise  = zero    -- bad character
+          | otherwise  = mzero    -- bad character
              where
               isSingle c =  c `elem` ",;()[]{}_`"
               isSym c    =  c `elem` "!@#$%&*+./<=>?\\^|:-~"
-              isIdChar c =  isAlphanum c || c `elem` "_'"
+              isIdChar c =  isAlphaNum c || c `elem` "_'"
 
-              lexFracExp ('.':cs)   = do
+              lexFracExp ('.':c:cs) | isDigit c = do
                        (ds,t) <- lex0Digits cs
                        (e,u)  <- lexExp t
-                       return ('.':ds++e,u)
-              lexFracExp s          = return ("",s)
+                       return ('.':c:ds++e,u)
+              lexFracExp s        = return ("",s)
 
               lexExp (e:s) | e `elem` "eE" = 
                  (do
                    (c:t) <- return s
                    guard (c `elem` "+-")
-                   (ds,u) <- lexDigits t
+                   (ds,u) <- lexDecDigits t
                    return (e:c:ds,u))      ++
                  (do
-                   (ds,t) <- lexDigits s
+                   (ds,t) <- lexDecDigits s
                    return (e:ds,t))
 
               lexExp s = return ("",s)
 
-lexDigits               :: ReadS String 
-lexDigits               =  nonnull isDigit
+lexDigits           :: ReadS String
+lexDigits            = lexDecDigits
+
+lexDecDigits            :: ReadS String 
+lexDecDigits            =  nonnull isDigit
+
+lexOctDigits            :: ReadS String 
+lexOctDigits            =  nonnull isOctDigit
+
+lexHexDigits            :: ReadS String 
+lexHexDigits            =  nonnull isHexDigit
 
 -- 0 or more digits
 lex0Digits               :: ReadS String 
@@ -215,13 +237,56 @@ lexLitChar              :: ReadS String
 lexLitChar ('\\':s)     =  do
            (esc,t) <- lexEsc s
            return ('\\':esc, t)
-        where
-        lexEsc (c:s)     | c `elem` "abfnrtv\\\"'" = return ([c],s)
-        lexEsc s@(d:_)   | isDigit d               = lexDigits s
-        lexEsc _                                   = zero
+       where
+        lexEsc (c:s)     | c `elem` escChars = return ([c],s)
+        lexEsc s@(d:_)   | isDigit d         = checkSize 10 lexDecDigits s
+        lexEsc ('o':d:s) | isOctDigit d      = checkSize  8 lexOctDigits (d:s)
+        lexEsc ('O':d:s) | isOctDigit d      = checkSize  8 lexOctDigits (d:s)
+        lexEsc ('x':d:s) | isHexDigit d      = checkSize 16 lexHexDigits (d:s)
+        lexEsc ('X':d:s) | isHexDigit d      = checkSize 16 lexHexDigits (d:s)
+       lexEsc ('^':c:s) | c >= '@' && c <= '_' = [(['^',c],s)] -- cf. cntrl in 2.6 of H. report.
+       lexEsc s@(c:_)   | isUpper c            = fromAsciiLab s
+        lexEsc _                                = mzero
+
+       escChars = "abfnrtv\\\"'"
+
+        fromAsciiLab (x:y:z:ls) | isUpper y && (isUpper z || isDigit z) &&
+                                  [x,y,z] `elem` asciiEscTab = return ([x,y,z], ls)
+        fromAsciiLab (x:y:ls)   | isUpper y &&
+                                  [x,y]   `elem` asciiEscTab = return ([x,y], ls)
+        fromAsciiLab _                                       = mzero
+
+        asciiEscTab = "DEL" : asciiTab
+
+        {-
+          Check that the numerically escaped char literals are
+          within accepted boundaries.
+          
+          Note: this allows char lits with leading zeros, i.e.,
+                \0000000000000000000000000000001. 
+        -}
+        checkSize base f str = do
+          (num, res) <- f str
+          if toAnInteger base num > toInteger (ord maxBound) then 
+             mzero
+           else
+             case base of
+                8  -> return ('o':num, res)
+                16 -> return ('x':num, res)
+                _  -> return (num, res)
+
+       toAnInteger base = foldl (\ acc n -> acc*base + toInteger (digitToInt n)) 0
+
 
 lexLitChar (c:s)        =  return ([c],s)
-lexLitChar ""           =  zero
+lexLitChar ""           =  mzero
+
+digitToInt :: Char -> Int
+digitToInt c
+ | isDigit c           =  fromEnum c - fromEnum '0'
+ | c >= 'a' && c <= 'f' =  fromEnum c - fromEnum 'a' + 10
+ | c >= 'A' && c <= 'F' =  fromEnum c - fromEnum 'A' + 10
+ | otherwise           =  error ("Char.digitToInt: not a digit " ++ show c) -- sigh
 \end{code}
 
 %*********************************************************
@@ -232,10 +297,10 @@ lexLitChar ""           =  zero
 
 \begin{code}
 instance  Read Char  where
-    readsPrec p      = readParen False
+    readsPrec _      = readParen False
                            (\r -> do
                                ('\'':s,t) <- lex r
-                               (c,_)      <- readLitChar s
+                               (c,"\'")   <- readLitChar s
                                return (c,t))
 
     readList = readParen False (\r -> do
@@ -250,7 +315,7 @@ instance  Read Char  where
                            return (c:cs,u)
 
 instance Read Bool where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                        (\r ->
                           lex r >>= \ lr ->
                           (do { ("True", rest)  <- return lr ; return (True,  rest) }) ++
@@ -258,7 +323,7 @@ instance Read Bool where
                
 
 instance Read Ordering where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                        (\r -> 
                           lex r >>= \ lr ->
                           (do { ("LT", rest) <- return lr ; return (LT,  rest) }) ++
@@ -266,7 +331,7 @@ instance Read Ordering where
                           (do { ("GT", rest) <- return lr ; return (GT, rest) }))
 
 instance Read a => Read (Maybe a) where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                        (\r -> 
                            lex r >>= \ lr ->
                            (do { ("Nothing", rest) <- return lr ; return (Nothing, rest)}) ++
@@ -276,7 +341,7 @@ instance Read a => Read (Maybe a) where
                                return (Just x, rest2)))
 
 instance (Read a, Read b) => Read (Either a b) where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                        (\r ->
                            lex r >>= \ lr ->
                            (do 
@@ -289,16 +354,16 @@ instance (Read a, Read b) => Read (Either a b) where
                                return (Right x, rest2)))
 
 instance  Read Int  where
-    readsPrec p x = readSigned readDec x
+    readsPrec _ x = readSigned readDec x
 
 instance  Read Integer  where
-    readsPrec p x = readSigned readDec x
+    readsPrec _ x = readSigned readDec x
 
 instance  Read Float  where
-    readsPrec p x = readSigned readFloat x
+    readsPrec _ x = readSigned readFloat x
 
 instance  Read Double  where
-    readsPrec p x = readSigned readFloat x
+    readsPrec _ x = readSigned readFloat x
 
 instance  (Integral a, Read a)  => Read (Ratio a)  where
     readsPrec p  =  readParen (p > ratio_prec)
@@ -309,17 +374,17 @@ instance  (Integral a, Read a)  => Read (Ratio a)  where
                                return (x%y,u))
 
 instance  (Read a) => Read [a]  where
-    readsPrec p         = readList
+    readsPrec _         = readList
 
 instance Read () where
-    readsPrec p    = readParen False
+    readsPrec _    = readParen False
                             (\r -> do
                                ("(",s) <- lex r
                                (")",t) <- lex s
                                return ((),t))
 
 instance  (Read a, Read b) => Read (a,b)  where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                             (\r -> do
                                ("(",s) <- lex r
                                (x,t)   <- readsPrec 0 s
@@ -329,7 +394,7 @@ instance  (Read a, Read b) => Read (a,b)  where
                                return ((x,y), w))
 
 instance (Read a, Read b, Read c) => Read (a, b, c) where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                             (\a -> do
                                ("(",b) <- lex a
                                (x,c)   <- readsPrec 0 b
@@ -341,7 +406,7 @@ instance (Read a, Read b, Read c) => Read (a, b, c) where
                                return ((x,y,z), h))
 
 instance (Read a, Read b, Read c, Read d) => Read (a, b, c, d) where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                             (\a -> do
                                ("(",b) <- lex a
                                (w,c)   <- readsPrec 0 b
@@ -355,7 +420,7 @@ instance (Read a, Read b, Read c, Read d) => Read (a, b, c, d) where
                                return ((w,x,y,z), i))
 
 instance (Read a, Read b, Read c, Read d, Read e) => Read (a, b, c, d, e) where
-    readsPrec p = readParen False
+    readsPrec _ = readParen False
                             (\a -> do
                                ("(",b) <- lex a
                                (v,c)   <- readsPrec 0 b
@@ -381,6 +446,7 @@ instance (Read a, Read b, Read c, Read d, Read e) => Read (a, b, c, d, e) where
 \begin{code}
 readLitChar            :: ReadS Char
 
+readLitChar []         =  mzero
 readLitChar ('\\':s)   =  readEsc s
        where
        readEsc ('a':s)  = return ('\a',s)
@@ -411,8 +477,8 @@ readLitChar ('\\':s)        =  readEsc s
                           in case [(c,s') | (c, mne) <- table,
                                             ([],s') <- [match mne s]]
                              of (pr:_) -> return pr
-                                []     -> zero
-       readEsc _        = zero
+                                []     -> mzero
+       readEsc _        = mzero
 
 readLitChar (c:s)      =  return (c,s)
 
@@ -437,26 +503,27 @@ include lexing common prefixes such as '0x' or '0o' etc.
                ReadS Int,
                ReadS Integer #-}
 readDec :: (Integral a) => ReadS a
-readDec = readInt 10 isDigit (\d -> ord d - ord_0)
+readDec = readInt 10 isDigit (\d -> ord d - ord '0')
 
 {-# SPECIALISE readOct :: 
                ReadS Int,
                ReadS Integer #-}
 readOct :: (Integral a) => ReadS a
-readOct = readInt 8 isOctDigit (\d -> ord d - ord_0)
+readOct = readInt 8 isOctDigit (\d -> ord d - ord '0')
 
 {-# SPECIALISE readHex :: 
                ReadS Int,
                ReadS Integer #-}
 readHex :: (Integral a) => ReadS a
 readHex = readInt 16 isHexDigit hex
-           where hex d = ord d - (if isDigit d then ord_0
+           where hex d = ord d - (if isDigit d then ord '0'
                                   else ord (if isUpper d then 'A' else 'a') - 10)
 
 readInt :: (Integral a) => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a
 readInt radix isDig digToInt s = do
     (ds,r) <- nonnull isDig s
-    return (foldl1 (\n d -> n * radix + d) (map (fromInt . digToInt) ds), r)
+    return (foldl1 (\n d -> n * radix + d)
+                   (map (fromInteger . toInteger . digToInt) ds), r)
 
 {-# SPECIALISE readSigned ::
                ReadS Int     -> ReadS Int,
@@ -504,7 +571,7 @@ readRational r =
       return (1/0,t) )
  where
      readFix r = do
-       (ds,s)  <- lexDigits r
+       (ds,s)  <- lexDecDigits r
        (ds',t) <- lexDotDigits s
        return (read (ds++ds'), length ds', t)