Ticket #5688: 0001-Better-handling-of-exponential-notation-when-parsing.patch

File 0001-Better-handling-of-exponential-notation-when-parsing.patch, 3.4 KB (added by gracjan, 4 years ago)
  • GHC/Read.lhs

    From 8797698d93079dd27e4f1428c2aad6a29d4dd1dc Mon Sep 17 00:00:00 2001
    From: Gracjan Polak <[email protected]>
    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 ) 
    6969#endif
    7070import GHC.Num
    7171import GHC.Real
    72 import GHC.Float ()
     72import GHC.Float
    7373import GHC.Show
     74import GHC.Enum
    7475import GHC.Base
    7576import GHC.Arr
    7677-- For defining instances for the generic deriving mechanism
    convertInt :: Num a => L.Lexeme -> ReadPrec a 
    473474convertInt (L.Int i) = return (fromInteger i)
    474475convertInt _         = pfail
    475476
    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
     477clampToInt :: Integer -> Int
     478clampToInt a | a < fromIntegral minBound' = minBound'
     479             | a > fromIntegral maxBound' = maxBound'
     480             | otherwise = fromIntegral a
     481  where
     482     minBound' = minBound
     483     maxBound' = maxBound
     484
     485convertFrac :: RealFloat a => L.Lexeme -> ReadPrec a
     486convertFrac (L.Int i)   = return (fromInteger i)
     487convertFrac (L.Rat r)   = return (fromRational r)
     488convertFrac (L.Exp b e) = return (encodeFloat b (clampToInt e))
     489convertFrac _           = pfail
    480490
    481491instance Read Int where
    482492  readPrec     = readNumber convertInt
  • Text/Read/Lex.hs

    diff --git a/Text/Read/Lex.hs b/Text/Read/Lex.hs
    index e4563b6..ec03830 100644
    a b data Lexeme 
    6767  | Symbol String       -- ^ Haskell symbol, e.g. @>>@, @:%@
    6868  | Int Integer         -- ^ Integer literal
    6969  | Rat Rational        -- ^ Floating point literal
     70  | Exp Integer Integer -- ^ Floating point literal in exponential form a*10^b
    7071  | EOF
    7172 deriving (Eq, Show)
    7273
    lexDecNumber = 
    345346  valueFracExp a Nothing Nothing
    346347    = Int a                                             -- 43
    347348  valueFracExp a Nothing (Just exp)
    348     | exp >= 0  = Int (a * (10 ^ exp))                  -- 43e7
    349     | otherwise = Rat (a % (10 ^ (-exp)))               -- 43e-7
     349    = Exp a exp
    350350  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
    356352
    357353lexFrac :: ReadP (Maybe Digits)
    358354-- Read the fractional part; fail if it doesn't
    val base y (x:xs) = y' `seq` val base y' xs 
    404400--
    405401-- frac was never used with anything but Integer and base 10, so
    406402-- 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)
     403fracExp :: Integer -> Integer -> Digits -> (Integer,Integer)
     404fracExp exp mant [] = (mant, exp)
    411405fracExp exp mant (d:ds) = exp' `seq` mant' `seq` fracExp exp' mant' ds
    412406  where
    413407    exp'  = exp - 1