parsingleft-recursiontop-down

Eliminating Left Recursion


So I have some grammar that doesn't work for a top-down parser due to it having left recursion:

L::= A a | B b
A::= L b | a a
B::= b B b | b a

So in order to fix this, I have to remove the left recursion. To do this, I do a little substitute-like-thing:

L::= A a | B b
A::= A a b | B b b | a a (I plugged in the possible values of "L")

A then turns to (I believe):

A::= a a A' | B b b
A'::= a b A' | ε

I'm fairly certain that I'm correct up to there (wouldn't be surprised if I'm not, though). Where I'm struggling is now removing the left recursion out of "B b b". I've tried going about this so many ways, and I don't think any of them work. Here's one that seems most logical, but ugly as well (thus saying it's probably wrong). Starting by manipulating B::= b B b | b a

B::= b B b | b a
B::= b B' (they both start with b, so maybe i can pull it out?)
B'::= B b | a
B'::= b B' b | a (substituted B's value in)
B'::= b B" | a
B"::= b B" |a B" | ε

So I guess to show what the finalized B's would be:

B::= b B'
B'::= b B" | a
B"::= b B" | a B" | ε

This seems way too ugly to be correct. Especially since I'd have to plug that into the new "A" terminals that I created.

Can someone help me out? No idea if I'm going about this the right way. I'm supposed to be able to create an LL(1) parse table afterward (should be able to do that part on my own).

Thanks.


Solution

  • In a parser that tries to expand nonterminals from the left, if some nonterminal can expand to a string with itself on the left, the parser may expand that nonterminal forever without actually parsing anything. This is left recursion. On the other hand, it is perfectly fine if a nonterminal expands to a string with some different nonterminal on the left, as long as no chain of expansions produces a string with the original nonterminal on the left. Similarly, it is fine if nonterminals aren't all the way to the right in the expansion, as long as they're not all the way to the left.

    tl;dr There's nothing wrong with B b b or b B b. You've removed all the left recursion. You don't need to keep going.