[Haskell-beginners] writing many1Till combinator for Parsec

Vlad Skvortsov vss at 73rus.com
Mon Dec 14 17:35:13 EST 2009


Daniel Fischer wrote:
> You want a nonempty sequence of 'p's which aren't 'end's, followed by an 'end'.
> So you could do for example
> a)
> many1Till p end = do
>     ps <- manyTill p end
>     guard (not $ null ps)
>     return ps
>
> , i.e. check whether the result of manyTill is a nonempty list after the fact, or check 
> whether manyTill p end will return an empty list before manyTill is run, like
> b)
> many1Till p end = do
>     notFollowedBy end
>     manyTill p end
>
> (i.e. many1Till p end = notFollowedBy end >> manyTill p end).
>   

Thanks Daniel! I missed out on 'guard' and somewhy was under impression 
that 'notFollowedBy' can only deal with Chars.

>> 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;
>> 2) the error output should say that only 'p' parser is expected, while
>> it says (technically correct) that either 'p' or 'end' is expected:
>>
>> 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
>     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!

-- 
Vlad Skvortsov, vss at 73rus.com, http://vss.73rus.com



More information about the Beginners mailing list