[Haskell-beginners] writing many1Till combinator for Parsec

Vlad Skvortsov vss at 73rus.com
Fri Dec 11 19:58:11 EST 2009


I'm writing a parser where I find myself in need to use manyTill 
combinator with an additional constraint that there should be at least 
one meaningful element before the trailer (say, a word ended with a 
period: 'abc.').

Here is what I have:

many1Till :: Parser a -> Parser end -> Parser [a]
many1Till p end = do
  p1 <- p
  ps <- manyTill p end
  return (p1:ps)

The problem here is that I want to catch and report a case when 'p1' 
could be actually parsed by 'end' ('..' is not a word ended by a 
period). Generally 'p' and 'end' can parse the same subset of strings.

Another version a had was:

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")

Any suggestions?


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

More information about the Beginners mailing list