Why is parsecs “choice” combinator seemingly stuck on the first choice?

Parsec's strategy is essentially LL(1), which means that it "commits" to the current branch whenever any input is consumed. Your openTag parser consumes the with its char which means that if when it sees instead of the whole parse fails instead of trying a new choice. If openTag didn't consume any input and failed, another choice would be tried.

Parsec does this for efficiency (the alternative is exponential time! ) and for reasonable error messages You have two options. The preferred option, when it is reasonable to pull off, is to factor your grammar so that all choices are made without consuming input, eg. : tag = word (char '> tagbody) where tagbody = do content ", char '>' Modulo errors and style (my brain is a bit fried at the moment :-P) The other way, which locally changes parsec's semantics (at the expense of the aforementioned error messages and efficiency -- but it's not usually too bad because it's local), is to use the try combinator which allows a parser to consume input and still fail "softly" so another choice can be tried: nulltag = try $ between (char '") word -- etc Sometimes using try is cleaner and easier than factoring like above, which can obscure the "deep structure" of the language.

It's a stylistic trade-off.

Parsec's strategy is essentially LL(1), which means that it "commits" to the current branch whenever any input is consumed. Your openTag parser consumes the instead of /, the whole parse fails instead of trying a new choice. If openTag didn't consume any input and failed, another choice would be tried.

Parsec does this for efficiency (the alternative is exponential time! ) and for reasonable error messages. You have two options.

The preferred option, when it is reasonable to pull off, is to factor your grammar so that all choices are made without consuming input, eg. : tag = word (char '> tagbody) where tagbody = do content ", char '>' Modulo errors and style (my brain is a bit fried at the moment :-P). The other way, which locally changes parsec's semantics (at the expense of the aforementioned error messages and efficiency -- but it's not usually too bad because it's local), is to use the try combinator which allows a parser to consume input and still fail "softly" so another choice can be tried: nulltag = try $ between (char '") word -- etc.Sometimes using try is cleaner and easier than factoring like above, which can obscure the "deep structure" of the language. It's a stylistic trade-off.

2 Good answer - a further note on try. Parsec is perhaps unusual in that it allows you to write lexing functions (Char parsers) using the same code as regular "syntax" parsers. For Char parsers try is very valuable; for syntax parsers try is problematic and best avoided usually by left-factoring your grammar.

– stephen tetley Apr 18 at 9:19 Thanks so much! Exactly what I needed to know. – nont Apr 18 at 13:27.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions