Skip to content

Commit ed85e62

Browse files
committed
Change MonadState instance
`state` refers to base monad instead of `ParseState`
1 parent 7e804ad commit ed85e62

File tree

4 files changed

+40
-23
lines changed

4 files changed

+40
-23
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ Breaking changes:
3737
* `noneOf`
3838
* `noneOfCodePoints`
3939
from `Parsing.String` to `Parsing.String.Basic`. (#183 by @jamesdbrock)
40+
- Change MonadState instance (#187 by jamesdbrock)
41+
42+
Users who stack a `ParserT` on a `StateT` base monad will call the `MonadState` members directly like `get` instead of needing to do `lift <<< get`.
43+
44+
To get the `ParserT` internal state, call `getParserT` instead of `get`.
4045

4146
New features:
4247

src/Parsing.purs

+26-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module Parsing
2121
, failWithPosition
2222
, region
2323
, ParseState(..)
24+
, stateParserT
25+
, getParserT
2426
, hoistParserT
2527
, mapParserT
2628
) where
@@ -32,8 +34,8 @@ import Control.Apply (lift2)
3234
import Control.Lazy (class Lazy)
3335
import Control.Monad.Error.Class (class MonadError, class MonadThrow, catchError, throwError)
3436
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM)
35-
import Control.Monad.State.Class (class MonadState, gets, modify_)
36-
import Control.Monad.Trans.Class (class MonadTrans)
37+
import Control.Monad.State.Class (class MonadState, state)
38+
import Control.Monad.Trans.Class (class MonadTrans, lift)
3739
import Control.MonadPlus (class Alternative, class MonadPlus, class Plus)
3840
import Data.Either (Either(..))
3941
import Data.Function.Uncurried (Fn2, Fn5, mkFn2, mkFn3, mkFn5, runFn2, runFn3, runFn5)
@@ -273,12 +275,8 @@ instance MonadRec (ParserT s m) where
273275
runFn3 loop state1 initArg 30
274276
)
275277

276-
instance MonadState (ParseState s) (ParserT s m) where
277-
state k = ParserT
278-
( mkFn5 \state1 _ _ _ done -> do
279-
let (Tuple a state2) = k state1
280-
runFn2 done state2 a
281-
)
278+
instance (MonadState t m) => MonadState t (ParserT s m) where
279+
state k = lift (state k)
282280

283281
instance MonadThrow ParseError (ParserT s m) where
284282
throwError err = ParserT
@@ -360,18 +358,35 @@ instance MonadTrans (ParserT s) where
360358
lift' $ map (\a _ -> runFn2 done state1 a) m
361359
)
362360

361+
-- | Query and modify the `ParserT` internal state.
362+
-- |
363+
-- | Like the `state` member of `MonadState`.
364+
stateParserT :: forall s m a. (ParseState s -> Tuple a (ParseState s)) -> ParserT s m a
365+
stateParserT k = ParserT
366+
( mkFn5 \state1 _ _ _ done -> do
367+
let (Tuple a state2) = k state1
368+
runFn2 done state2 a
369+
)
370+
371+
-- | Query the `ParserT` internal state.
372+
-- |
373+
-- | Like the `get` member of `MonadState`.
374+
getParserT :: forall s m. ParserT s m (ParseState s)
375+
getParserT = ParserT
376+
( mkFn5 \state1 _ _ _ done -> runFn2 done state1 state1
377+
)
378+
363379
-- | Set the consumed flag.
364380
-- |
365381
-- | Setting the consumed flag means that we're committed to this parsing branch
366382
-- | of an alternative (`<|>`), so that if this branch fails then we want to
367383
-- | fail the entire parse instead of trying the other alternative.
368384
consume :: forall s m. ParserT s m Unit
369-
consume = modify_ \(ParseState input pos _) ->
370-
ParseState input pos true
385+
consume = stateParserT \(ParseState input pos _) -> Tuple unit (ParseState input pos true)
371386

372387
-- | Returns the current position in the stream.
373388
position :: forall s m. ParserT s m Position
374-
position = gets \(ParseState _ pos _) -> pos
389+
position = stateParserT \state1@(ParseState _ pos _) -> Tuple pos state1
375390

376391
-- | Fail with a message.
377392
fail :: forall m s a. String -> ParserT s m a

src/Parsing/String.purs

+5-6
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ module Parsing.String
5252
import Prelude hiding (between)
5353

5454
import Control.Monad.Rec.Class (Step(..), tailRecM)
55-
import Control.Monad.State (get)
5655
import Data.Array.NonEmpty as NonEmptyArray
5756
import Data.Either (Either(..))
5857
import Data.Enum (fromEnum, toEnum)
@@ -64,7 +63,7 @@ import Data.String.CodeUnits as SCU
6463
import Data.String.Regex as Regex
6564
import Data.String.Regex.Flags (RegexFlags)
6665
import Data.Tuple (Tuple(..))
67-
import Parsing (ParseError(..), ParseState(..), ParserT(..), Position(..))
66+
import Parsing (ParseError(..), ParseState(..), ParserT(..), Position(..), getParserT)
6867
import Parsing.Combinators (alt, try, (<?>))
6968
import Partial.Unsafe (unsafePartial)
7069

@@ -195,9 +194,9 @@ updatePosSingle (Position { index, line, column }) cp after = case fromEnum cp o
195194
-- | ```
196195
match :: forall m a. ParserT String m a -> ParserT String m (Tuple String a)
197196
match p = do
198-
ParseState input1 _ _ <- get
197+
ParseState input1 _ _ <- getParserT
199198
x <- p
200-
ParseState input2 _ _ <- get
199+
ParseState input2 _ _ <- getParserT
201200
-- We use the `SCU.length`, which is in units of “code units”
202201
-- instead of `Data.String.length`. which is in units of “code points”.
203202
-- This is more efficient, and it will be correct as long as we can assume
@@ -300,13 +299,13 @@ anyTill
300299
=> ParserT String m a
301300
-> ParserT String m (Tuple String a)
302301
anyTill p = do
303-
ParseState input1 _ _ <- get
302+
ParseState input1 _ _ <- getParserT
304303
Tuple input2 t <- tailRecM go unit
305304
pure $ Tuple (SCU.take (SCU.length input1 - SCU.length input2) input1) t
306305
where
307306
go unit = alt
308307
( do
309-
ParseState input2 _ _ <- get
308+
ParseState input2 _ _ <- getParserT
310309
t <- try p
311310
pure $ Done $ Tuple input2 t
312311
)

src/Parsing/Token.purs

+4-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ module Parsing.Token
2323
import Prelude hiding (between, when)
2424

2525
import Control.Lazy (fix)
26-
import Control.Monad.State (get, gets, modify_)
2726
import Control.MonadPlus (guard, (<|>))
2827
import Data.Array as Array
2928
import Data.Char (fromCharCode, toCharCode)
@@ -43,7 +42,7 @@ import Data.String.CodeUnits (singleton, toChar) as CodeUnits
4342
import Data.String.CodeUnits as SCU
4443
import Data.String.Unicode as Unicode
4544
import Data.Tuple (Tuple(..))
46-
import Parsing (ParseState(..), ParserT, consume, fail)
45+
import Parsing (ParseState(..), ParserT, consume, fail, getParserT, stateParserT)
4746
import Parsing.Combinators (between, choice, notFollowedBy, option, sepBy, sepBy1, skipMany, skipMany1, try, tryRethrow, (<?>), (<??>))
4847
import Parsing.Pos (Position)
4948
import Parsing.String (char, satisfy, satisfyCodePoint, string)
@@ -53,12 +52,11 @@ import Parsing.String.Basic as Basic
5352
-- | A parser which returns the first token in the stream.
5453
token :: forall m a. (a -> Position) -> ParserT (List a) m a
5554
token tokpos = do
56-
input <- gets \(ParseState input _ _) -> input
55+
ParseState input _ _ <- getParserT
5756
case List.uncons input of
5857
Nothing -> fail "Unexpected EOF"
5958
Just { head, tail } -> do
60-
modify_ \(ParseState _ _ _) ->
61-
ParseState tail (tokpos head) true
59+
stateParserT \(ParseState _ _ _) -> Tuple unit (ParseState tail (tokpos head) true)
6260
pure head
6361

6462
-- | A parser which matches any token satisfying the predicate.
@@ -75,7 +73,7 @@ match tokpos tok = when tokpos (_ == tok)
7573
-- | Match the “end-of-file,” the end of the input stream.
7674
eof :: forall a m. ParserT (List a) m Unit
7775
eof = do
78-
ParseState input _ _ <- get
76+
ParseState input _ _ <- getParserT
7977
if (List.null input)
8078
-- We must consume so this combines correctly with notFollowedBy
8179
then consume

0 commit comments

Comments
 (0)