module PrelRead where
-import {-# SOURCE #-} PrelErr ( error )
+import PrelErr ( error )
+import PrelEnum ( Enum(..) )
import PrelNum
-import PrelNumExtra
+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, userError )
+-- needed for readIO and instance Read Buffermode
+import PrelIOBase ( IO, userError, BufferMode(..) )
import PrelException ( ioError )
\end{code}
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}
(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
('x':rs) -> (isHexDigit, rs, False)
('X':rs) -> (isHexDigit, rs, False)
_ -> (isDigit, s, True)
-
- (ds,s) <- return (span pred s')
- (fe,t) <- lexFracExp isDec s
+-}
+ (ds,s) <- return (span isDigit s)
+ (fe,t) <- lexFracExp s
return (c:ds++fe,t)
| otherwise = mzero -- bad character
where
isSym c = c `elem` "!@#$%&*+./<=>?\\^|:-~"
isIdChar c = isAlphaNum c || c `elem` "_'"
- lexFracExp True ('.':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
(esc,t) <- lexEsc s
return ('\\':esc, t)
where
- lexEsc (c:s) | c `elem` "abfnrtv\\\"'" = return ([c],s)
- lexEsc s@(d:_) | isDigit d = lexDecDigits s
- lexEsc ('o':d:s) | isDigit d = lexOctDigits (d:s)
- lexEsc ('O':d:s) | isDigit d = lexOctDigits (d:s)
- lexEsc ('x':d:s) | isDigit d = lexHexDigits (d:s)
- lexEsc ('X':d:s) | isDigit d = 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
+ 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)
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 "" = 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}
%*********************************************************
#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}