From 2797941c7841a09a18904928e9dd47268c712e45 Mon Sep 17 00:00:00 2001
From: Gracjan Polak <gracjanpolak@gmail.com>
Date: Mon, 12 Dec 2011 15:17:55 +0100
exponential notation can be safely parsed.

Fixes #5688 and #3897

instance Read Integer/Rational/Double readsPrec out of memory and crash due to exponential notation

and

reading a large String as Double takes too long
---
index fcbdb8e..963cb74 100644
diff --git a/Text/Read/Lex.hs b/Text/Read/Lex.hs
index e4563b6..ec03830 100644
 a data Lexeme | Symbol String       -- ^ Haskell symbol, e.g. @>>@, @:%@ | Int Integer         -- ^ Integer literal | Rat Rational        -- ^ Floating point literal | Exp Integer Integer -- ^ Floating point literal in exponential form a*10^b | EOF deriving (Eq, Show) lexDecNumber = valueFracExp a Nothing Nothing = Int a                                             -- 43 valueFracExp a Nothing (Just exp) | exp >= 0  = Int (a * (10 ^ exp))                  -- 43e7 | otherwise = Rat (a % (10 ^ (-exp)))               -- 43e-7 = Exp a exp valueFracExp a (Just fs) mExp                         -- 4.3[e2] = Rat (fracExp (fromMaybe 0 mExp) a fs) -- Be a bit more efficient in calculating the Rational. -- Instead of calculating the fractional part alone, then -- adding the integral part and finally multiplying with -- 10 ^ exp if an exponent was given, do it all at once. = let (a,e) = fracExp (fromMaybe 0 mExp) a fs in Exp a e lexFrac :: ReadP (Maybe Digits) -- Read the fractional part; fail if it doesn't val base y (x:xs) = y' seq val base y' xs -- -- frac was never used with anything but Integer and base 10, so -- those are hardcoded now (trivial to change if necessary). fracExp :: Integer -> Integer -> Digits -> Rational fracExp exp mant [] | exp < 0     = mant % (10 ^ (-exp)) | otherwise   = fromInteger (mant * 10 ^ exp) fracExp :: Integer -> Integer -> Digits -> (Integer,Integer) fracExp exp mant [] = (mant, exp) fracExp exp mant (d:ds) = exp' seq mant' seq fracExp exp' mant' ds where exp'  = exp - 1