From 8797698d93079dd27e4f1428c2aad6a29d4dd1dc Mon Sep 17 00:00:00 2001
From: Gracjan Polak <gracjanpolak@gmail.com>
Date: Fri, 9 Dec 2011 00:36:52 +0100
Subject: [PATCH] Better handling of exponential notation when parsing decimal
lexemes, fixes #5688

GHC/Read.lhs  20 +++++++++++++++
Text/Read/Lex.hs  16 +++++
2 files changed, 20 insertions(+), 16 deletions()
diff git a/GHC/Read.lhs b/GHC/Read.lhs
index fcbdb8e..8b4ec0b 100644
a

b

import {# SOURCE #} GHC.Unicode ( isDigit ) 
69  69  #endif 
70  70  import GHC.Num 
71  71  import GHC.Real 
72   import GHC.Float () 
 72  import GHC.Float 
73  73  import GHC.Show 
 74  import GHC.Enum 
74  75  import GHC.Base 
75  76  import GHC.Arr 
76  77   For defining instances for the generic deriving mechanism 
… 
… 
convertInt :: Num a => L.Lexeme > ReadPrec a 
473  474  convertInt (L.Int i) = return (fromInteger i) 
474  475  convertInt _ = pfail 
475  476  
476   convertFrac :: Fractional a => L.Lexeme > ReadPrec a 
477   convertFrac (L.Int i) = return (fromInteger i) 
478   convertFrac (L.Rat r) = return (fromRational r) 
479   convertFrac _ = pfail 
 477  clampToInt :: Integer > Int 
 478  clampToInt a  a < fromIntegral minBound' = minBound' 
 479   a > fromIntegral maxBound' = maxBound' 
 480   otherwise = fromIntegral a 
 481  where 
 482  minBound' = minBound 
 483  maxBound' = maxBound 
 484  
 485  convertFrac :: RealFloat a => L.Lexeme > ReadPrec a 
 486  convertFrac (L.Int i) = return (fromInteger i) 
 487  convertFrac (L.Rat r) = return (fromRational r) 
 488  convertFrac (L.Exp b e) = return (encodeFloat b (clampToInt e)) 
 489  convertFrac _ = pfail 
480  490  
481  491  instance Read Int where 
482  492  readPrec = readNumber convertInt 
diff git a/Text/Read/Lex.hs b/Text/Read/Lex.hs
index e4563b6..ec03830 100644
a

b

data Lexeme 
67  67   Symbol String  ^ Haskell symbol, e.g. @>>@, @:%@ 
68  68   Int Integer  ^ Integer literal 
69  69   Rat Rational  ^ Floating point literal 
 70   Exp Integer Integer  ^ Floating point literal in exponential form a*10^b 
70  71   EOF 
71  72  deriving (Eq, Show) 
72  73  
… 
… 
lexDecNumber = 
345  346  valueFracExp a Nothing Nothing 
346  347  = Int a  43 
347  348  valueFracExp a Nothing (Just exp) 
348    exp >= 0 = Int (a * (10 ^ exp))  43e7 
349    otherwise = Rat (a % (10 ^ (exp)))  43e7 
 349  = Exp a exp 
350  350  valueFracExp a (Just fs) mExp  4.3[e2] 
351   = Rat (fracExp (fromMaybe 0 mExp) a fs) 
352    Be a bit more efficient in calculating the Rational. 
353    Instead of calculating the fractional part alone, then 
354    adding the integral part and finally multiplying with 
355    10 ^ exp if an exponent was given, do it all at once. 
 351  = let (a,e) = fracExp (fromMaybe 0 mExp) a fs in Exp a e 
356  352  
357  353  lexFrac :: ReadP (Maybe Digits) 
358  354   Read the fractional part; fail if it doesn't 
… 
… 
val base y (x:xs) = y' `seq` val base y' xs 
404  400   
405  401   frac was never used with anything but Integer and base 10, so 
406  402   those are hardcoded now (trivial to change if necessary). 
407   fracExp :: Integer > Integer > Digits > Rational 
408   fracExp exp mant [] 
409    exp < 0 = mant % (10 ^ (exp)) 
410    otherwise = fromInteger (mant * 10 ^ exp) 
 403  fracExp :: Integer > Integer > Digits > (Integer,Integer) 
 404  fracExp exp mant [] = (mant, exp) 
411  405  fracExp exp mant (d:ds) = exp' `seq` mant' `seq` fracExp exp' mant' ds 
412  406  where 
413  407  exp' = exp  1 