Search code examples
haskellparsec

Haskell parsec parsing a string of items


I have a list that I need to parse where the all but the last element needs to be parsed by one parser, and the last element needs to be parsed by another parser.

a = "p1 p1b ... p2"
or
a = "p2"

Originally I tried

parser = do parse1 <- many parser1
            parse2 <- parser2
            return AParse parse1 parse2

The problem is that parse1 can consume a parse2 input. So parse1 always consumes the entire list, and leave parse2 with nothing.

Is there a way to say to apply parse1 to everything besides the last element in a string, and then apply parse2?


Solution

  • How about:

    parseTrain car caboose = choice
        [ fmap (:[]) $ try (caboose `endBy` eof), 
        , liftM2 (:) car (parseTrain car caboose) 
        [
    

    The eof bugs me, since that makes this parser not compositional. I.e. you couldn't say:

    char '(' >> parseTrain p1 p2 >> char ')'
    

    Doing this compsitionally is very hard for a parser. How is it supposed to know to move on to char ')', without trying to at every opportunity and seeing if it fails? Doing so could exponential time.

    If you need it to be compositional, does your problem have some additional structure you can exploit? Can you, for example, parse a list of all elements and then process the last one after the fact?