Ambiguity in Context-Free Grammars, Disambiguation Techniques, and Analysis of the Grammar
Ambiguous Grammars & Removing Ambiguity (lecture-style)
A context-free grammar (CFG) is called ambiguous when there exists at least one terminal string that can be produced in two distinct ways resulting in two different parse trees (equivalently, two different leftmost/rightmost derivations).2 Ambiguity is a syntactic property of the grammar, not of the language alone: a language may admit both ambiguous and unambiguous grammars (or be inherently ambiguous).2
Ambiguity becomes a practical problem in parsing/compilers because a parser would not have a unique syntactic structure to attach to the same input string, undermining deterministic meaning assignment from syntax trees.
Key terms:
- Ambiguous grammar
- Parse tree
- Leftmost derivation
- Unambiguous grammar
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩ ↩2 ↩3
-
Ambiguous Grammar (GeeksforGeeks overview) - https://www.geeksforgeeks.org/compiler-design/ambiguous-grammar - Defines ambiguity in terms of more than one parse tree/derivation for a string. ↩
-
Ambiguous grammar - Wikipedia - https://en.wikipedia.org/wiki/Ambiguous_grammar - Discusses ambiguity, recognition, and (inherently) ambiguous languages. ↩
Ambiguity can often be reduced or eliminated by redesigning the grammar (grammar transformation) so that the intended structure is forced by the rules. Typical approaches include:
- Refactoring to enforce structure, e.g., left-factoring (common in LL parsers).
- Eliminating left/right recursion (improves parser construction but does not always solve ambiguity by itself).
- Encoding precedence and associativity in the grammar (crucial for arithmetic-expression ambiguity).
- Using parser-generator precedence/associativity declarations (e.g., in YACC) which effectively resolves some shift/reduce conflicts.2
However, there is a strong theoretical limitation: the computational task “given a CFG, decide whether it is ambiguous” is undecidable in general. Likewise, the task of algorithmically finding an equivalent unambiguous CFG (when possible) is not solvable in general.
Key terms:
- Left factoring
- Operator precedence
- Associativity
- Undecidable problem
Footnotes
-
Ambiguous grammar - Wikipedia - https://en.wikipedia.org/wiki/Ambiguous_grammar - Discusses ambiguity, recognition, and (inherently) ambiguous languages. ↩
-
Context-Free Grammars lecture notes (UT Austin PDF) - https://www.cs.utexas.edu/~cline/ear/automata/CS341-Fall-2004-Packet/1-LectureNotes/ContextFree.pdf - Covers resolving ambiguity via precedence/associativity and grammar transformations. ↩
-
CS 373 lecture notes (Grainger/Illinois) on ambiguity decision/removal being undecidable - https://courses.grainger.illinois.edu/cs373/fa2010/lectures/lect20.pdf - States ambiguity decision is undecidable and discusses impossibility of general removal as an algorithmic task. ↩ ↩2
How to test (prove) a CFG is ambiguous
- 1Step 1
Pick a terminal string that you suspect can be derived in multiple ways.
- 2Step 2
Construct two different parse trees (or two distinct leftmost/rightmost derivations) for the same string.
- 3Step 3
Ensure the parse trees differ structurally (not just by redundant rearrangements).
- 4Step 4
If you find one string with two different parse trees, the grammar is ambiguous.
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩
-
Now consider the grammar (as written):
Interpreting “” as alternative productions, the CFG is:
We will decide whether it is ambiguous by checking whether some string has more than one parse tree.
Key insight: every production adds exactly one terminal symbol either on the left () or on the right (), and the base case produces exactly one ().
Key terms:
- Base case
- Sentential form
- Derivation length
Claim: The grammar is unambiguous
Let the target string be (i.e., copies of ). We show that it has a unique parse tree.
Structure forced by the first step
- If the derivation starts with , then one is fixed as the leftmost symbol of the final yield; the rest must come from deriving the remaining symbols via .
- If instead , then one is fixed as the rightmost symbol.
- Only can produce a string of length .
Uniqueness argument (for ): Consider the derivation tree’s root label . The tree has exactly one internal node labeled at each derivation depth until reaching the leaf created by .
For the yield to be exactly , at each internal node, you must choose whether that node contributes the next on the left or on the right. But because the entire string is homogeneous ( everywhere), different “left vs right” choices could appear to lead to the same terminal string.
We resolve this by observing that different sequences of left/right choices change the branching structure in the parse tree: the grammar’s productions are not symmetric through a single local rewrite—each internal node corresponds to a specific production occurrence ( or ). Those occurrences induce different tree shapes.
Concretely:
- For , the grammar can only derive by either:
- or These terminal strings are identical, so we check whether these produce different parse trees:
- First derivation tree: root uses ; the child then uses .
- Second derivation tree: root uses ; the child then uses .
These two parse trees are structurally different because the root production differs ( vs ), even though the final yield is the same terminal string .
Therefore, the grammar is ambiguous.
This directly matches the definition: if there exists a string with two different parse trees, the grammar is ambiguous.
Key terms:
- Ambiguity witness
- Production choice
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩
Explicit ambiguity witness for this grammar
We exhibit two different parse trees (equivalently, two distinct derivations) for the same string .
Derivation 1 (using at the root):
Derivation 2 (using at the root):
These correspond to different parse-tree structures at the root because the root production differs ( vs ). Hence the grammar is ambiguous.
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩
Pro Tip
To prove ambiguity, it’s enough to find one string (an ambiguity witness) with two different parse trees/derivations. You do not need to prove ambiguity for all strings.
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩
Warning: ambiguity vs. multiple derivations
Having two different derivations/parse trees for some string implies ambiguity, but “existence of derivations” alone isn’t enough—your derivations must be structurally distinct parse trees for the same terminal yield.2
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩
-
Ambiguous Grammar (GeeksforGeeks overview) - https://www.geeksforgeeks.org/compiler-design/ambiguous-grammar - Defines ambiguity in terms of more than one parse tree/derivation for a string. ↩
From definitions to a grammar decision
Definition
Step AAmbiguous iff some string has two different parse trees."
Footnotes
-
Parse Trees / Ambiguous Grammars (University of Rochester CSC 173 notes) - https://www.cs.rochester.edu/u/nelson/courses/csc_173/grammars/parsetrees.html - Defines ambiguous grammars via existence of two different parse trees for the same terminal string and uses this to prove ambiguity. ↩
Search for a witness
Step BTry short strings first (e.g., ) to find conflicting root productions."
Compare parse trees
Step CIf the root production differs and yields the same string, ambiguity holds."
Conclude
Step DIf witness exists, grammar is ambiguous; general ambiguity decision is undecidable."
Footnotes
-
CS 373 lecture notes (Grainger/Illinois) on ambiguity decision/removal being undecidable - https://courses.grainger.illinois.edu/cs373/fa2010/lectures/lect20.pdf - States ambiguity decision is undecidable and discusses impossibility of general removal as an algorithmic task. ↩
Ambiguity evidence for the grammar
For input , the grammar yields multiple distinct parse structures.
Disambiguation: can ambiguity always be removed?
Knowledge Check
A CFG is ambiguous if
Explore Related Topics
Functional-Dependency Analysis and Normalization of R(A, B, C, D, E, F)
Ambiguity in the Grammar \(S \rightarrow ABA,\; A \rightarrow aA \mid \epsilon,\; B \rightarrow bB \mid \epsilon\)
The grammar (S\rightarrow ABA,;A\rightarrow aA\mid\epsilon,;B\rightarrow bB\mid\epsilon) is ambiguous because the two (A) nonterminals can distribute the same (a)-string in multiple ways, especially when (B) derives (\epsilon).
- It generates the language (L(S)={a^i b^j a^k\mid i,j,k\ge0}=a^*b^a^).
- The shortest string (a) has two distinct left‑most derivations (or parse trees), proving ambiguity.
- Every string (a^n) with (n\ge1) can be split between the two (A) symbols in (n+1) ways, yielding multiple parse trees.
- The ambiguity stems from both (A) producing (a^*) and (B) being able to vanish via (\epsilon).
- An equivalent unambiguous grammar can be constructed, showing the ambiguity is a property of this grammar, not necessarily of the language.
Lexical Analysis and the Main Structure Used: Finite Automata
Lexical analysis relies on finite automata—typically deterministic finite automata (DFA)—to recognize token patterns defined by regular expressions.
- Regular expressions for identifiers, numbers, etc., are converted to NFAs then to a DFA for fast scanning.
- The DFA processes the source character by character, tracking a single current state and emitting a token at each accepting state.
- Queues, stacks, and trees support other compiler phases (parsing, AST construction) but are not the primary model for token recognition.
- Lexers output a stream of tokens that the parser consumes for syntax analysis.