[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