Left Recursion
Understand what left recursion is, why it causes top-down parsers to loop forever, and how to eliminate it — both direct and indirect — using a systematic algorithm.
What is Left Recursion?
A grammar rule is left-recursive if a non-terminal can derive a string that begins with itself.
Direct left recursion:
Example:
Here, E → E + T is directly left-recursive because E is the leftmost symbol on the right side.
Indirect left recursion:
A does not directly start with A, but:
- A expands to B...
- B expands back to A...
So we have a cycle: A → B → A.
Intuitive Understanding
Think of left recursion like this: before a non-terminal A can produce anything, it first needs to process another copy of A. But that copy of A again needs to process a copy of A, and so on — infinitely.
This is exactly what happens when a top-down parser (like recursive descent) tries to handle a left-recursive grammar — it enters an infinite loop.
Why is Left Recursion a Problem?
Bottom-up parsers (LR parsers) handle left recursion fine. They work from the input upward, so they never need to predict what comes first — they just keep reducing.
Top-down parsers (LL parsers, recursive descent) read the input left to right and try to expand rules from the start symbol downward. When they see a left-recursive rule, they get stuck in an infinite loop.
Tracing a Recursive Descent Parser on E → E + T | T:
The parser never even looks at the input — it just keeps calling itself forever.
The Rule
Top-down parsers cannot handle left-recursive grammars. Left recursion must be eliminated before using LL or recursive descent parsing.
Eliminating Direct Left Recursion
Direct left recursion is removed by converting it into right recursion using a helper non-terminal.
The General Pattern
Left-recursive grammar:
where:
A αare the left-recursive rules (A is the first symbol)βare the non-left-recursive rules (do not start with A)
Transformed grammar (no left recursion):
The new non-terminal A' (A-prime) captures the repeated trailing part. It recurses on the right, which is fine for top-down parsers.
Example 1 — Simple Expression Grammar
Original (left-recursive):
Identify:
- Left-recursive rule:
E + T(α =+ T) - Non-left-recursive rule:
T(β =T)
Transformed:
Verification — derive "T + T + T":
Same language — no left recursion.
Example 2 — Full Arithmetic Grammar
Original:
Transformed:
This is the classic LL(1)-ready form of arithmetic expressions.
Eliminating Indirect Left Recursion
Indirect left recursion is trickier. It requires a systematic algorithm that substitutes rules to reveal hidden direct left recursion, then eliminates it.
The Algorithm
Given: A grammar with non-terminals A₁, A₂, …, Aₙ in some fixed order.
The outer loop goes through each non-terminal in order. The inner loop substitutes earlier non-terminals to expose any hidden recursion.
Example — Indirect Left Recursion
Original grammar:
Order: S = A₁, A = A₂.
Step 1 — Process A₁ = S:
No Aⱼ with j < 1, so skip the inner loop. Check for direct left recursion in S: none.
Step 2 — Process A₂ = A:
Inner loop: j = 1, substitute A₁ = S.
A has production A → S b. Replace S with its productions:
So A's productions are now:
Now A has direct left recursion! Eliminate it:
Identify: Left-recursive: A a b (α = a b), Non-left-recursive: b b and d (β)
Final grammar (no left recursion):
Key Point
After eliminating indirect left recursion, the grammar generates the same language, but can now be parsed by a top-down parser without looping.
Left Recursion vs. Right Recursion
After eliminating left recursion, the grammar becomes right-recursive. It is worth understanding what this means for associativity.
Original Left-Recursive Grammar — Left-Associative
Parse tree for a + b + c:
Result: (a + b) + c — left-associative. The leftmost E subtree groups first, so addition folds from the left.
Transformed Right-Recursive Grammar
Parse tree for a + b + c:
When you evaluate this tree the standard way (left to right, collecting operators), you still get (a + b) + c — the same left-associative result.
The tree shape changes, but the semantic result is the same. The elimination is safe.