[snip]

Now comes the tricky part for me. Since the control can have three different
types of children I use a helper that parses the body of the control using other
parsers, collecting their results in three lists:

ctrlBodyParser :: CharParser ([Value], [Property], [Control]) ([Value], [Property], [Control])
ctrlBodyParser =
    do { c <- ctrlParser -- parse child control
       ; (vs, ps, cs) <- getState
       ; setState (vs, ps, (c : cs))
       ; ctrlBodyParser
       }
    <|>

 [snip some alternatives]

    <|>
    do { getState } -- we're finished, return children


I think you might do better to make it tail-recursive (sort of) by passing intermediate lists as parameters to ctrlBodyParser rather than using state. Parsec state (if I recall correctly) needs to have the same type throughout the parse, but here you really just want a bit of help accumulating some results in a section of the parse tree. Try this:

ctrlBodyParser :: Parser ([Value],[Property],[Control])
ctrlBodyParser = ctrlBodyParser0 [] [] []

ctrlBodyParser0 :: [Value] -> [Property] -> [Control] ->
    Parser ([Value],[Property],[Control])
ctrlBodyParser0 vs ps cs =
    do { c <- ctrlParser; ctrlBodyBodyParser0 vs ps (c : cs) }
    <|>
    .... etc
    <|>
    do { return (vs,ps,cs) }


Be aware that your lists will come out in the reverse order that they apper in the text.

You can also use a single labeled record instead of the three list parameters and a tuple.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to