) where
import PrelBase
-import PrelRead (readLitChar, lexLitChar)
+import PrelRead (readLitChar, lexLitChar, digitToInt)
import {-# SOURCE #-} PrelErr ( error )
\end{code}
-
-\begin{code}
--- Digit conversion operations
-
-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}
(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}
%*********************************************************
--- /dev/null
+lex '\X00' = [("'\\x00'","")]
+lex '\x0f2' = [("'\\x0f2'","")]
+lex '\xf2' = [("'\\xf2'","")]
+lex '\xf2t' = []
+lex '\X24' = [("'\\x24'","")]
+lex '\x24b' = []
+lex '\Xa4b' = []
+lex '\xa4bg' = []
+lex '\o00' = [("'\\o00'","")]
+lex '\o05' = [("'\\o05'","")]
+lex '\o50' = [("'\\o50'","")]
+lex '\o72' = [("'\\o72'","")]
+lex '\o82' = []
+lex '\O24' = [("'\\o24'","")]
+lex '\O000024' = [("'\\o000024'","")]
+lex '\024b' = []
+lex '\o14b' = []
+lex '\0a4bg' = []