[Haskell-beginners] writing many1Till combinator for Parsec

Daniel Fischer daniel.is.fischer at web.de
Mon Dec 14 18:57:15 EST 2009


Am Montag 14 Dezember 2009 23:35:13 schrieb Vlad Skvortsov:
>
> Thanks Daniel! I missed out on 'guard' and somewhy was under impression
> that 'notFollowedBy' can only deal with Chars.

That's correct, its type is 

notFollowedBy :: Show tok => GenParser tok st tok -> GenParser tok st ()

I didn't lookup the type. However, you can easily generalize it:

nFB p = ((try p >> pzero) <|> return ()) <?> ""

Be aware, however, that the use of try may have adverse effects on performance.

> >> many1Till :: Parser a -> Parser end -> Parser [a]
> >> many1Till p end = do
> >>   try (end >> (unexpected "sequence terminator"))
> >>   <|> (do { p1 <- p; ps <- manyTill p end; return (p1:ps) })
> >>
> >> Here there are two disadvantages:
> >>
> >> 1) I don't like hardcoding "sequence terminator" here;

Understandable, but I haven't a better idea either.

> >> 2) the error output should say that only 'p' parser is expected, while
> >> it says (technically correct) that either 'p' or 'end' is expected:

Remove expectations of end by labelling the test with an empty string:

many1Till p end =
    ((try end >> unexpected "whatever") <?> "")
    <|> do { p1 <- p; ps <- manyTill p end; return (p1:ps) }

> >>
> >> Prelude Main Text.ParserCombinators.Parsec> parseTest (many1Till letter
> >> (char '.')) "1"
> >> parse error at (line 1, column 1):
> >> unexpected "1"
> >> expecting "." or letter
> >>
> >> (What I want here is to say "expecting letter")
> >
> > For that, you need the slightly clumsier
> > c)
> > many1Till p end = do
> >     notFollowedBy end

make that nFB end or better ((try end >> unexpected "whatever") <?> "")

> >     p1 <- p
> >     ps <- manyTill p end
> >     return (p1:ps)
>
> Yep, that works but still provides incorrect diagnostics when fed with
> an empty string:
>
> Prelude Main Text.ParserCombinators.Parsec> parseTest (many1Till letter
> (char '.')) ""
> parse error at (line 1, column 1):
> unexpected end of input
> expecting "." or letter
>
> It's not a showstopper, but I'd still like to understand how to make it
> provide better error messages.
>
> Thanks!



More information about the Beginners mailing list