|laziness, impatience, and hubris|
Re^3: Left-associative binary operators in Parse::RecDescentby jryan (Vicar)
|on Dec 14, 2004 at 23:10 UTC||Need Help??|
Yeah, look at all of that crazy recursion! I was trying to steer you away from that in my other reply, but I had this freaking meeting to go to, so I guess I wasn't very clear in my explantion because I was in a rush. Apologies for that; I'll be more thorough here.
Like I said in my other reply, a binop is essentially a string of expressions at the same precedence that are executed in sequence. (Earlier, you only had 1 level of precedence, so you could get away with just changing one rule.) The classic recursive/BNF way to do this is with a tail/right-recursive call back to the original rule. Unfortunately, recursion is really slow, especially when something has to back-track. However, tail-recursion can also be implemented as a loop, but only if the grammar engine has the capabilities.
Luckily, PRD does infact have these capabilities via leftop, (s), and (s?). So, if we take a rule like:
We can turn this into the loop form:
And so, we continue down the precedence ladder, until we get to paren_expr, which should really be called something like "single_expr". paren_expr then needs to recurse back up to the top of the precedence list like you have, as this is unavoidable. Of course, we can capture more precisely with PRD, and so with these modifications, we come up with:
And, if you test it, you'll find it runs very fast now.
A couple more notes: