{-# LANGUAGE LambdaCase #-}

{-| Simple module to provide functions that read Fortran literals -}
module Language.Fortran.Parser.Utils
  ( readReal
  , readInteger
  , parseRealLiteral
  , RealLit(..)
  , Exponent(..)
  , NumSign(..)
  , ExponentLetter(..)
  ) where

import Language.Fortran.AST (Kind)

import Data.Char
import Numeric
import Text.Read (readMaybe)

breakAtDot :: String -> (String, String)
replaceDwithE :: Char -> Char
readsToMaybe :: [(a, b)] -> Maybe a
fixAtDot :: (String, String) -> (String, String)
fixAtDot' :: (String, String) -> (String, String)
combineAtDot :: (String, String) -> String

-- | Convert a Fortran literal Real into a Haskell Double.
readReal :: String -> Maybe Double
readReal :: [Char] -> Maybe Double
readReal = [(Double, [Char])] -> Maybe Double
forall a b. [(a, b)] -> Maybe a
readsToMaybe ([(Double, [Char])] -> Maybe Double)
-> ([Char] -> [(Double, [Char])]) -> [Char] -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [(Double, [Char])]
forall a. Read a => ReadS a
reads ([Char] -> [(Double, [Char])])
-> ([Char] -> [Char]) -> [Char] -> [(Double, [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'+') ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Char]) -> [Char]
combineAtDot (([Char], [Char]) -> [Char])
-> ([Char] -> ([Char], [Char])) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Char]) -> ([Char], [Char])
fixAtDot (([Char], [Char]) -> ([Char], [Char]))
-> ([Char] -> ([Char], [Char])) -> [Char] -> ([Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ([Char], [Char])
breakAtDot ([Char] -> ([Char], [Char]))
-> ([Char] -> [Char]) -> [Char] -> ([Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
replaceDwithE ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'_')

-- | Convert a Fortran literal Integer into a Haskell Integer.
readInteger :: String -> Maybe Integer
readInteger :: [Char] -> Maybe Integer
readInteger [Char]
s = [(Integer, [Char])] -> Maybe Integer
forall a b. [(a, b)] -> Maybe a
readsToMaybe ([(Integer, [Char])] -> Maybe Integer)
-> [(Integer, [Char])] -> Maybe Integer
forall a b. (a -> b) -> a -> b
$ case [Char]
s' of
  Char
'b':[Char]
_ -> Integer -> (Char -> Bool) -> (Char -> Kind) -> ReadS Integer
forall a. Num a => a -> (Char -> Bool) -> (Char -> Kind) -> ReadS a
readInt Integer
2 (Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char]
"01") Char -> Kind
digitToInt (Kind -> [Char] -> [Char]
forall a. Kind -> [a] -> [a]
drop Kind
2 [Char]
s')
  Char
'o':[Char]
_ -> Integer -> (Char -> Bool) -> (Char -> Kind) -> ReadS Integer
forall a. Num a => a -> (Char -> Bool) -> (Char -> Kind) -> ReadS a
readInt Integer
8 (Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'0'..Char
'7']) Char -> Kind
digitToInt (Kind -> [Char] -> [Char]
forall a. Kind -> [a] -> [a]
drop Kind
2 [Char]
s')
  Char
'z':[Char]
_ -> Integer -> (Char -> Bool) -> (Char -> Kind) -> ReadS Integer
forall a. Num a => a -> (Char -> Bool) -> (Char -> Kind) -> ReadS a
readInt Integer
16 (Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ([Char
'0'..Char
'9'] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char
'A'..Char
'F'] [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char
'a'..Char
'f'])) Char -> Kind
digitToInt (Kind -> [Char] -> [Char]
forall a. Kind -> [a] -> [a]
drop Kind
2 [Char]
s')
  [Char]
_     -> ReadS Integer -> ReadS Integer
forall a. Real a => ReadS a -> ReadS a
readSigned ReadS Integer
forall a. (Eq a, Num a) => ReadS a
readDec [Char]
s'
  where
    s' :: [Char]
s' = (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'+') ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'_') ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ [Char]
s

fixAtDot' :: ([Char], [Char]) -> ([Char], [Char])
fixAtDot' ([Char]
"", [Char]
r)                      = ([Char]
"0", [Char]
r)
fixAtDot' ([Char]
"-", [Char]
r)                     = ([Char]
"-0", [Char]
r)
fixAtDot' ([Char]
l, [Char]
"")                      = ([Char]
l, [Char]
"0")
fixAtDot' ([Char]
l, Char
r0:[Char]
r) | Bool -> Bool
not (Char -> Bool
isDigit Char
r0) = ([Char]
l, Char
'0'Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:Char
r0Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
r)
fixAtDot' ([Char], [Char])
x                            = ([Char], [Char])
x

combineAtDot :: ([Char], [Char]) -> [Char]
combineAtDot ([Char]
a, [Char]
b) = [Char]
a [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"." [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
b
fixAtDot :: ([Char], [Char]) -> ([Char], [Char])
fixAtDot ([Char], [Char])
x
  | ([Char], [Char])
x ([Char], [Char]) -> ([Char], [Char]) -> Bool
forall a. Eq a => a -> a -> Bool
== ([Char], [Char])
x'         = ([Char], [Char])
x
  | Bool
otherwise       = ([Char], [Char]) -> ([Char], [Char])
fixAtDot ([Char], [Char])
x' where x' :: ([Char], [Char])
x' = ([Char], [Char]) -> ([Char], [Char])
fixAtDot' ([Char], [Char])
x
breakAtDot :: [Char] -> ([Char], [Char])
breakAtDot          = ([Char] -> [Char]) -> ([Char], [Char]) -> ([Char], [Char])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Kind -> [Char] -> [Char]
forall a. Kind -> [a] -> [a]
drop Kind
1) (([Char], [Char]) -> ([Char], [Char]))
-> ([Char] -> ([Char], [Char])) -> [Char] -> ([Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> [Char] -> ([Char], [Char])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'.')
replaceDwithE :: Char -> Char
replaceDwithE Char
'd'   = Char
'e'
replaceDwithE Char
c     = Char
c

readsToMaybe :: forall a b. [(a, b)] -> Maybe a
readsToMaybe [(a, b)]
r = case [(a, b)]
r of
  (a
x, b
_):[(a, b)]
_ -> a -> Maybe a
forall a. a -> Maybe a
Just a
x
  [(a, b)]
_ -> Maybe a
forall a. Maybe a
Nothing

--------------------------------------------------------------------------------

-- TODO limitation
-- Kind params allow 'Name's as well (which are checked at compile time to be a
-- special type of constant expression). We limit ourselves to integer kind
-- params only, because currently we don't handle full kind params in the later
-- stages anyway.
type KindParam = Kind

-- | A REAL literal may have an optional exponent and kind.
--
-- The value can be retrieved as a 'Double' by using these parts.
data RealLit = RealLit
  { RealLit -> [Char]
realLitValue     :: String -- xyz.abc, xyz, xyz., .abc
  , RealLit -> Maybe Exponent
realLitExponent  :: Maybe Exponent
  , RealLit -> Maybe Kind
realLitKindParam :: Maybe KindParam
  } deriving (RealLit -> RealLit -> Bool
(RealLit -> RealLit -> Bool)
-> (RealLit -> RealLit -> Bool) -> Eq RealLit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RealLit -> RealLit -> Bool
$c/= :: RealLit -> RealLit -> Bool
== :: RealLit -> RealLit -> Bool
$c== :: RealLit -> RealLit -> Bool
Eq, Eq RealLit
Eq RealLit
-> (RealLit -> RealLit -> Ordering)
-> (RealLit -> RealLit -> Bool)
-> (RealLit -> RealLit -> Bool)
-> (RealLit -> RealLit -> Bool)
-> (RealLit -> RealLit -> Bool)
-> (RealLit -> RealLit -> RealLit)
-> (RealLit -> RealLit -> RealLit)
-> Ord RealLit
RealLit -> RealLit -> Bool
RealLit -> RealLit -> Ordering
RealLit -> RealLit -> RealLit
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: RealLit -> RealLit -> RealLit
$cmin :: RealLit -> RealLit -> RealLit
max :: RealLit -> RealLit -> RealLit
$cmax :: RealLit -> RealLit -> RealLit
>= :: RealLit -> RealLit -> Bool
$c>= :: RealLit -> RealLit -> Bool
> :: RealLit -> RealLit -> Bool
$c> :: RealLit -> RealLit -> Bool
<= :: RealLit -> RealLit -> Bool
$c<= :: RealLit -> RealLit -> Bool
< :: RealLit -> RealLit -> Bool
$c< :: RealLit -> RealLit -> Bool
compare :: RealLit -> RealLit -> Ordering
$ccompare :: RealLit -> RealLit -> Ordering
Ord, Kind -> RealLit -> [Char] -> [Char]
[RealLit] -> [Char] -> [Char]
RealLit -> [Char]
(Kind -> RealLit -> [Char] -> [Char])
-> (RealLit -> [Char])
-> ([RealLit] -> [Char] -> [Char])
-> Show RealLit
forall a.
(Kind -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [RealLit] -> [Char] -> [Char]
$cshowList :: [RealLit] -> [Char] -> [Char]
show :: RealLit -> [Char]
$cshow :: RealLit -> [Char]
showsPrec :: Kind -> RealLit -> [Char] -> [Char]
$cshowsPrec :: Kind -> RealLit -> [Char] -> [Char]
Show)

-- | An exponent is an exponent letter (E, D) and a value (with an optional
-- sign).
data Exponent = Exponent
  { Exponent -> ExponentLetter
expLetter :: ExponentLetter
  , Exponent -> Maybe NumSign
expSign   :: Maybe NumSign
  , Exponent -> Kind
expNum    :: Int
  } deriving (Exponent -> Exponent -> Bool
(Exponent -> Exponent -> Bool)
-> (Exponent -> Exponent -> Bool) -> Eq Exponent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Exponent -> Exponent -> Bool
$c/= :: Exponent -> Exponent -> Bool
== :: Exponent -> Exponent -> Bool
$c== :: Exponent -> Exponent -> Bool
Eq, Eq Exponent
Eq Exponent
-> (Exponent -> Exponent -> Ordering)
-> (Exponent -> Exponent -> Bool)
-> (Exponent -> Exponent -> Bool)
-> (Exponent -> Exponent -> Bool)
-> (Exponent -> Exponent -> Bool)
-> (Exponent -> Exponent -> Exponent)
-> (Exponent -> Exponent -> Exponent)
-> Ord Exponent
Exponent -> Exponent -> Bool
Exponent -> Exponent -> Ordering
Exponent -> Exponent -> Exponent
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Exponent -> Exponent -> Exponent
$cmin :: Exponent -> Exponent -> Exponent
max :: Exponent -> Exponent -> Exponent
$cmax :: Exponent -> Exponent -> Exponent
>= :: Exponent -> Exponent -> Bool
$c>= :: Exponent -> Exponent -> Bool
> :: Exponent -> Exponent -> Bool
$c> :: Exponent -> Exponent -> Bool
<= :: Exponent -> Exponent -> Bool
$c<= :: Exponent -> Exponent -> Bool
< :: Exponent -> Exponent -> Bool
$c< :: Exponent -> Exponent -> Bool
compare :: Exponent -> Exponent -> Ordering
$ccompare :: Exponent -> Exponent -> Ordering
Ord, Kind -> Exponent -> [Char] -> [Char]
[Exponent] -> [Char] -> [Char]
Exponent -> [Char]
(Kind -> Exponent -> [Char] -> [Char])
-> (Exponent -> [Char])
-> ([Exponent] -> [Char] -> [Char])
-> Show Exponent
forall a.
(Kind -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [Exponent] -> [Char] -> [Char]
$cshowList :: [Exponent] -> [Char] -> [Char]
show :: Exponent -> [Char]
$cshow :: Exponent -> [Char]
showsPrec :: Kind -> Exponent -> [Char] -> [Char]
$cshowsPrec :: Kind -> Exponent -> [Char] -> [Char]
Show)

-- Note: Some Fortran language references include extensions here. HP's F90
-- reference provides a Q exponent letter which sets kind to 16.
data ExponentLetter
  = ExpLetterD
  | ExpLetterE
    deriving (ExponentLetter -> ExponentLetter -> Bool
(ExponentLetter -> ExponentLetter -> Bool)
-> (ExponentLetter -> ExponentLetter -> Bool) -> Eq ExponentLetter
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExponentLetter -> ExponentLetter -> Bool
$c/= :: ExponentLetter -> ExponentLetter -> Bool
== :: ExponentLetter -> ExponentLetter -> Bool
$c== :: ExponentLetter -> ExponentLetter -> Bool
Eq, Eq ExponentLetter
Eq ExponentLetter
-> (ExponentLetter -> ExponentLetter -> Ordering)
-> (ExponentLetter -> ExponentLetter -> Bool)
-> (ExponentLetter -> ExponentLetter -> Bool)
-> (ExponentLetter -> ExponentLetter -> Bool)
-> (ExponentLetter -> ExponentLetter -> Bool)
-> (ExponentLetter -> ExponentLetter -> ExponentLetter)
-> (ExponentLetter -> ExponentLetter -> ExponentLetter)
-> Ord ExponentLetter
ExponentLetter -> ExponentLetter -> Bool
ExponentLetter -> ExponentLetter -> Ordering
ExponentLetter -> ExponentLetter -> ExponentLetter
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ExponentLetter -> ExponentLetter -> ExponentLetter
$cmin :: ExponentLetter -> ExponentLetter -> ExponentLetter
max :: ExponentLetter -> ExponentLetter -> ExponentLetter
$cmax :: ExponentLetter -> ExponentLetter -> ExponentLetter
>= :: ExponentLetter -> ExponentLetter -> Bool
$c>= :: ExponentLetter -> ExponentLetter -> Bool
> :: ExponentLetter -> ExponentLetter -> Bool
$c> :: ExponentLetter -> ExponentLetter -> Bool
<= :: ExponentLetter -> ExponentLetter -> Bool
$c<= :: ExponentLetter -> ExponentLetter -> Bool
< :: ExponentLetter -> ExponentLetter -> Bool
$c< :: ExponentLetter -> ExponentLetter -> Bool
compare :: ExponentLetter -> ExponentLetter -> Ordering
$ccompare :: ExponentLetter -> ExponentLetter -> Ordering
Ord, Kind -> ExponentLetter -> [Char] -> [Char]
[ExponentLetter] -> [Char] -> [Char]
ExponentLetter -> [Char]
(Kind -> ExponentLetter -> [Char] -> [Char])
-> (ExponentLetter -> [Char])
-> ([ExponentLetter] -> [Char] -> [Char])
-> Show ExponentLetter
forall a.
(Kind -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [ExponentLetter] -> [Char] -> [Char]
$cshowList :: [ExponentLetter] -> [Char] -> [Char]
show :: ExponentLetter -> [Char]
$cshow :: ExponentLetter -> [Char]
showsPrec :: Kind -> ExponentLetter -> [Char] -> [Char]
$cshowsPrec :: Kind -> ExponentLetter -> [Char] -> [Char]
Show)

data NumSign
  = SignPos
  | SignNeg
    deriving (NumSign -> NumSign -> Bool
(NumSign -> NumSign -> Bool)
-> (NumSign -> NumSign -> Bool) -> Eq NumSign
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NumSign -> NumSign -> Bool
$c/= :: NumSign -> NumSign -> Bool
== :: NumSign -> NumSign -> Bool
$c== :: NumSign -> NumSign -> Bool
Eq, Eq NumSign
Eq NumSign
-> (NumSign -> NumSign -> Ordering)
-> (NumSign -> NumSign -> Bool)
-> (NumSign -> NumSign -> Bool)
-> (NumSign -> NumSign -> Bool)
-> (NumSign -> NumSign -> Bool)
-> (NumSign -> NumSign -> NumSign)
-> (NumSign -> NumSign -> NumSign)
-> Ord NumSign
NumSign -> NumSign -> Bool
NumSign -> NumSign -> Ordering
NumSign -> NumSign -> NumSign
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NumSign -> NumSign -> NumSign
$cmin :: NumSign -> NumSign -> NumSign
max :: NumSign -> NumSign -> NumSign
$cmax :: NumSign -> NumSign -> NumSign
>= :: NumSign -> NumSign -> Bool
$c>= :: NumSign -> NumSign -> Bool
> :: NumSign -> NumSign -> Bool
$c> :: NumSign -> NumSign -> Bool
<= :: NumSign -> NumSign -> Bool
$c<= :: NumSign -> NumSign -> Bool
< :: NumSign -> NumSign -> Bool
$c< :: NumSign -> NumSign -> Bool
compare :: NumSign -> NumSign -> Ordering
$ccompare :: NumSign -> NumSign -> Ordering
Ord, Kind -> NumSign -> [Char] -> [Char]
[NumSign] -> [Char] -> [Char]
NumSign -> [Char]
(Kind -> NumSign -> [Char] -> [Char])
-> (NumSign -> [Char])
-> ([NumSign] -> [Char] -> [Char])
-> Show NumSign
forall a.
(Kind -> a -> [Char] -> [Char])
-> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
showList :: [NumSign] -> [Char] -> [Char]
$cshowList :: [NumSign] -> [Char] -> [Char]
show :: NumSign -> [Char]
$cshow :: NumSign -> [Char]
showsPrec :: Kind -> NumSign -> [Char] -> [Char]
$cshowsPrec :: Kind -> NumSign -> [Char] -> [Char]
Show)

-- | Parse a Fortran literal real to its constituent parts.
parseRealLiteral :: String -> RealLit
parseRealLiteral :: [Char] -> RealLit
parseRealLiteral [Char]
r =
    RealLit :: [Char] -> Maybe Exponent -> Maybe Kind -> RealLit
RealLit { realLitValue :: [Char]
realLitValue     = (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
isValuePart [Char]
r
            , realLitExponent :: Maybe Exponent
realLitExponent  = [Char] -> Maybe Exponent
parseRealLitExponent ((Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isValuePart [Char]
r)
            , realLitKindParam :: Maybe Kind
realLitKindParam = [Char] -> Maybe Kind
parseRealLitKindInt ((Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'_') [Char]
r)
            }
  where
    -- slightly ugly: we add the signs in here to allow -1.0 easily
    isValuePart :: Char -> Bool
    isValuePart :: Char -> Bool
isValuePart Char
ch
      | Char -> Bool
isDigit Char
ch                 = Bool
True
      | Char
ch Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'.', Char
'-', Char
'+']  = Bool
True
      | Bool
otherwise                  = Bool
False
    parseRealLitKindInt :: String -> Maybe Kind
    parseRealLitKindInt :: [Char] -> Maybe Kind
parseRealLitKindInt = \case
      Char
'_':[Char]
chs -> [Char] -> Maybe Kind
forall a. Read a => [Char] -> Maybe a
readMaybe [Char]
chs
      [Char]
_       -> Maybe Kind
forall a. Maybe a
Nothing
    parseRealLitExponent :: String -> Maybe Exponent
    parseRealLitExponent :: [Char] -> Maybe Exponent
parseRealLitExponent [Char]
"" = Maybe Exponent
forall a. Maybe a
Nothing
    parseRealLitExponent (Char
c:[Char]
cs) = do
        ExponentLetter
letter <-
                case Char -> Char
toLower Char
c of
                  Char
'e' -> ExponentLetter -> Maybe ExponentLetter
forall a. a -> Maybe a
Just ExponentLetter
ExpLetterE
                  Char
'd' -> ExponentLetter -> Maybe ExponentLetter
forall a. a -> Maybe a
Just ExponentLetter
ExpLetterD
                  Char
_   -> Maybe ExponentLetter
forall a. Maybe a
Nothing
        let (Maybe NumSign
sign, [Char]
cs'') =
                case [Char]
cs of
                  [Char]
""       -> (Maybe NumSign
forall a. Maybe a
Nothing, [Char]
cs)
                  Char
c':[Char]
cs'  -> -- TODO: want to locally scope cs' but unsure how to??
                    case Char
c' of
                      Char
'-' -> (NumSign -> Maybe NumSign
forall a. a -> Maybe a
Just NumSign
SignNeg, [Char]
cs')
                      Char
'+' -> (NumSign -> Maybe NumSign
forall a. a -> Maybe a
Just NumSign
SignPos, [Char]
cs')
                      Char
_   -> (Maybe NumSign
forall a. Maybe a
Nothing     , [Char]
cs)
            digitStr :: Kind
digitStr = [Char] -> Kind
forall a. Read a => [Char] -> a
read ((Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Char -> Bool
isDigit [Char]
cs'')
        Exponent -> Maybe Exponent
forall (m :: * -> *) a. Monad m => a -> m a
return (Exponent -> Maybe Exponent) -> Exponent -> Maybe Exponent
forall a b. (a -> b) -> a -> b
$ ExponentLetter -> Maybe NumSign -> Kind -> Exponent
Exponent ExponentLetter
letter Maybe NumSign
sign Kind
digitStr