2
2
3
3
module Text.Parsing.Parser.Stream where
4
4
5
- import Control.Monad.State (modify , gets )
5
+ import Control.Monad.State (put , get )
6
6
import Control.Monad.Trans.Class (lift )
7
- import Data.Foldable (fold , elem , notElem )
7
+ import Data.Foldable (foldl , elem , notElem )
8
8
import Data.List as L
9
9
import Data.List.Lazy as LazyL
10
10
import Data.Maybe (Maybe (..))
11
- import Data.Monoid.Endo (Endo (..))
12
- import Data.Newtype (class Newtype , unwrap )
11
+ import Data.Newtype (class Newtype )
13
12
import Data.String as S
13
+ import Data.Tuple (Tuple (..))
14
14
import Prelude hiding (between )
15
15
import Text.Parsing.Parser (ParseState (..), ParserT , fail )
16
16
import Text.Parsing.Parser.Combinators (tryRethrow , (<?>))
@@ -36,60 +36,63 @@ instance charHasUpdatePosition :: HasUpdatePosition Char where
36
36
updatePos = updatePosChar
37
37
38
38
-- | This class exists to abstract over streams which support the string-like
39
- -- | operations which this modules needs.
39
+ -- | operations with position tracking, which this modules needs.
40
40
-- |
41
41
-- | Instances must satisfy the following laws:
42
- -- | - `stripPrefix (Prefix a) a >>= uncons = Nothing`
42
+ -- | - `stripPrefix (Prefix input) {input, position} >>= uncons = Nothing`
43
+
43
44
class Stream s m t | s -> t where
44
- uncons :: s -> m (Maybe { head :: t , tail :: s , updatePos :: Position -> Position } )
45
- stripPrefix :: Prefix s -> s -> m (Maybe { rest :: s , updatePos :: Position -> Position } )
45
+ uncons :: forall r . ParserCursor s r -> m (Maybe (Tuple t (ParserCursor s r )))
46
+ stripPrefix :: forall r . Prefix s -> ParserCursor s r -> m (Maybe (ParserCursor s r ))
47
+
48
+ -- Part or ParseState which is exposed to Stream instances
49
+ type ParserCursor s r = { input :: s , pos :: Position | r }
50
+
46
51
47
- instance stringStream :: (Applicative m ) => Stream String m Char where
48
- uncons f = pure $ S .uncons f <#> \({ head, tail}) ->
49
- { head, tail, updatePos: (_ ` updatePos` head) }
50
- stripPrefix (Prefix p) s = pure $ S .stripPrefix (S.Pattern p) s <#> \rest ->
51
- { rest, updatePos: (_ ` updatePos` p) }
52
+ instance stringStream :: (Applicative m ) => Stream String m Char where
53
+ uncons state = pure $ S .uncons state.input <#> \({ head, tail}) ->
54
+ Tuple head state{input = tail, pos = updatePos state.pos head }
55
+ stripPrefix (Prefix p) state = pure $ S .stripPrefix (S.Pattern p) state.input <#> \rest ->
56
+ state{input = rest, pos = updatePos state.pos p }
52
57
53
58
instance listStream :: (Applicative m , Eq a , HasUpdatePosition a ) => Stream (L.List a ) m a where
54
- uncons f = pure $ L .uncons f <#> \({ head, tail}) ->
55
- { head, tail, updatePos: (_ ` updatePos` head) }
56
- stripPrefix (Prefix p) s = pure $ L .stripPrefix (L.Pattern p) s <#> \rest ->
57
- { rest, updatePos: unwrap (fold (p <#> (flip updatePos >>> Endo ))) }
59
+ uncons state = pure $ L .uncons state.input <#> \({ head, tail}) ->
60
+ Tuple head state{input = tail, pos = updatePos state.pos head }
61
+ stripPrefix (Prefix p) state = pure $ L .stripPrefix (L.Pattern p) state.input <#> \rest ->
62
+ state{input = rest, pos = foldl updatePos state.pos p }
58
63
59
64
instance lazyListStream :: (Applicative m , Eq a , HasUpdatePosition a ) => Stream (LazyL.List a ) m a where
60
- uncons f = pure $ LazyL .uncons f <#> \({ head, tail}) ->
61
- { head, tail, updatePos: (_ ` updatePos` head) }
62
- stripPrefix (Prefix p) s = pure $ LazyL .stripPrefix (LazyL.Pattern p) s <#> \rest ->
63
- { rest, updatePos: unwrap (fold (p <#> (flip updatePos >>> Endo ))) }
65
+ uncons state = pure $ LazyL .uncons state.input <#> \({ head, tail}) ->
66
+ Tuple head state{input = tail, pos = updatePos state.pos head }
67
+ stripPrefix (Prefix p) state = pure $ LazyL .stripPrefix (LazyL.Pattern p) state.input <#> \rest ->
68
+ state{input = rest, pos = foldl updatePos state.pos p }
64
69
65
70
-- | Match end of stream.
66
71
eof :: forall s t m . Stream s m t => Monad m => ParserT s m Unit
67
72
eof = do
68
- input <- gets \( ParseState input _ _) -> input
69
- (lift $ uncons input ) >>= case _ of
73
+ ParseState state <- get
74
+ (lift $ uncons state ) >>= case _ of
70
75
Nothing -> pure unit
71
76
_ -> fail " Expected EOF"
72
77
73
78
-- | Match the specified prefix.
74
79
prefix :: forall f c m . Stream f m c => Show f => Monad m => f -> ParserT f m f
75
80
prefix p = do
76
- input <- gets \( ParseState input _ _) -> input
77
- (lift $ stripPrefix (Prefix p) input ) >>= case _ of
78
- Just {rest, updatePos} -> do
79
- modify \( ParseState _ position _) ->
80
- ParseState rest (updatePos position) true
81
+ ParseState state <- get
82
+ (lift $ stripPrefix (Prefix p) state ) >>= case _ of
83
+ Nothing -> fail $ " Expected " <> show p
84
+ Just state -> do
85
+ put $ ParseState state{consumed = true }
81
86
pure p
82
- _ -> fail (" Expected " <> show p)
83
87
84
88
-- | Match any token.
85
89
token :: forall s t m . Stream s m t => Monad m => ParserT s m t
86
90
token = do
87
- input <- gets \( ParseState input _ _) -> input
88
- (lift $ uncons input ) >>= case _ of
91
+ ParseState state <- get
92
+ (lift $ uncons state ) >>= case _ of
89
93
Nothing -> fail " Unexpected EOF"
90
- Just ({ head, updatePos, tail }) -> do
91
- modify \(ParseState _ position _) ->
92
- ParseState tail (updatePos position) true
94
+ Just (Tuple head nextState) -> do
95
+ put $ ParseState nextState{consumed = true }
93
96
pure head
94
97
95
98
-- | Match a token satisfying the specified predicate.
0 commit comments