Evan Laforge | 5 Jul 03:01

nested parsing?

Here's something I occasionally want to do with parsec:

msg = do
    header
    body <- manyTill anyToken footer
    vals <- sub_parse parse_body (preprocess body)
    ...

By coincidence I notice that perhaps the "manyTill stack overflow"
thread could use something like this too.  So I wrote:

sub_parse :: Parsec.GenParser subtok st a -> [subtok]
    -> Parsec.GenParser tok st a
sub_parse parser toks = do
    st <- Parsec.getState
    pos <- Parsec.getPosition
    case Parsec.runParser (Parsec.setPosition pos >> parser) st "" toks of
        Left err -> fail (show err)
        Right val -> return val
    -- oh yes, and I'd set the state to the final sub parse state too

In this particular case, I found another solution that didn't need
sub-parsing, so I haven't actually tested this much.  In particular
parsec doesn't let me throw a "raw" exception so I have to use "fail"
and the error msgs look ugly.  In addition, if 'preprocess' adds or
removes tokens from 'body', I have to do something awkward like pass
tokens around as (pos, tok).

But come to think of it, I've done this pattern before, where I invoke
a sub-monad and (mostly) splice it in with the current one, in one
(Continue reading)


Gmane