[Haskell-cafe] Parsec question

Tomasz Zielonka tomasz.zielonka at gmail.com
Tue Apr 19 04:34:10 EDT 2005


On Tue, Apr 19, 2005 at 09:47:22AM +0200, Ketil Malde wrote:
> 
> Hi,
> 
> I've started using Parsec for my parsing needs, and must say I'm very
> happy with it.  There is one thing that I'm struggling with
> implementing though.
> 
> Basically, I want to parse a file containing multiple records.  I
> already have a parser for a single record, and of course I could parse
> the file simply as 
> 
>     many record
> 
> However, this gives me the type
> 
>     Either ParseError [Record]
> 
> which AFAICT, requires the whole file to be parsed correctly before
> any result is returned.  I think it would be better for my purposes to
> have a parser of type
> 
>      [Either ParseError Record]
> 
> so that the list of Records can be processed in an on-line fashion,
> until an error occurs.
> 
> Is there an obvious way to achieve this?

If you have one record per line, this is simple:
    map (parse record "?") (lines cs)

But if you want proper source positions in error messages or your
records are not so easily separated, you can use something like
this:

    lazyMany :: GenParser Char () a -> SourceName -> [Char] -> [a]
    lazyMany p file contents = lm state0
      where
        Right state0 = parse getParserState file contents

        lm state = case parse p' "" "" of
                        Left err -> error (show err)
                        Right x -> x
          where
            p' = do
              setParserState state
              choice
                [ do
                    eof
                    return []
                , do
                    x <- p
                    state' <- getParserState
                    return (x : lm state')
                ]

Best regards
Tomasz


More information about the Haskell-Cafe mailing list