@@ -20,6 +20,9 @@ module Parsing
20
20
, fail
21
21
, failWithPosition
22
22
, region
23
+ , liftMaybe
24
+ , liftEither
25
+ , liftExceptT
23
26
, ParseState (..)
24
27
, stateParserT
25
28
, getParserT
@@ -33,6 +36,7 @@ import Control.Alt (class Alt)
33
36
import Control.Apply (lift2 )
34
37
import Control.Lazy (class Lazy )
35
38
import Control.Monad.Error.Class (class MonadError , class MonadThrow , catchError , throwError )
39
+ import Control.Monad.Except (ExceptT , runExceptT )
36
40
import Control.Monad.Reader.Class (class MonadAsk , class MonadReader , ask , local )
37
41
import Control.Monad.Rec.Class (class MonadRec , Step (..), tailRecM )
38
42
import Control.Monad.State.Class (class MonadState , state )
@@ -43,6 +47,7 @@ import Data.Function.Uncurried (Fn2, Fn5, mkFn2, mkFn3, mkFn5, runFn2, runFn3, r
43
47
import Data.Generic.Rep (class Generic )
44
48
import Data.Identity (Identity )
45
49
import Data.Lazy as Lazy
50
+ import Data.Maybe (Maybe (..))
46
51
import Data.Newtype (unwrap )
47
52
import Data.Show.Generic (genericShow )
48
53
import Data.Tuple (Tuple (..), fst )
@@ -441,4 +446,58 @@ instance Ord Position where
441
446
-- |
442
447
-- | `{ index: 0, line: 1, column: 1 }`
443
448
initialPos :: Position
444
- initialPos = Position { index: 0 , line: 1 , column: 1 }
449
+ initialPos = Position { index: 0 , line: 1 , column: 1 }
450
+
451
+ -- | Lift a `Maybe a` computation into a `ParserT`, with a note for
452
+ -- | the `ParseError` message in case of `Nothing`.
453
+ -- |
454
+ -- | Consumes no parsing input, does not change the parser state at all.
455
+ -- | If the `Maybe` computation is `Nothing`, then this will `fail` in the
456
+ -- | `ParserT` monad with the given error message `String` at the current input
457
+ -- | `Position`.
458
+ -- |
459
+ -- | This is a “validation” function, for when we want to produce some
460
+ -- | data from the parsing input or fail at the current
461
+ -- | parsing position if that’s impossible.
462
+ -- |
463
+ -- | For example:
464
+ -- |
465
+ -- | ```
466
+ -- | runParser "3" do
467
+ -- | myenum :: MyEnum <- tryRethrow do
468
+ -- | x <- intDecimal
469
+ -- | liftMaybe (defer $ "Bad MyEnum " <> show x) $ toEnum x
470
+ -- | pure myenum
471
+ -- | ```
472
+ liftMaybe :: forall s m a . Monad m => Lazy.Lazy String -> Maybe a -> ParserT s m a
473
+ liftMaybe message f = case f of
474
+ Nothing -> fail (Lazy .force message)
475
+ Just x -> pure x
476
+
477
+ -- | Lift an `Either String a` computation into a `ParserT`.
478
+ -- |
479
+ -- | Consumes no parsing input, does not change the parser state at all.
480
+ -- | If the `Either` computation is `Left String`, then this will `fail` in the
481
+ -- | `ParserT` monad at the current input `Position`.
482
+ -- |
483
+ -- | This is a “validation” function, for when we want to produce some
484
+ -- | data from the parsing input or fail at the current
485
+ -- | parsing position if that’s impossible.
486
+ liftEither :: forall s m a . Monad m => Either String a -> ParserT s m a
487
+ liftEither f = case f of
488
+ Left err -> fail err
489
+ Right x -> pure x
490
+
491
+ -- | Lift an `ExceptT String m a` computation into a `ParserT`.
492
+ -- |
493
+ -- | Consumes no parsing input, does not change the parser state at all.
494
+ -- | If the `ExceptT` computation is `Left String`, then this will `fail` in the
495
+ -- | `ParserT` monad at the current input `Position`.
496
+ -- |
497
+ -- | This is a “validation” function, for when we want to produce some
498
+ -- | data from the parsing input or fail at the current
499
+ -- | parsing position if that’s impossible.
500
+ liftExceptT :: forall s m a . (Monad m ) => ExceptT String m a -> ParserT s m a
501
+ liftExceptT f = lift (runExceptT f) >>= case _ of
502
+ Left err -> fail err
503
+ Right x -> pure x
0 commit comments