3 ms·
So, I agree with your take as a reaction to this article specifically. However, I also think that there is a legitimate point here. Which is that parser combin
by eslaught 2y ago
So, I agree with your take as a reaction to this article specifically.
However, I also think that there is a legitimate point here. Which is that parser combinators, even in languages like Haskell, are shockingly tricky to use correctly. In particular, they violate the usual Haskell principle that "if it compiles, then it will probably run correctly". Having written multiple parsers in multiple languages with multiple parsing frameworks (including direct recursive descent), using Parsec in Haskell was the only time I had to write a test suite for the parser specifically. And that's because there were so many footguns that I was repeatedly making mistakes despite the fact that this was a port of a parser I'd already written (and therefore, ought to know backward and forward). (For the record, this was not my first Haskell project either, which is why I was so shocked it went so poorly.)
I'm sure it's possible to make mistakes in CFGs too, but practically speaking I can't remember running into that situation myself. Whereas with Parsec I ran into it repeatedly.
- HelloNurse 2y agoPEG parsing is likely to squash some grammar ambiguities in unexpected ways, making a test suite a very good idea; but we shouldn't forget that this kind of failure can only happen starting from an ambiguous grammar specification, so the work of taming PEG precedence or combinator behaviour is not an additional burden of the technology but an additional tool to correct the grammar to become less ambiguous, an alternative to rewriting it in unnatural, verbose and complex ways.
- yatac42 2y ago> but we shouldn't forget that this kind of failure can only happen starting from an ambiguous grammar specification I don't think that's true. The following CFG is unambiguous: S ::= A S | A A ::= 'a' | 'a' 'b' Yet if we translate this 1-to-1 to a PEG (without changing the order of the alternatives), it's not going to match any input with 'b's in it, so it doesn't match the same language.
- HelloNurse 2y agoThis grammar is difficult to adapt to ordered choice, having 4 possible variants that mostly define different languages from each other and from the "same" grammar with traditional parsing. It's a formally very different problem from spontaneously and arbitrarily disambiguating an ambiguous grammar, but in practice it causes the same kind of suffering and it's likely to be a more common issue.
- rowanG077 2y agoI have written a simple compiler in Haskell using parser combinators for parsing. And I couldn't disagree more with you. It was super straightforward writing the parser and it worked immediately. Why do say they are tricky?
- HelloNurse 2y agoWhat language did you compile? Some languages can be much more manageable than others. Did you adapt an existing CFG, or another parser combinator implementation, or did you start from scratch? The first case is more treacherous.
- rowanG077 2y agoStart from scratch. It was a basic c like syntax with sane typing syntax.
- eslaught 2y agoUnfortunately this was years ago so I'm not sure I can dig that far into specifics. Overall, combinators (almost by definition) have the property that you can plug anything into anything else. Haskell encourages a "zero-point" style where you don't even name the parameters (this is sort of the point of parser combinator libraries) and provides a bunch of fancy operators to glue them together in various ways. I think the mistakes I was making were mainly in just gluing the combinators together in the wrong way. It's not that the grammar was ambiguous, I just messed it up. You could say some of the same things about CFGs, and I guess that's true at some level. But in my opinion the syntax is more obvious and you don't usually spend time squinting at the syntax to remember how $ works or what order things execute in. And like I said, with parser combinators, there is no feedback (because everything compiles, more or less), so the only way to tell if it's working is to run it, which is a very un-Haskell-like experience.