[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