{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Aeson.Internal.Scientific (
scanScientific,
) where
import Data.Integer.Conversion (textToInteger)
import Data.Scientific (Scientific)
import Data.Text (Text)
import qualified Data.Scientific as Sci
import qualified Data.Text as T
scanScientific
:: forall r. (Scientific -> Text -> r)
-> (String -> r)
-> Text
-> r
scanScientific :: forall r. (Scientific -> Text -> r) -> (String -> r) -> Text -> r
scanScientific Scientific -> Text -> r
kont String -> r
err Text
input0 = case Text -> Maybe (Char, Text)
T.uncons Text
input0 of
Maybe (Char, Text)
Nothing -> r
errEnd
Just (Char
c, Text
text')
| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'+' -> (Scientific -> Text -> r) -> (String -> r) -> Text -> r
forall r. (Scientific -> Text -> r) -> (String -> r) -> Text -> r
scanScientific' Scientific -> Text -> r
kont String -> r
err Text
text'
| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-' -> (Scientific -> Text -> r) -> (String -> r) -> Text -> r
forall r. (Scientific -> Text -> r) -> (String -> r) -> Text -> r
scanScientific' (\Scientific
sci -> Scientific -> Text -> r
kont (Scientific -> Scientific
forall a. Num a => a -> a
negate Scientific
sci)) String -> r
err Text
text'
| Bool
otherwise -> (Scientific -> Text -> r) -> (String -> r) -> Text -> r
forall r. (Scientific -> Text -> r) -> (String -> r) -> Text -> r
scanScientific' Scientific -> Text -> r
kont String -> r
err Text
input0
where
errEnd :: r
errEnd = String -> r
err String
"Unexpected end-of-input while parsing number literal"
scanScientific'
:: forall r. (Scientific -> Text -> r)
-> (String -> r)
-> Text
-> r
scanScientific' :: forall r. (Scientific -> Text -> r) -> (String -> r) -> Text -> r
scanScientific' Scientific -> Text -> r
kont String -> r
err Text
input0 = Text -> r
state_start Text
input0 where
state_start :: Text -> r
state_start :: Text -> r
state_start !Text
text = case Text -> Maybe (Char, Text)
T.uncons Text
text of
Maybe (Char, Text)
Nothing -> r
errEnd
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Int -> Text -> r
state_i Int
1 Text
text'
| Bool
otherwise -> String -> r
err (String -> r) -> String -> r
forall a b. (a -> b) -> a -> b
$ String
"Unexpected " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char -> String
forall a. Show a => a -> String
show Char
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" while parsing number literal"
state_i :: Int -> Text -> r
state_i :: Int -> Text -> r
state_i !Int
n !Text
text = case Text -> Maybe (Char, Text)
T.uncons Text
text of
Maybe (Char, Text)
Nothing -> Scientific -> Text -> r
kont (Integer -> Scientific
forall a. Num a => Integer -> a
fromInteger Integer
int) Text
text
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Int -> Text -> r
state_i (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Text
text'
| Char
'.' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c -> Integer -> Text -> r
go_dec Integer
int Text
text'
| Char
'e' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c Bool -> Bool -> Bool
|| Char
'E' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c -> Integer -> Int -> Text -> r
go_sci Integer
int Int
0 Text
text'
| Bool
otherwise -> Scientific -> Text -> r
kont (Integer -> Scientific
forall a. Num a => Integer -> a
fromInteger Integer
int) Text
text
where
int :: Integer
int = Text -> Integer
textToInteger (Int -> Text -> Text
T.take Int
n Text
input0)
go_dec :: Integer -> Text -> r
go_dec :: Integer -> Text -> r
go_dec !Integer
int !Text
text1 = case Text -> Maybe (Char, Text)
T.uncons Text
text1 of
Maybe (Char, Text)
Nothing -> r
errEnd
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Int -> Text -> r
state_dec Int
1 Text
text'
| Bool
otherwise -> String -> r
err (String -> r) -> String -> r
forall a b. (a -> b) -> a -> b
$ String
"Unexpected " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char -> String
forall a. Show a => a -> String
show Char
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" while parsing number literal"
where
state_dec :: Int -> Text -> r
state_dec :: Int -> Text -> r
state_dec !Int
n !Text
text = case Text -> Maybe (Char, Text)
T.uncons Text
text of
Maybe (Char, Text)
Nothing -> Scientific -> Text -> r
kont Scientific
dec Text
text
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Int -> Text -> r
state_dec (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Text
text'
| Char
'e' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c Bool -> Bool -> Bool
|| Char
'E' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c -> Integer -> Int -> Text -> r
go_sci Integer
coef (Int -> Int
forall a. Num a => a -> a
negate Int
n) Text
text'
| Bool
otherwise -> Scientific -> Text -> r
kont Scientific
dec Text
text
where
frac :: Integer
frac = Text -> Integer
textToInteger (Int -> Text -> Text
T.take Int
n Text
text1)
coef :: Integer
coef = Integer
int Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
10 Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
frac
dec :: Scientific
dec = Integer -> Int -> Scientific
Sci.scientific Integer
coef (Int -> Int
forall a. Num a => a -> a
negate Int
n)
go_sci :: Integer -> Int -> Text -> r
go_sci :: Integer -> Int -> Text -> r
go_sci !Integer
coef !Int
exp10 !Text
text2 = case Text -> Maybe (Char, Text)
T.uncons Text
text2 of
Maybe (Char, Text)
Nothing -> r
errEnd
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Integer -> Int -> Text -> Int -> Text -> r
go_sci_pos Integer
coef Int
exp10 Text
text2 Int
1 Text
text'
| Char
'+' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c -> case Text -> Maybe (Char, Text)
T.uncons Text
text' of
Maybe (Char, Text)
Nothing -> r
errEnd
Just (Char
c', Text
text'')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c', Char
c' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Integer -> Int -> Text -> Int -> Text -> r
go_sci_pos Integer
coef Int
exp10 Text
text' Int
1 Text
text''
| Bool
otherwise -> Char -> r
forall {a}. Show a => a -> r
errUnx Char
c'
| Char
'-' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c -> case Text -> Maybe (Char, Text)
T.uncons Text
text' of
Maybe (Char, Text)
Nothing -> r
errEnd
Just (Char
c', Text
text'')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c', Char
c' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Integer -> Int -> Text -> Int -> Text -> r
go_sci_neg Integer
coef Int
exp10 Text
text' Int
1 Text
text''
| Bool
otherwise -> Char -> r
forall {a}. Show a => a -> r
errUnx Char
c'
| Bool
otherwise -> Char -> r
forall {a}. Show a => a -> r
errUnx Char
c
go_sci_pos :: Integer -> Int -> Text -> Int -> Text -> r
go_sci_pos :: Integer -> Int -> Text -> Int -> Text -> r
go_sci_pos !Integer
coef !Int
exp10 !Text
text2 !Int
n !Text
text = case Text -> Maybe (Char, Text)
T.uncons Text
text of
Maybe (Char, Text)
Nothing -> Scientific -> Text -> r
kont Scientific
sci Text
text
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Integer -> Int -> Text -> Int -> Text -> r
go_sci_pos Integer
coef Int
exp10 Text
text2 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Text
text'
| Bool
otherwise -> Scientific -> Text -> r
kont Scientific
sci Text
text
where
exp10' :: Int
exp10' = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Text -> Integer
textToInteger (Int -> Text -> Text
T.take Int
n Text
text2))
sci :: Scientific
sci = Integer -> Int -> Scientific
Sci.scientific Integer
coef (Int
exp10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
exp10')
go_sci_neg :: Integer -> Int -> Text -> Int -> Text -> r
go_sci_neg :: Integer -> Int -> Text -> Int -> Text -> r
go_sci_neg !Integer
coef !Int
exp10 !Text
text2 !Int
n !Text
text = case Text -> Maybe (Char, Text)
T.uncons Text
text of
Maybe (Char, Text)
Nothing -> Scientific -> Text -> r
kont Scientific
sci Text
text
Just (Char
c, Text
text')
| Char
'0' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c, Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' -> Integer -> Int -> Text -> Int -> Text -> r
go_sci_neg Integer
coef Int
exp10 Text
text2 (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Text
text'
| Bool
otherwise -> Scientific -> Text -> r
kont Scientific
sci Text
text
where
exp10' :: Int
exp10' = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Text -> Integer
textToInteger (Int -> Text -> Text
T.take Int
n Text
text2))
sci :: Scientific
sci = Integer -> Int -> Scientific
Sci.scientific Integer
coef (Int
exp10 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
exp10')
errEnd :: r
errEnd = String -> r
err String
"Unexpected end-of-input while parsing number literal"
errUnx :: a -> r
errUnx a
c = String -> r
err (String -> r) -> String -> r
forall a b. (a -> b) -> a -> b
$ String
"Unexpected " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" while parsing number literal"