module Data.BAByNF.Core.Repeat
    ( Repeat
    , RepeatCount
    , required
    , optional
    , from
    , exactly
    , once
    , upTo
    , maybeOnce
    , zeroOrMore
    , oneOrMore
    , nOrMore
    , repeatDef
    , count
    , initCount
    , State (..)
    , tryIncrementCount
    , state
    ) where
import Numeric.Natural (Natural)


data Repeat = Repeat { Repeat -> Natural
required :: Natural, Repeat -> Maybe Natural
optional :: Maybe Natural } deriving (Repeat -> Repeat -> Bool
(Repeat -> Repeat -> Bool)
-> (Repeat -> Repeat -> Bool) -> Eq Repeat
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Repeat -> Repeat -> Bool
== :: Repeat -> Repeat -> Bool
$c/= :: Repeat -> Repeat -> Bool
/= :: Repeat -> Repeat -> Bool
Eq, Int -> Repeat -> ShowS
[Repeat] -> ShowS
Repeat -> String
(Int -> Repeat -> ShowS)
-> (Repeat -> String) -> ([Repeat] -> ShowS) -> Show Repeat
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Repeat -> ShowS
showsPrec :: Int -> Repeat -> ShowS
$cshow :: Repeat -> String
show :: Repeat -> String
$cshowList :: [Repeat] -> ShowS
showList :: [Repeat] -> ShowS
Show)

from :: Natural -> Maybe Natural -> Repeat
from :: Natural -> Maybe Natural -> Repeat
from Natural
req Maybe Natural
opt = Repeat { required :: Natural
required = Natural
req, optional :: Maybe Natural
optional = Maybe Natural
opt }

exactly :: Natural -> Repeat
exactly :: Natural -> Repeat
exactly Natural
val = Repeat { required :: Natural
required = Natural
val, optional :: Maybe Natural
optional = Natural -> Maybe Natural
forall a. a -> Maybe a
Just Natural
0}

once :: Repeat
once :: Repeat
once = Natural -> Repeat
exactly Natural
1

upTo :: Natural -> Repeat
upTo :: Natural -> Repeat
upTo Natural
val = Repeat { required :: Natural
required = Natural
0, optional :: Maybe Natural
optional = Natural -> Maybe Natural
forall a. a -> Maybe a
Just Natural
val }

maybeOnce :: Repeat
maybeOnce :: Repeat
maybeOnce = Natural -> Repeat
upTo Natural
1 

zeroOrMore :: Repeat
zeroOrMore :: Repeat
zeroOrMore = Natural -> Repeat
nOrMore Natural
0

oneOrMore :: Repeat
oneOrMore :: Repeat
oneOrMore = Natural -> Repeat
nOrMore Natural
1

nOrMore :: Natural -> Repeat
nOrMore :: Natural -> Repeat
nOrMore Natural
val = Repeat { required :: Natural
required = Natural
val, optional :: Maybe Natural
optional = Maybe Natural
forall a. Maybe a
Nothing } 


initCount :: Repeat -> RepeatCount
initCount :: Repeat -> RepeatCount
initCount Repeat
r = RepeatCount { repeatDef :: Repeat
repeatDef = Repeat
r, count :: Natural
count = Natural
0 }

data RepeatCount = RepeatCount { RepeatCount -> Repeat
repeatDef :: Repeat, RepeatCount -> Natural
count :: Natural } deriving (RepeatCount -> RepeatCount -> Bool
(RepeatCount -> RepeatCount -> Bool)
-> (RepeatCount -> RepeatCount -> Bool) -> Eq RepeatCount
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RepeatCount -> RepeatCount -> Bool
== :: RepeatCount -> RepeatCount -> Bool
$c/= :: RepeatCount -> RepeatCount -> Bool
/= :: RepeatCount -> RepeatCount -> Bool
Eq, Int -> RepeatCount -> ShowS
[RepeatCount] -> ShowS
RepeatCount -> String
(Int -> RepeatCount -> ShowS)
-> (RepeatCount -> String)
-> ([RepeatCount] -> ShowS)
-> Show RepeatCount
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RepeatCount -> ShowS
showsPrec :: Int -> RepeatCount -> ShowS
$cshow :: RepeatCount -> String
show :: RepeatCount -> String
$cshowList :: [RepeatCount] -> ShowS
showList :: [RepeatCount] -> ShowS
Show)

tryIncrementCount :: RepeatCount -> Maybe RepeatCount
tryIncrementCount :: RepeatCount -> Maybe RepeatCount
tryIncrementCount RepeatCount
x = 
    case RepeatCount -> State
state RepeatCount
x of
        State
Satisfied -> Maybe RepeatCount
forall a. Maybe a
Nothing
        State
_ -> RepeatCount -> Maybe RepeatCount
forall a. a -> Maybe a
Just (RepeatCount -> Maybe RepeatCount)
-> RepeatCount -> Maybe RepeatCount
forall a b. (a -> b) -> a -> b
$ RepeatCount { repeatDef :: Repeat
repeatDef = RepeatCount -> Repeat
repeatDef RepeatCount
x, count :: Natural
count = RepeatCount -> Natural
count RepeatCount
x Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
1 }

data State = NeedMore | WantMore | Satisfied
state :: RepeatCount -> State
state :: RepeatCount -> State
state RepeatCount { repeatDef :: RepeatCount -> Repeat
repeatDef = Repeat { required :: Repeat -> Natural
required = Natural
required, optional :: Repeat -> Maybe Natural
optional = Maybe Natural
maybeOptional }, count :: RepeatCount -> Natural
count = Natural
count} =
    if Natural
count Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
< Natural
required then State
NeedMore else
    case Maybe Natural
maybeOptional of
        Maybe Natural
Nothing -> State
WantMore
        Just Natural
optional -> if Natural
optional Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
> (Natural
count Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
- Natural
required) then State
WantMore else State
Satisfied