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

import Bookhound.Parser            (Parser, withErrorN)
import Bookhound.ParserCombinators (IsMatch (..), string, (->>-), (|?), (||+),
                                    (||?))
import Bookhound.Parsers.Char      (dash, digit, dot, plus)
import Control.Applicative
import Data.Text                   (Text, unpack)


hexInt :: Parser Int
hexInt :: Parser Int
hexInt = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Hex Int" forall a b. (a -> b) -> a -> b
$ Text -> Int
readInt
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> Parser Text
string Text
"0x" forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- ((Parser Char
digit forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'A' .. Char
'F'] forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'a' .. Char
'f']) ||+))

octInt :: Parser Int
octInt :: Parser Int
octInt = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Oct Int" forall a b. (a -> b) -> a -> b
$ Text -> Int
readInt
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> Parser Text
string Text
"0o" forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- (forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'0' .. Char
'7'] ||+))

unsignedInt :: Parser Int
unsignedInt :: Parser Int
unsignedInt = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Unsigned Int" forall a b. (a -> b) -> a -> b
$ Text -> Int
readInt
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser Char
digit ||+)

posInt :: Parser Int
posInt :: Parser Int
posInt = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Positive Int" forall a b. (a -> b) -> a -> b
$ Text -> Int
readInt
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((Parser Char
plus ||?) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Parser Char
digit ||+))

negInt :: Parser Int
negInt :: Parser Int
negInt = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Negative Int" forall a b. (a -> b) -> a -> b
$ Text -> Int
readInt
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char
dash forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- (Parser Char
digit ||+)

int :: Parser Int
int :: Parser Int
int = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Int" forall a b. (a -> b) -> a -> b
$ Parser Int
negInt forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Int
posInt

double :: Parser Double
double :: Parser Double
double = forall a. Int -> Text -> Parser a -> Parser a
withErrorN (-Int
1) Text
"Double" forall a b. (a -> b) -> a -> b
$ Text -> Double
readDouble
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Int
int forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- (Parser Text
decimals forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- (Parser Text
expn |?) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text
expn)
  where
  decimals :: Parser Text
decimals = Parser Char
dot forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- (Parser Char
digit ||+)
  expn :: Parser Text
expn      = forall a. IsMatch a => [a] -> Parser a
oneOf [Char
'e', Char
'E'] forall a b.
(ToText a, ToText b) =>
Parser a -> Parser b -> Parser Text
->>- Parser Int
int

readInt :: Text -> Int
readInt :: Text -> Int
readInt = forall a. Read a => [Char] -> a
read forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
unpack

readDouble :: Text -> Double
readDouble :: Text -> Double
readDouble = forall a. Read a => [Char] -> a
read forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
unpack