packages feed

babynf-0.1.0.2: lib/Data/BAByNF/Core/Repeat.hs

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 { required :: Natural, optional :: Maybe Natural } deriving (Eq, Show)

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

exactly :: Natural -> Repeat
exactly val = Repeat { required = val, optional = Just 0}

once :: Repeat
once = exactly 1

upTo :: Natural -> Repeat
upTo val = Repeat { required = 0, optional = Just val }

maybeOnce :: Repeat
maybeOnce = upTo 1 

zeroOrMore :: Repeat
zeroOrMore = nOrMore 0

oneOrMore :: Repeat
oneOrMore = nOrMore 1

nOrMore :: Natural -> Repeat
nOrMore val = Repeat { required = val, optional = Nothing } 


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

data RepeatCount = RepeatCount { repeatDef :: Repeat, count :: Natural } deriving (Eq, Show)

tryIncrementCount :: RepeatCount -> Maybe RepeatCount
tryIncrementCount x = 
    case state x of
        Satisfied -> Nothing
        _ -> Just $ RepeatCount { repeatDef = repeatDef x, count = count x + 1 }

data State = NeedMore | WantMore | Satisfied
state :: RepeatCount -> State
state RepeatCount { repeatDef = Repeat { required = required, optional = maybeOptional }, count = count} =
    if count < required then NeedMore else
    case maybeOptional of
        Nothing -> WantMore
        Just optional -> if optional > (count - required) then WantMore else Satisfied