[Haskell-cafe] Parsec, state and/of my cluelessness
robert dockins
robdockins at fastmail.fm
Mon Oct 17 14:53:27 EDT 2005
[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.
More information about the Haskell-Cafe
mailing list