7 ms·
As an exercise in showing how LR works, this was an interesting article. However, I'm unconvinced that this would be a good approach to implement in a real sys
by dwheeler 9y ago
As an exercise in showing how LR works, this was an interesting article. However, I'm unconvinced that this would be a good approach to implement in a real system when the grammar might change in the future (and they pretty much always do). When things change, I think it'd be difficult to keep it correct, and there are lots of tools to help (such as bison and ANTLR). I've implemented several recursive-descent parsers; their simplicity makes it practical to do directly. But recursive-descent, if you're going to use it, seems to cry out for tooling. Does anyone have a different experience?
- tyingq 9y agoHaven't used it myself, but have heard many rave about Perl's Parse::RecDescent
- swiley 9y agoRecursive descent is very different (if I understand correctly.) Some languages that can be parsed with a recursive ascent parser cannot be parsed by a recursive descent parser.
- tyingq 9y agoRight. Was responding to "But recursive-descent, if you're going to use it, seems to cry out for tooling"
- barrkel 9y agoAs I mentioned in an uncle comment, recursive descent permits localised hackery to switch parsing scheme or dynamically fix tricky context-specific grammar constructs, which argues against tooling. Tooling is still very useful for grammar validation though, and it's the way to go for ad hoc parsing of a simple or new language.
- rejschaap 9y agoThat was a typo, he meant to say recursive-ascent needs tooling. Recursive-descent parsers can be hand-written quite easily.
- barrkel 9y agoYes; left recursion. However in practice left recursion can usually be eliminated by adjusting the grammar. Other cases can be handled using various degrees of grammar action cleverness. And finally, recursive descent lends itself naturally to parsing a subset of the language using a different scheme; top down operator precedence for expressions to avoid lots of redundant recursion is a fine example.
- nnq 9y ago> can usually be eliminated by adjusting the grammar Never understood this backwards way of thinking. You first write/immagine the grammar that you want to write, whatever is most intuitive for you. Then you figure out what kind of parser your grammar needs. Why would one contort a grammar? I mean, even "contorting it to not be context-dependent" is already a limitation enough...
- barrkel 9y agoWhy would you let the grammar dictate the architecture of your compiler? Left recursion in things like expressions is completely trivial to eliminate. If you want to e.g. embed a DSL in a language, something that's really easy to do with recursive descent, it's worth spending 30 seconds or so to remove left recursion from your expression rules. Etc. > You first write/immagine the grammar that you want to write, whatever is most intuitive for you. IMO this is the road to hard to parse languages; if you genuinely advocate this path, you'll end up needing a GLR parser before you know it. I think it's much better to ensure your grammar is parseable with LL(1); not only is the tooling simpler, but the language will be less ambiguous for human users too. Follow the example of Pascal, not C++. This is what I'd advocate even for people doing hand-written recursive descent on a new language: validate your grammar with an LL(k) tool even if you don't use the generated parser. (You've ended up sounding a bit like Ira Baxter, who's often seen around the net selling his DMS toolkit. He has a strong self-interest in people writing complicated grammars, so that he can sell them his services...)
- tom_mellior 9y ago> You've ended up sounding a bit like Ira Baxter Haha, I was thinking about him too. He does have a point, though, that on 2018 machines we might be able to afford parsing technology a bit more expensive than the 1970s approaches commonly used today.
- FractalLP 9y agoI think Damian Conway (Perl Author, Keynote speaker, compsci professor, seemingly super nice guy too) wrote the recursive descent parser module and its successor module, although someone else maintains it now on CPAN.
- agumonkey 9y agoif his code is as interesting as his talks then I want to write parsers in perl
- FractalLP 9y agoI barely even write perl, but still read part of his OO book and learned a lot
- tyingq 9y agoPerl OO is underrated. The bless() function and Perl's packages are straightforward and make OO seem less magic. You even get to pick the encapsulation. Most people go with hashtable based objects, but you can use lists or even strings instead. It's a really good language to see how OO works under the covers. https://perldoc.perl.org/perlootut.html https://perldoc.perl.org/perlootut.html https://perldoc.perl.org/perlobj.html https://perldoc.perl.org/perlobj.html
- FractalLP 9y agoAgreed. I found it a bit of a pain though to write using it as most languages have so much syntactic sugar for OO.
- userbinator 9y agoI'm not aware of any practical uses of recursive ascent either; given that the major production-quality compilers (GCC, Clang, icc, MSVC) all use handwritten recursive descent and can handle grammars as complex as C++, it doesn't seem the claimed extra power of an LR parser is really needed at all in practice.
- watwut 9y agoThe biggest issue is not so much parsing the grammar itself, that part is relatively easy, but reasonable error handing and recovery from errors. I think that is why they use something that is hand-written.
- Rusky 9y agoYeah, I agree. When writing this I spent a lot of time keeping track of LR states to decide how to split things up into functions, but in a recursive descent parser that's already decided by the grammar. I can see myself using it for expression parsing, though, since that's almost inherently left-recursive. I usually use top-down operator precedence (AKA pratt parsing) for that, but recursive ascent might simplify it in some ways.
- abecedarius 9y agoExpression parsing without left recursion can be straightforward: https://github.com/darius/parson/blob/master/eg_calc.py https://github.com/darius/parson/blob/master/eg_calc.py A left-associative operator means a Kleene star in the grammar, while a right-associative operator means right-recursion. I think the common view that it's left-recursive is just a weakness of the most common scheme for semantic actions. (I mean, yes, if you need to go through a parse tree first then the tree needs to be left-recursive -- but it seems simpler not to do that.)
- Rusky 9y agoThe idea that it's left-recursive is not changed by the existence of top-down operator precedence, or kleene stars, or right recursion. And it's not a weakness, either- just one way to think about the problem which happens to map fairly naturally to how people think about expressions.
- lihaoyi 9y agoIf you do not mind a small performance hit then a PEG parser combinator library like FastParse (http://www.lihaoyi.com/post/EasyParsingwithParserCombinators.html http://www.lihaoyi.com/post/EasyParsingwithParserCombinators...) is basically tooling to help you write recursive descent parsers. Way easier to set up and learn the bison/antlr if you don't need best-of-the-best performance: just import the library, start sketching out how your parser should behave and you're off to the races: parsing, debugging, error-reporting, etc. are all made really easy. At least in the Scala community, FastParse is used quite a lot. Works great for parsing source code, obscure data-formats (textual or binary), user query-languages, etc.. As long as you're not parsing gigabytes of big data, you probably won't even notice the 5-10x performance hit.
- necubi 9y agoFor Rust there's the nom [0] parser combinator library. Very pleasant to use, good support for expressing parse errors, with speed quite close to hand-written parsers. [0] https://github.com/Geal/nom https://github.com/Geal/nom
- dwheeler 9y agoWhups... I meant to say that I can see hand-implementing recursive-descent, but recursive-ASCENT seems to cry out for tooling. Especially since there are so many good tools out there.