module Sound.MIDI.Parser.State
(T, zeroOrMore, StateT(..), ) where
import qualified Sound.MIDI.Parser.Class as Parser
import Control.Monad.State (StateT(..), mapStateT, liftM, liftM2, lift, )
type T st parser = StateT st parser
force :: Parser.C parser =>
T st parser a -> T st parser a
force = mapStateT Parser.force
zeroOrMore :: Parser.C parser =>
T st parser a -> T st parser (Parser.PossiblyIncomplete [a])
zeroOrMore p =
let go =
force $ isEnd >>= \b ->
if b
then return (Nothing, [])
else handleMsg
(\errMsg -> (Just errMsg, []))
(liftM2 (\ x ~(e,xs) -> (e,x:xs)) p go)
in go
handleMsg :: Parser.C parser =>
(Parser.UserMessage -> a) -> T st parser a -> T st parser a
handleMsg handler action =
StateT $ \s ->
liftM
(either (\e -> (handler e, s)) id)
(Parser.try (runStateT action s))
isEnd :: Parser.C parser =>
T st parser Bool
isEnd = lift $ Parser.isEnd