-- misc failure conditions
-- | an unknown error (the state might indicate where the error happened)
Parser s e a = Parser { runP :: StateT s (Either e) a }
-- | lift an unwrapped parser into our structures
Parser . StateT $ f origp
fmap f = Parser . (fmap f) . runP
pure = Parser . pure
Parser a <*> Parser b = Parser $ a <*> b
empty = Parser $ StateT (Left . perrUnknown)
Parser (StateT p1) <|> Parser (StateT p2) = Parser . StateT $ \st ->
case (p1 st, p2 st) of
(Right y, _) -> Right y
(_, Right y) -> Right y
(Left e1, Left e2) -> Left $ e1 <> e2
return = pure
Parser a >>= fb = Parser $ a >>= (runP . fb)
state = Parser . state
throwError e = Parser . StateT . const $ Left e
catchError (Parser (StateT m)) eh = Parser . StateT $ \st -> case m st of
Left err -> let (Parser (StateT ehp)) = eh err in ehp st
Right x -> Right x
runStateT p st
-- some simple parser combinators
-- | shave an maybe from the parser result and throw an unknown error if it got Nothing
Parser . StateT $ case mb of
Nothing -> Left . perrUnknown
Just x -> \st -> Right (x, st)
-- | shave an either from the parser result and possibly throw errors into the parser itself
Parser . StateT $ \st -> fmap (\y -> (y, st)) eith