[Haskell-cafe]
Re: [Haskell] Parsec question: attempted 'notMatching'
combinator
Graham Klyne
gk at ninebynine.org
Wed Feb 18 10:48:39 EST 2004
[To Haskell-cafe...]
At 16:57 17/02/04 -0500, Andrew Pimlott wrote:
>On Tue, Feb 17, 2004 at 07:48:52PM +0000, Graham Klyne wrote:
> > Thanks! That got me going, though not with quite what you suggested.
> >
> > I ended up with this:
> > [[
> > notMatching :: Show a => GenParser tok st a -> GenParser tok st ()
> > notMatching p = do { a <- try p ; unexpected (show a) } <|> return ()
> > ]]
> > which does the required job for me.
>
>Oops, that does look better. I knew the try had to go somewhere. :-)
>
>The only remaining problem is when p succeeds but does not consume any
>input, eg eof. In this case, the <|> return () cannot distinguish it
>from p failing.
>
>I didn't realize at first what a dirty trick this function uses: It
>distinguishes success or failure of p by whether any input from the
>first part (before <|> return ()) was consumed. I don't think it is
>possible (or desirable!) to get this approach 100% right: By "erasing"
>the success of p, you lose the information you need.
>
>What about a more prosaic implementation:
>
> notFollowedBy' :: Show a => GenParser tok st a -> GenParser tok st ()
> notFollowedBy' p = do res <- do a <- try p; return $ Just a
> <|>
> return Nothing
> case res of Just a -> unexpected (show a)
> Nothing -> return ()
I don't see why that would work where the above case does not; i.e. when p
consumes no input.
Or indeed, your later, preferred version:
[[
notFollowedBy' :: Show a => GenParser tok st a -> GenParser tok st ()
notFollowedBy' p = join $ do a <- try p; return (unexpected (show a))
<|>
return (return ())
]]
>This works for the tests I've tried, but there's one little quirk with
>error reporting:
I never really cared so much about that bit!
#g
--
> aNoBC = do char 'a'
> notFollowedBy' $ do char 'b'; char 'c'
>
> *Main> parseTest (aNoBC >> char 'e') "abe"
> parse error at (line 1, column 2):
> unexpected "e"
> expecting "c" or "e"
>
>It seems that parsec both misreports which token is unexpected (should
>be "b", and thinks that the failure to match "c" is a problem, even
>though notFollowedBy' succeeded.
>
> > Using your version caused the notMatching parser to be equivalent to:
> > return ()
> > presumably, because the failure was protected by the try combinator?
>
>Or perhaps more accurately, the success (of p) was protected by the try!
>Ie, the unexpected and the try together undid the tell-tale token
>consumption of p.
>
>Andrew
------------
Graham Klyne
For email:
http://www.ninebynine.org/#Contact
More information about the Haskell-Cafe
mailing list