Reputation: 163
I have a parser monad that looks like this:
data Parser b a = P(b -> [(a, b)])
instance Monad (Parser p) where
p >>= f = P $ \inp -> case parse p inp of
[] -> []
[(v, inp')] -> parse (f v) inp'
I also have the following functions/parsers for getting and setting the state of the parser:
getState :: Parser b b
getState = P(\inp -> [(inp, inp)])
setState b -> Parser b ()
setState s = P(\inp -> [(), s)]
Additionally, I have a Parser function that looks ahead to see if there is more to parse without consuming anything:
lookahead :: Parser b a -> Parser b ()
lookahead p = do
state <- getState
result <- p
setState state
return result
Now, suppose I want to write a Parser function that succeeds if another parser fails: It should fail if there are more to consume and succeed if there isn't.
notFollowedBy :: Parser b a -> Parser b ()
notFollowedBy p = do --statements
The intended usage is to disallow illegal parsers to continue, according to some grammar.
This has me kind of stumped: To my (limited) understanding of Monads, they provide you with a safety net in case any of the evaluations fails. Is there a (good and recommended) way to make this function do the opposite?
Upvotes: 0
Views: 285
Reputation: 85907
Here's how you could implement notFollowedBy
in your parser:
notFollowedBy :: Parser b a -> Parser b ()
notFollowedBy p = P (\inp -> case parse p inp of
[] -> [((), inp)]
_ -> [])
This definition relies on being able to access the internals of Parser
(specifically the P
constructor).
Alternatively you can do the following:
notFollowedBy p = do
inp <- getState
case parse p inp of
[] -> return ()
_ -> fail "sub-parse succeeded"
Upvotes: 2