Left factoring in Compiler Design - Time & Space Complexity
Left factoring is a technique used in compiler design to rewrite grammar rules for easier parsing.
We want to understand how the time to apply left factoring grows as the grammar size increases.
Analyze the time complexity of the following left factoring process.
for each non-terminal N in grammar:
find common prefixes among N's productions
if common prefix found:
create new non-terminal N_prime
rewrite productions factoring out prefix
This code finds common beginnings in grammar rules and rewrites them to remove ambiguity.
Look for repeated checks and rewrites in the grammar.
- Primary operation: Comparing productions to find common prefixes.
- How many times: For each non-terminal, all pairs of its productions are compared.
As the number of productions grows, the comparisons increase quickly.
| Input Size (n productions) | Approx. Operations |
|---|---|
| 10 | About 45 comparisons |
| 100 | About 4,950 comparisons |
| 1000 | About 499,500 comparisons |
Pattern observation: The number of comparisons grows roughly with the square of the number of productions.
Time Complexity: O(n^2)
This means the time to left factor grows quickly as the number of productions increases, roughly by the square of that number.
[X] Wrong: "Left factoring takes linear time because it just scans each production once."
[OK] Correct: Actually, it compares pairs of productions to find common prefixes, which leads to many more checks than just scanning once.
Understanding how left factoring scales helps you explain parser design choices clearly and shows your grasp of grammar processing.
"What if the grammar had a fixed maximum number of productions per non-terminal? How would that affect the time complexity?"
Practice
left factoring in compiler design?Solution
Step 1: Understand left factoring concept
Left factoring is used to remove common prefixes from grammar rules to make parsing decisions easier.Step 2: Differentiate from other grammar techniques
Unlike eliminating left recursion or code optimization, left factoring focuses on simplifying grammar by factoring out common starts.Final Answer:
To remove common prefixes from grammar rules to simplify parsing -> Option AQuick Check:
Left factoring = remove common prefixes [OK]
- Confusing left factoring with left recursion elimination
- Thinking it optimizes runtime code
- Assuming it generates machine code
A -> a b | a c?Solution
Step 1: Identify common prefix in rules
Both alternatives start with 'a', so 'a' is the common prefix.Step 2: Factor out the common prefix
Rewrite asA -> a (b | c)to factor out 'a'.Final Answer:
A -> a (b | c) -> Option DQuick Check:
Common prefix 'a' factored out [OK]
- Not factoring out the common prefix 'a'
- Combining alternatives incorrectly
- Removing essential parts of the rule
S -> if E then S else S | if E then SWhat is the left factored form?
Solution
Step 1: Identify common prefix in alternatives
Both alternatives start withif E then S.Step 2: Factor out the common prefix
Rewrite asS -> if E then S (else S | ε), where ε means empty (no else).Final Answer:
S -> if E then S (else S | ε) -> Option AQuick Check:
Common prefix factored with optional else [OK]
- Not factoring out the entire common prefix
- Misplacing parentheses
- Ignoring the optional else part
Original: A -> a b | a c d
Attempted: A -> a (b | c d)Solution
Step 1: Analyze the original and attempted factoring
Original rules share common prefix 'a'. Alternatives are 'b' and 'c d'.Step 2: Verify correctness
The attemptA -> a (b | c d)is correct: it generatesa banda c d. Sequences like 'c d' are valid in alternatives.Final Answer:
Correct left factoring, no error -> Option BQuick Check:
Same language generated [OK]
- Confusing left factoring with left recursion elimination
- Thinking it optimizes runtime code
- Assuming it generates machine code
Expr -> Expr + Term | Expr - Term | TermApply left factoring to this grammar.
Solution
Step 1: Identify left recursion and common prefix
The rule is left recursive:Expr -> Expr + Term | Expr - Term | Term.Step 2: Remove left recursion and apply left factoring
Rewrite as:Expr -> Term Expr'Expr' -> (+ | -) Term Expr' | εto factor out common prefix and remove recursion.Final Answer:
Expr -> Term Expr'; Expr' -> (+ | -) Term Expr' | ε -> Option CQuick Check:
Left recursion removed and common prefix factored [OK]
- Not removing left recursion before factoring
- Incorrectly grouping alternatives
- Ignoring the ε (empty) option
Ready to prove it?
Pass the test and this pattern moves unknown
