-- |
-- Collection of commonly used regular expressions.
module Text.Regex.Applicative.Common (
    -- * Digits
    digit
  , hexDigit
    -- * Numbers
  , signed
  , decimal
  , hexadecimal
  ) where

import Data.Char
import Data.List (foldl')
import Text.Regex.Applicative


-- | Decimal digit, i.e. @\'0\'@..@\'9\'@
digit :: Num a => RE Char a
digit :: forall a. Num a => RE Char a
digit = Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> a) -> (Char -> Int) -> Char -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
digitToInt (Char -> a) -> RE Char Char -> RE Char a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> RE Char Char
forall s. (s -> Bool) -> RE s s
psym Char -> Bool
isDigit

-- | Hexadecimal digit
-- i.e. @\'0\'@..@\'9\'@, @\'a\'@..@\'f\'@, @\'A\'@..@\'F\'@.
hexDigit :: Num a => RE Char a
hexDigit :: forall a. Num a => RE Char a
hexDigit = Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> a) -> (Char -> Int) -> Char -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
digitToInt (Char -> a) -> RE Char Char -> RE Char a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> RE Char Char
forall s. (s -> Bool) -> RE s s
psym Char -> Bool
isHexDigit

-- | Add optional sign
signed :: Num a => RE Char a -> RE Char a
signed :: forall a. Num a => RE Char a -> RE Char a
signed RE Char a
p = RE Char (a -> a)
sign RE Char (a -> a) -> RE Char a -> RE Char a
forall a b. RE Char (a -> b) -> RE Char a -> RE Char b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RE Char a
p
  where
    sign :: RE Char (a -> a)
sign =  a -> a
forall a. a -> a
id     (a -> a) -> RE Char Char -> RE Char (a -> a)
forall a b. a -> RE Char b -> RE Char a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> RE Char Char
forall s. Eq s => s -> RE s s
sym Char
'+'
        RE Char (a -> a) -> RE Char (a -> a) -> RE Char (a -> a)
forall a. RE Char a -> RE Char a -> RE Char a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> a -> a
forall a. Num a => a -> a
negate (a -> a) -> RE Char Char -> RE Char (a -> a)
forall a b. a -> RE Char b -> RE Char a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> RE Char Char
forall s. Eq s => s -> RE s s
sym Char
'-'
        RE Char (a -> a) -> RE Char (a -> a) -> RE Char (a -> a)
forall a. RE Char a -> RE Char a -> RE Char a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (a -> a) -> RE Char (a -> a)
forall a. a -> RE Char a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a -> a
forall a. a -> a
id

-- | Parse decimal number without sign.
decimal :: Num a => RE Char a
decimal :: forall a. Num a => RE Char a
decimal = (a -> a -> a) -> a -> [a] -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\a
d a
i -> a
da -> a -> a
forall a. Num a => a -> a -> a
*a
10 a -> a -> a
forall a. Num a => a -> a -> a
+ a
i) a
0 ([a] -> a) -> RE Char [a] -> RE Char a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RE Char a -> RE Char [a]
forall a. RE Char a -> RE Char [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some RE Char a
forall a. Num a => RE Char a
digit

-- | Parse decimal number without sign.
hexadecimal :: Num a => RE Char a
hexadecimal :: forall a. Num a => RE Char a
hexadecimal = (a -> a -> a) -> a -> [a] -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\a
d a
i -> a
da -> a -> a
forall a. Num a => a -> a -> a
*a
16 a -> a -> a
forall a. Num a => a -> a -> a
+ a
i) a
0 ([a] -> a) -> RE Char [a] -> RE Char a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RE Char a -> RE Char [a]
forall a. RE Char a -> RE Char [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some RE Char a
forall a. Num a => RE Char a
hexDigit