module Bookhound.Parsers.Number (int, double, posInt, negInt, unsignedInt, hexInt, octInt, intLike) where

import Bookhound.Parser            (ParseError (..), Parser, errorParser,
                                    withErrorN)
import Bookhound.ParserCombinators (IsMatch (..), (->>-), (<|>), (|+), (|?))
import Bookhound.Parsers.Char      (dash, digit, dot, plus)


hexInt :: Parser Integer
hexInt :: Parser Integer
hexInt = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Hex Int"
 forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a. IsMatch a => a -> Parser a
is [Char]
"0x" forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>-
             ((Parser Char
digit forall a. Parser a -> Parser a -> Parser a
<|> forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'A' .. Char
'F'] forall a. Parser a -> Parser a -> Parser a
<|> forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'a' .. Char
'f']) |+))

octInt :: Parser Integer
octInt :: Parser Integer
octInt = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Oct Int"
  forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a. IsMatch a => a -> Parser a
is [Char]
"0o" forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- (forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'0' .. Char
'7'] |+))

unsignedInt :: Parser Integer
unsignedInt :: Parser Integer
unsignedInt = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Unsigned Int"
  forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char
digit |+)

posInt :: Parser Integer
posInt :: Parser Integer
posInt = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Positive Int"
  forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char
plus |?) forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- (Parser Char
digit |+)

negInt :: Parser Integer
negInt :: Parser Integer
negInt = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Negative Int"
  forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char
dash forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- (Parser Char
digit |+)

int :: Parser Integer
int :: Parser Integer
int = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Int" forall a b. (a -> b) -> a -> b
$ Parser Integer
negInt forall a. Parser a -> Parser a -> Parser a
<|> Parser Integer
posInt

intLike :: Parser Integer
intLike :: Parser Integer
intLike = Parser Integer
parser forall a. Parser a -> Parser a -> Parser a
<|> Parser Integer
int
  where
    parser :: Parser Integer
parser = do [Char]
n1      <- forall a. Show a => a -> [Char]
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Integer
int
                [Char]
n2      <- forall a. Show a => a -> [Char]
show forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char
dot forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Integer
unsignedInt)
                Integer
expNum  <- forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'e', Char
'E'] forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Integer
int

                if forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
n1 forall a. Num a => a -> a -> a
+ forall (t :: * -> *) a. Foldable t => t a -> Int
length [Char]
n2 forall a. Ord a => a -> a -> Bool
<= forall a. Num a => Integer -> a
fromInteger Integer
expNum then
                  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => [Char] -> a
read forall a b. (a -> b) -> a -> b
$ [Char]
n1 forall a. Semigroup a => a -> a -> a
<> [Char]
"." forall a. Semigroup a => a -> a -> a
<> [Char]
n2 forall a. Semigroup a => a -> a -> a
<> [Char]
"E" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show Integer
expNum
                else
                  forall a. ParseError -> Parser a
errorParser forall a b. (a -> b) -> a -> b
$ [Char] -> ParseError
NoMatch [Char]
"Int Like"


double :: Parser Double
double :: Parser Double
double = forall a. Int -> [Char] -> Parser a -> Parser a
withErrorN (-Int
1) [Char]
"Double"
  forall a b. (a -> b) -> a -> b
$ forall a. Read a => [Char] -> a
read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Integer
int forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- (Parser [Char]
decimals |?) forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- (Parser [Char]
expn |?) where

  decimals :: Parser [Char]
decimals = Parser Char
dot forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- Parser Integer
unsignedInt
  expn :: Parser [Char]
expn      = forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'e', Char
'E'] forall a b.
(ToString a, ToString b) =>
Parser a -> Parser b -> Parser [Char]
->>- Parser Integer
int