[project @ 2000-04-10 12:12:27 by simonpj]
[ghc-hetmet.git] / ghc / lib / std / PrelRead.lhs
index 600bde0..3f64865 100644 (file)
@@ -11,18 +11,20 @@ Instances of the Read class.
 
 module PrelRead where
 
-import {-# SOURCE #-} PrelErr ( error )
+import PrelErr         ( error )
+import PrelEnum                ( Enum(..) )
 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 )
 
+-- needed for readIO and instance Read Buffermode
+import PrelIOBase ( IO, userError, BufferMode(..) )
+import PrelException ( ioError )
 \end{code}
 
 %*********************************************************
@@ -56,6 +58,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,16 +89,16 @@ 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
@@ -88,11 +106,11 @@ 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")
+                       []     -> ioError (userError "Prelude.readIO: no parse")
+                       _      -> ioError (userError "Prelude.readIO: ambiguous parse")
 #else
                         Just x -> return x
-                        Nothing  -> fail (userError "PreludeIO.readIO: no parse")
+                        Nothing  -> ioError (userError "Prelude.readIO: no parse")
 #endif
 
 \end{code}
@@ -172,35 +190,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 +253,57 @@ 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
+             -- Note: this is assumes that a Char is 8 bits long.
+          if (toAnInt base num) > 255 then 
+             mzero
+           else
+             case base of
+                8  -> return ('o':num, res)
+                16 -> return ('x':num, res)
+                _  -> return (num, res)
+
+       toAnInt base xs = foldl (\ acc n -> acc*base + n) 0 (map digitToInt xs)
+
 
 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 +314,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 +332,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 +340,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 +348,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 +358,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 +371,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 +391,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 +411,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 +423,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 +437,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 +463,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 +494,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)
 
@@ -504,7 +587,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)
 
@@ -539,3 +622,26 @@ readRational__ top_s
 #endif
 
 \end{code}
+
+%*********************************************************
+%*                                                     *
+\subsection{Reading BufferMode}
+%*                                                     *
+%*********************************************************
+
+This instance decl is here rather than somewhere more appropriate in
+order that we can avoid both orphan-instance modules and recursive
+dependencies.
+
+\begin{code}
+instance Read BufferMode where
+    readsPrec _ = 
+      readParen False
+       (\r ->  let lr = lex r
+               in
+               [(NoBuffering, rest)       | ("NoBuffering", rest) <- lr] ++
+               [(LineBuffering,rest)      | ("LineBuffering",rest) <- lr] ++
+               [(BlockBuffering mb,rest2) | ("BlockBuffering",rest1) <- lr,
+                                            (mb, rest2) <- reads rest1])
+
+\end{code}