mirror of
https://github.com/mrkkrp/megaparsec.git
synced 2024-12-25 09:12:29 +03:00
Add ‘MonadParsec’ instance for ‘RWST’ (#152)
This commit is contained in:
parent
38f5b36d46
commit
dd2386aafc
@ -1,3 +1,7 @@
|
|||||||
|
## Megaparsec 5.2.0
|
||||||
|
|
||||||
|
* Added `MonadParsec` instance for `RWST`.
|
||||||
|
|
||||||
## Megaparsec 5.1.2
|
## Megaparsec 5.1.2
|
||||||
|
|
||||||
* Stopped using property tests with `dbg` helper to avoid flood of debugging
|
* Stopped using property tests with `dbg` helper to avoid flood of debugging
|
||||||
|
@ -82,6 +82,8 @@ import Prelude hiding (all)
|
|||||||
import Test.QuickCheck hiding (Result (..), label)
|
import Test.QuickCheck hiding (Result (..), label)
|
||||||
import qualified Control.Applicative as A
|
import qualified Control.Applicative as A
|
||||||
import qualified Control.Monad.Fail as Fail
|
import qualified Control.Monad.Fail as Fail
|
||||||
|
import qualified Control.Monad.RWS.Lazy as L
|
||||||
|
import qualified Control.Monad.RWS.Strict as S
|
||||||
import qualified Control.Monad.Trans.Reader as L
|
import qualified Control.Monad.Trans.Reader as L
|
||||||
import qualified Control.Monad.Trans.State.Lazy as L
|
import qualified Control.Monad.Trans.State.Lazy as L
|
||||||
import qualified Control.Monad.Trans.State.Strict as S
|
import qualified Control.Monad.Trans.State.Strict as S
|
||||||
@ -1124,7 +1126,7 @@ instance MonadParsec e s m => MonadParsec e s (S.StateT st m) where
|
|||||||
getParserState = lift getParserState
|
getParserState = lift getParserState
|
||||||
updateParserState f = lift (updateParserState f)
|
updateParserState f = lift (updateParserState f)
|
||||||
|
|
||||||
instance MonadParsec e s m => MonadParsec e s (L.ReaderT st m) where
|
instance MonadParsec e s m => MonadParsec e s (L.ReaderT r m) where
|
||||||
failure us ps xs = lift (failure us ps xs)
|
failure us ps xs = lift (failure us ps xs)
|
||||||
label n (L.ReaderT m) = L.ReaderT $ label n . m
|
label n (L.ReaderT m) = L.ReaderT $ label n . m
|
||||||
try (L.ReaderT m) = L.ReaderT $ try . m
|
try (L.ReaderT m) = L.ReaderT $ try . m
|
||||||
@ -1175,6 +1177,46 @@ instance (Monoid w, MonadParsec e s m) => MonadParsec e s (S.WriterT w m) where
|
|||||||
getParserState = lift getParserState
|
getParserState = lift getParserState
|
||||||
updateParserState f = lift (updateParserState f)
|
updateParserState f = lift (updateParserState f)
|
||||||
|
|
||||||
|
instance (Monoid w, MonadParsec e s m) => MonadParsec e s (L.RWST r w st m) where
|
||||||
|
failure us ps xs = lift (failure us ps xs)
|
||||||
|
label n (L.RWST m) = L.RWST $ \r s -> label n (m r s)
|
||||||
|
try (L.RWST m) = L.RWST $ \r s -> try (m r s)
|
||||||
|
lookAhead (L.RWST m) = L.RWST $ \r s -> do
|
||||||
|
(x,_,_) <- lookAhead (m r s)
|
||||||
|
return (x,s,mempty)
|
||||||
|
notFollowedBy (L.RWST m) = L.RWST $ \r s -> do
|
||||||
|
notFollowedBy (void $ m r s)
|
||||||
|
return ((),s,mempty)
|
||||||
|
withRecovery n (L.RWST m) = L.RWST $ \r s ->
|
||||||
|
withRecovery (\e -> L.runRWST (n e) r s) (m r s)
|
||||||
|
observing (L.RWST m) = L.RWST $ \r s ->
|
||||||
|
fixs' s <$> observing (m r s)
|
||||||
|
eof = lift eof
|
||||||
|
token test mt = lift (token test mt)
|
||||||
|
tokens e ts = lift (tokens e ts)
|
||||||
|
getParserState = lift getParserState
|
||||||
|
updateParserState f = lift (updateParserState f)
|
||||||
|
|
||||||
|
instance (Monoid w, MonadParsec e s m) => MonadParsec e s (S.RWST r w st m) where
|
||||||
|
failure us ps xs = lift (failure us ps xs)
|
||||||
|
label n (S.RWST m) = S.RWST $ \r s -> label n (m r s)
|
||||||
|
try (S.RWST m) = S.RWST $ \r s -> try (m r s)
|
||||||
|
lookAhead (S.RWST m) = S.RWST $ \r s -> do
|
||||||
|
(x,_,_) <- lookAhead (m r s)
|
||||||
|
return (x,s,mempty)
|
||||||
|
notFollowedBy (S.RWST m) = S.RWST $ \r s -> do
|
||||||
|
notFollowedBy (void $ m r s)
|
||||||
|
return ((),s,mempty)
|
||||||
|
withRecovery n (S.RWST m) = S.RWST $ \r s ->
|
||||||
|
withRecovery (\e -> S.runRWST (n e) r s) (m r s)
|
||||||
|
observing (S.RWST m) = S.RWST $ \r s ->
|
||||||
|
fixs' s <$> observing (m r s)
|
||||||
|
eof = lift eof
|
||||||
|
token test mt = lift (token test mt)
|
||||||
|
tokens e ts = lift (tokens e ts)
|
||||||
|
getParserState = lift getParserState
|
||||||
|
updateParserState f = lift (updateParserState f)
|
||||||
|
|
||||||
instance MonadParsec e s m => MonadParsec e s (IdentityT m) where
|
instance MonadParsec e s m => MonadParsec e s (IdentityT m) where
|
||||||
failure us ps xs = lift (failure us ps xs)
|
failure us ps xs = lift (failure us ps xs)
|
||||||
label n (IdentityT m) = IdentityT $ label n m
|
label n (IdentityT m) = IdentityT $ label n m
|
||||||
@ -1195,6 +1237,11 @@ fixs s (Left a) = (Left a, s)
|
|||||||
fixs _ (Right (b, s)) = (Right b, s)
|
fixs _ (Right (b, s)) = (Right b, s)
|
||||||
{-# INLINE fixs #-}
|
{-# INLINE fixs #-}
|
||||||
|
|
||||||
|
fixs' :: Monoid w => s -> Either a (b, s, w) -> (Either a b, s, w)
|
||||||
|
fixs' s (Left a) = (Left a, s, mempty)
|
||||||
|
fixs' _ (Right (b,s,w)) = (Right b, s, w)
|
||||||
|
{-# INLINE fixs' #-}
|
||||||
|
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Debugging
|
-- Debugging
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@ import Test.Hspec.Megaparsec
|
|||||||
import Text.Megaparsec.Error
|
import Text.Megaparsec.Error
|
||||||
import Text.Megaparsec.Pos
|
import Text.Megaparsec.Pos
|
||||||
import Text.Megaparsec.Prim
|
import Text.Megaparsec.Prim
|
||||||
|
import qualified Control.Monad.RWS.Lazy as L
|
||||||
|
import qualified Control.Monad.RWS.Strict as S
|
||||||
import qualified Control.Monad.State.Lazy as L
|
import qualified Control.Monad.State.Lazy as L
|
||||||
import qualified Control.Monad.State.Strict as S
|
import qualified Control.Monad.State.Strict as S
|
||||||
import qualified Control.Monad.Writer.Lazy as L
|
import qualified Control.Monad.Writer.Lazy as L
|
||||||
@ -116,6 +118,8 @@ grs p s r = do
|
|||||||
r (prs (S.evalStateT p ()) s)
|
r (prs (S.evalStateT p ()) s)
|
||||||
r (prs (evalWriterTL p) s)
|
r (prs (evalWriterTL p) s)
|
||||||
r (prs (evalWriterTS p) s)
|
r (prs (evalWriterTS p) s)
|
||||||
|
r (prs (evalRWSTL p) s)
|
||||||
|
r (prs (evalRWSTS p) s)
|
||||||
|
|
||||||
-- | 'grs'' to 'grs' as 'prs'' to 'prs'.
|
-- | 'grs'' to 'grs' as 'prs'' to 'prs'.
|
||||||
|
|
||||||
@ -133,12 +137,24 @@ grs' p s r = do
|
|||||||
r (prs' (S.evalStateT p ()) s)
|
r (prs' (S.evalStateT p ()) s)
|
||||||
r (prs' (evalWriterTL p) s)
|
r (prs' (evalWriterTL p) s)
|
||||||
r (prs' (evalWriterTS p) s)
|
r (prs' (evalWriterTS p) s)
|
||||||
|
r (prs' (evalRWSTL p) s)
|
||||||
|
r (prs' (evalRWSTS p) s)
|
||||||
|
|
||||||
evalWriterTL :: Monad m => L.WriterT [Int] m a -> m a
|
evalWriterTL :: Monad m => L.WriterT [Int] m a -> m a
|
||||||
evalWriterTL = liftM fst . L.runWriterT
|
evalWriterTL = liftM fst . L.runWriterT
|
||||||
evalWriterTS :: Monad m => S.WriterT [Int] m a -> m a
|
evalWriterTS :: Monad m => S.WriterT [Int] m a -> m a
|
||||||
evalWriterTS = liftM fst . S.runWriterT
|
evalWriterTS = liftM fst . S.runWriterT
|
||||||
|
|
||||||
|
evalRWSTL :: Monad m => L.RWST () [Int] () m a -> m a
|
||||||
|
evalRWSTL m = do
|
||||||
|
(a,_,_) <- L.runRWST m () ()
|
||||||
|
return a
|
||||||
|
|
||||||
|
evalRWSTS :: Monad m => S.RWST () [Int] () m a -> m a
|
||||||
|
evalRWSTS m = do
|
||||||
|
(a,_,_) <- S.runRWST m () ()
|
||||||
|
return a
|
||||||
|
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Working with source position
|
-- Working with source position
|
||||||
|
|
||||||
|
@ -61,6 +61,8 @@ import Text.Megaparsec.Error
|
|||||||
import Text.Megaparsec.Pos
|
import Text.Megaparsec.Pos
|
||||||
import Text.Megaparsec.Prim
|
import Text.Megaparsec.Prim
|
||||||
import Text.Megaparsec.String
|
import Text.Megaparsec.String
|
||||||
|
import qualified Control.Monad.RWS.Lazy as L
|
||||||
|
import qualified Control.Monad.RWS.Strict as S
|
||||||
import qualified Control.Monad.State.Lazy as L
|
import qualified Control.Monad.State.Lazy as L
|
||||||
import qualified Control.Monad.State.Strict as S
|
import qualified Control.Monad.State.Strict as S
|
||||||
import qualified Control.Monad.Writer.Lazy as L
|
import qualified Control.Monad.Writer.Lazy as L
|
||||||
@ -1162,6 +1164,18 @@ spec = do
|
|||||||
return cs
|
return cs
|
||||||
prs (L.runWriterT p) "abx" `shouldParse` ("ab", pre ++ "AB" ++ post ++ "x")
|
prs (L.runWriterT p) "abx" `shouldParse` ("ab", pre ++ "AB" ++ post ++ "x")
|
||||||
|
|
||||||
|
describe "lookAhead" $
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = lookAhead (L.tell [w])
|
||||||
|
prs (L.runWriterT p) "" `shouldParse` ((), mempty :: [Int])
|
||||||
|
|
||||||
|
describe "notFollowedBy" $
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = notFollowedBy (L.tell [w] <* char 'a')
|
||||||
|
prs (L.runWriterT p) "" `shouldParse` ((), mempty :: [Int])
|
||||||
|
|
||||||
describe "observing" $ do
|
describe "observing" $ do
|
||||||
context "when inner parser succeeds" $
|
context "when inner parser succeeds" $
|
||||||
it "can affect log" $
|
it "can affect log" $
|
||||||
@ -1189,6 +1203,18 @@ spec = do
|
|||||||
return cs
|
return cs
|
||||||
prs (S.runWriterT p) "abx" `shouldParse` ("ab", pre ++ "AB" ++ post ++ "x")
|
prs (S.runWriterT p) "abx" `shouldParse` ("ab", pre ++ "AB" ++ post ++ "x")
|
||||||
|
|
||||||
|
describe "lookAhead" $
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = lookAhead (S.tell [w])
|
||||||
|
prs (S.runWriterT p) "" `shouldParse` ((), mempty :: [Int])
|
||||||
|
|
||||||
|
describe "notFollowedBy" $
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = notFollowedBy (S.tell [w] <* char 'a')
|
||||||
|
prs (S.runWriterT p) "" `shouldParse` ((), mempty :: [Int])
|
||||||
|
|
||||||
describe "observing" $ do
|
describe "observing" $ do
|
||||||
context "when inner parser succeeds" $
|
context "when inner parser succeeds" $
|
||||||
it "can affect log" $
|
it "can affect log" $
|
||||||
@ -1201,6 +1227,146 @@ spec = do
|
|||||||
let p = observing (S.tell (Sum n) <* empty)
|
let p = observing (S.tell (Sum n) <* empty)
|
||||||
prs (S.execWriterT p) "" `shouldParse` (mempty :: Sum Integer)
|
prs (S.execWriterT p) "" `shouldParse` (mempty :: Sum Integer)
|
||||||
|
|
||||||
|
describe "MonadParsec instance of lazy RWST" $ do
|
||||||
|
|
||||||
|
describe "label" $
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = label "a" ((,) <$> L.ask <*> L.get)
|
||||||
|
prs (L.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "try" $
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = try ((,) <$> L.ask <*> L.get)
|
||||||
|
prs (L.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "lookAhead" $ do
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = lookAhead ((,) <$> L.ask <*> L.get)
|
||||||
|
prs (L.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = lookAhead (L.tell [w])
|
||||||
|
prs (L.runRWST p (0 :: Int) (0 :: Int)) "" `shouldParse`
|
||||||
|
((), 0, mempty :: [Int])
|
||||||
|
it "does not allow to influence state outside it" $
|
||||||
|
property $ \s0 s1 -> (s0 /= s1) ==> do
|
||||||
|
let p = lookAhead (L.put s1)
|
||||||
|
prs (L.runRWST p (0 :: Int) (s0 :: Int)) "" `shouldParse`
|
||||||
|
((), s0, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "notFollowedBy" $ do
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = notFollowedBy (L.tell [w] <* char 'a')
|
||||||
|
prs (L.runRWST p (0 :: Int) (0 :: Int)) "" `shouldParse`
|
||||||
|
((), 0, mempty :: [Int])
|
||||||
|
it "does not allow to influence state outside it" $
|
||||||
|
property $ \s0 s1 -> (s0 /= s1) ==> do
|
||||||
|
let p = notFollowedBy (L.put s1 <* char 'a')
|
||||||
|
prs (L.runRWST p (0 :: Int) (s0 :: Int)) "" `shouldParse`
|
||||||
|
((), s0, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "withRecovery" $ do
|
||||||
|
it "allows main parser to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = withRecovery (const empty) ((,) <$> L.ask <*> L.get)
|
||||||
|
prs (L.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
it "allows recovering parser to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = withRecovery (\_ -> (,) <$> L.ask <*> L.get) empty
|
||||||
|
prs (L.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "observing" $ do
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = observing ((,) <$> L.ask <*> L.get)
|
||||||
|
prs (L.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
(Right (r, s), s, mempty :: [Int])
|
||||||
|
context "when the inner parser fails" $
|
||||||
|
it "backtracks state" $
|
||||||
|
property $ \r s0 s1 -> (s0 /= s1) ==> do
|
||||||
|
let p = observing (L.put s1 <* empty)
|
||||||
|
prs (L.runRWST p (r :: Int) (s0 :: Int)) "" `shouldParse`
|
||||||
|
(Left (err posI mempty), s0, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "MonadParsec instance of strict RWST" $ do
|
||||||
|
|
||||||
|
describe "label" $
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = label "a" ((,) <$> S.ask <*> S.get)
|
||||||
|
prs (S.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "try" $
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = try ((,) <$> S.ask <*> S.get)
|
||||||
|
prs (S.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "lookAhead" $ do
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = lookAhead ((,) <$> S.ask <*> S.get)
|
||||||
|
prs (S.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = lookAhead (S.tell [w])
|
||||||
|
prs (S.runRWST p (0 :: Int) (0 :: Int)) "" `shouldParse`
|
||||||
|
((), 0, mempty :: [Int])
|
||||||
|
it "does not allow to influence state outside it" $
|
||||||
|
property $ \s0 s1 -> (s0 /= s1) ==> do
|
||||||
|
let p = lookAhead (S.put s1)
|
||||||
|
prs (S.runRWST p (0 :: Int) (s0 :: Int)) "" `shouldParse`
|
||||||
|
((), s0, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "notFollowedBy" $ do
|
||||||
|
it "discards what writer tells inside it" $
|
||||||
|
property $ \w -> do
|
||||||
|
let p = notFollowedBy (S.tell [w] <* char 'a')
|
||||||
|
prs (S.runRWST p (0 :: Int) (0 :: Int)) "" `shouldParse`
|
||||||
|
((), 0, mempty :: [Int])
|
||||||
|
it "does not allow to influence state outside it" $
|
||||||
|
property $ \s0 s1 -> (s0 /= s1) ==> do
|
||||||
|
let p = notFollowedBy (S.put s1 <* char 'a')
|
||||||
|
prs (S.runRWST p (0 :: Int) (s0 :: Int)) "" `shouldParse`
|
||||||
|
((), s0, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "withRecovery" $ do
|
||||||
|
it "allows main parser to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = withRecovery (const empty) ((,) <$> S.ask <*> S.get)
|
||||||
|
prs (S.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
it "allows recovering parser to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = withRecovery (\_ -> (,) <$> S.ask <*> S.get) empty
|
||||||
|
prs (S.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
((r, s), s, mempty :: [Int])
|
||||||
|
|
||||||
|
describe "observing" $ do
|
||||||
|
it "allows to access reader context and state inside it" $
|
||||||
|
property $ \r s -> do
|
||||||
|
let p = observing ((,) <$> S.ask <*> S.get)
|
||||||
|
prs (S.runRWST p (r :: Int) (s :: Int)) "" `shouldParse`
|
||||||
|
(Right (r, s), s, mempty :: [Int])
|
||||||
|
context "when the inner parser fails" $
|
||||||
|
it "backtracks state" $
|
||||||
|
property $ \r s0 s1 -> (s0 /= s1) ==> do
|
||||||
|
let p = observing (S.put s1 <* empty)
|
||||||
|
prs (S.runRWST p (r :: Int) (s0 :: Int)) "" `shouldParse`
|
||||||
|
(Left (err posI mempty), s0, mempty :: [Int])
|
||||||
|
|
||||||
describe "dbg" $ do
|
describe "dbg" $ do
|
||||||
-- NOTE We don't test properties here to avoid flood of debugging output
|
-- NOTE We don't test properties here to avoid flood of debugging output
|
||||||
-- when the test runs.
|
-- when the test runs.
|
||||||
|
Loading…
Reference in New Issue
Block a user