@@ -19,42 +19,51 @@ import Control.Monad.Error.Trans
19
19
import Control.MonadPlus
20
20
import Control.Plus
21
21
22
+ import Text.Parsing.Parser.Pos
23
+
22
24
data ParseError = ParseError
23
25
{ message :: String
26
+ , position :: Position
24
27
}
25
28
26
29
instance errorParseError :: Error ParseError where
27
- noMsg = ParseError { message: " " }
28
- strMsg msg = ParseError { message: msg }
30
+ noMsg = ParseError { message: " " , position: initialPos }
31
+ strMsg msg = ParseError { message: msg, position: initialPos }
29
32
30
33
instance showParseError :: Show ParseError where
31
- show (ParseError msg) = " ParseError { message: " ++ msg.message ++ " }"
34
+ show (ParseError msg) = " ParseError { message: " ++ msg.message ++ " , position: " ++ show msg.position ++ " }"
35
+
36
+ -- | `PState` contains the remaining input and current position.
37
+ data PState s = PState
38
+ { input :: s
39
+ , position :: Position
40
+ }
32
41
33
- newtype ParserT s m a = ParserT (s -> m { input :: s , result :: Either ParseError a , consumed :: Boolean } )
42
+ newtype ParserT s m a = ParserT (PState s -> m { input :: s , result :: Either ParseError a , consumed :: Boolean , position :: Position } )
34
43
35
- unParserT :: forall m s a . ParserT s m a -> s -> m { input :: s , result :: Either ParseError a , consumed :: Boolean }
44
+ unParserT :: forall m s a . ParserT s m a -> PState s -> m { input :: s , result :: Either ParseError a , consumed :: Boolean , position :: Position }
36
45
unParserT (ParserT p) = p
37
46
38
- runParserT :: forall m s a . (Monad m ) => s -> ParserT s m a -> m (Either ParseError a )
47
+ runParserT :: forall m s a . (Monad m ) => PState s -> ParserT s m a -> m (Either ParseError a )
39
48
runParserT s p = do
40
49
o <- unParserT p s
41
50
return o.result
42
51
43
52
type Parser s a = ParserT s Identity a
44
53
45
54
runParser :: forall s a . s -> Parser s a -> Either ParseError a
46
- runParser s = runIdentity <<< runParserT s
55
+ runParser s = runIdentity <<< runParserT ( PState { input: s, position: initialPos })
47
56
48
57
instance functorParserT :: (Functor m ) => Functor (ParserT s m ) where
49
58
(<$>) f p = ParserT $ \s -> f' <$> unParserT p s
50
59
where
51
- f' o = { input: o.input, result: f <$> o.result, consumed: o.consumed }
60
+ f' o = { input: o.input, result: f <$> o.result, consumed: o.consumed, position: o.position }
52
61
53
62
instance applyParserT :: (Monad m ) => Apply (ParserT s m ) where
54
63
(<*>) = ap
55
64
56
65
instance applicativeParserT :: (Monad m ) => Applicative (ParserT s m ) where
57
- pure a = ParserT $ \s -> pure { input: s, result: Right a, consumed: false }
66
+ pure a = ParserT $ \( PState { input: s, position: pos }) -> pure { input: s, result: Right a, consumed: false , position: pos }
58
67
59
68
instance altParserT :: (Monad m ) => Alt (ParserT s m ) where
60
69
(<|>) p1 p2 = ParserT $ \s -> unParserT p1 s >>= \o ->
@@ -70,29 +79,35 @@ instance alternativeParserT :: (Monad m) => Alternative (ParserT s m)
70
79
instance bindParserT :: (Monad m ) => Bind (ParserT s m ) where
71
80
(>>=) p f = ParserT $ \s -> unParserT p s >>= \o ->
72
81
case o.result of
73
- Left err -> return { input: o.input, result: Left err, consumed: o.consumed }
74
- Right a -> updateConsumedFlag o.consumed <$> unParserT (f a) o.input
82
+ Left err -> return { input: o.input, result: Left err, consumed: o.consumed, position: o.position }
83
+ Right a -> updateConsumedFlag o.consumed <$> unParserT (f a) ( PState { input: o.input, position: o.position })
75
84
where
76
- updateConsumedFlag c o = { input: o.input, consumed: c || o.consumed, result: o.result }
85
+ updateConsumedFlag c o = { input: o.input, consumed: c || o.consumed, result: o.result, position: o.position }
77
86
78
87
instance monadParserT :: (Monad m ) => Monad (ParserT s m )
79
88
80
89
instance monadPlusParserT :: (Monad m ) => MonadPlus (ParserT s m )
81
90
82
91
instance monadTransParserT :: MonadTrans (ParserT s ) where
83
- lift m = ParserT $ \s -> (\a -> { input: s, consumed: false , result: Right a }) <$> m
92
+ lift m = ParserT $ \( PState { input: s, position: pos }) -> (\a -> { input: s, consumed: false , result: Right a, position: pos }) <$> m
84
93
85
94
instance monadStateParserT :: (Monad m ) => MonadState s (ParserT s m ) where
86
- state f = ParserT $ \s ->
95
+ state f = ParserT $ \( PState { input: s, position: pos }) ->
87
96
return $ case f s of
88
- Tuple a s' -> { input: s', consumed: false , result: Right a }
97
+ Tuple a s' -> { input: s', consumed: false , result: Right a, position: pos }
89
98
90
99
instance lazy1ParserT :: Lazy1 (ParserT s m ) where
91
100
defer1 f = ParserT $ \s -> unParserT (f unit) s
92
101
93
102
consume :: forall s m . (Monad m ) => ParserT s m Unit
94
- consume = ParserT $ \s -> return { consumed: true , input: s, result: Right unit }
103
+ consume = ParserT $ \( PState { input: s, position: pos }) -> return { consumed: true , input: s, result: Right unit, position: pos }
95
104
96
105
fail :: forall m s a . (Monad m ) => String -> ParserT s m a
97
- fail message = ParserT $ \s -> return { input: s, consumed: false , result: Left (ParseError { message: message }) }
106
+ fail message = ParserT $ \(PState { input: s, position: pos }) -> return $ parseFailed s pos message
107
+
108
+ -- | Creates a failed parser state for the remaining input `s` and current position
109
+ -- | with an error message.
110
+ -- | Most of the time, `fail` should be used instead.
111
+ parseFailed :: forall s a . s -> Position -> String -> { input :: s , result :: Either ParseError a , consumed :: Boolean , position :: Position }
112
+ parseFailed s pos message = { input: s, consumed: false , result: Left (ParseError { message: message, position: pos }), position: pos }
98
113
0 commit comments