Derivations and Parse Trees

Consider a compiler reading the expression `2 + 3 4`. It must decide whether multiplication happens before addition. The grammar alone lists rules. It does not say how to apply them, or what shape the final answer takes. Derivations answer the "how," step by step. Parse trees answer the "what shape." They show the hierarchical structure hidden inside a flat string of symbols. Together they turn an abstract <a class="wiki-link" href="/wiki/cs-theory-context-free-grammars" data-track="wiki_article.body.wiki_link">context-free grammar</a> into a concrete recipe. That recipe generates, recognizes, and structurally interprets strings. This distinction matters enormously in real systems. A compiler's parser does not merely check that source code is syntactically valid. It builds a parse tree, or a lighter abstract syntax tree derived from it. Downstream stages walk this tree to generate machine code, perform type checking, or optimize expressions. Two different derivations of the same string can correspond to the same tree. They then differ only in the order rules were applied. Or they can correspond to genuinely different trees. This exposes a structural ambiguity the language designer must resolve. Understanding when derivations coincide and when they diverge is key. It is the conceptual bridge to ambiguity, one of the central concerns in language and grammar design. The big picture is this: a context-free grammar generates a language. It does so by permitting sequences of substitutions. These start from a special start symbol. Nonterminals are then repeatedly replaced using production rules, until only terminal symbols remain. Any such sequence is a <strong>derivation</strong>. A <strong>parse tree</strong> is a picture of one particular kind of derivation. It is an order-independent snapshot of which substitutions were made and how they nest. It is stripped of the arbitrary bookkeeping of when* each one happened. This article makes the mechanics precise. It covers what a derivation step is. It explains how leftmost and rightmost derivations canonically order the substitution choices. It shows how to build the parse tree that corresponds to a derivation. It explains why every parse tree corresponds to infinitely many equivalent derivations. Yet every leftmost (or rightmost) derivation corresponds to exactly one tree. This correspondence is the load-bearing fact used later to define and detect ambiguity. It also sets up the motivation for normal forms like Chomsky Normal Form. These make parse trees easier to analyze algorithmically.

Key takeaways
  • A derivation is a sequence of substitution steps transforming the start symbol into a string, using the grammar's rules one at a time.
  • A leftmost derivation always expands the leftmost remaining nonterminal; a rightmost derivation always expands the rightmost one.
  • A parse tree is a rooted, ordered tree whose internal nodes are nonterminals (labeled by rule left-hand sides) and whose leaves, read left to right, spell the derived string.
  • Every parse tree corresponds to exactly one leftmost derivation and exactly one rightmost derivation, even though many interleaved derivations can share the same tree.
  • If a string has two different parse trees under the same grammar, the grammar is ambiguous for that string — the key idea that motivates the next stage of study.
  • Building parse trees mechanically (top-down or bottom-up) is the algorithmic core of parsing in compilers and other language-processing tools.
The core insight

A derivation records the order of rule applications; a parse tree records only their nesting — and leftmost derivations are the canonical bridge that recovers one from the other uniquely.

The idea

A context-free grammar G=(V,Σ,R,S)G = (V, \Sigma, R, S) consists of nonterminals VV, terminals Σ\Sigma, production rules RR, and a start symbol SS. A derivation step rewrites a single occurrence of a nonterminal AA appearing in some string αAβ\alpha A \beta (where α,β\alpha, \beta are strings of terminals and nonterminals) into γ\gamma, provided A→γA \to \gamma is a rule in RR. We write

αAβ⇒αγβ\alpha A \beta \Rightarrow \alpha \gamma \beta

to denote one derivation step. A derivation is a chain of such steps,

S=σ0⇒σ1⇒σ2⇒⋯⇒σn=w,S = \sigma_0 \Rightarrow \sigma_1 \Rightarrow \sigma_2 \Rightarrow \cdots \Rightarrow \sigma_n = w,

written compactly as S⇒∗wS \Rightarrow^{*} w, showing that the string ww is generated by GG. Crucially, at each intermediate string σi\sigma_i there is usually more than one nonterminal present, and the grammar's rules say nothing about which one must be expanded next — that choice is a bookkeeping decision made by whoever performs the derivation, not a property of the grammar itself. This ambiguity of order (not to be confused with ambiguity of the grammar) motivates fixing a canonical strategy. In a leftmost derivation, every step expands the leftmost nonterminal symbol still present in the current string. In a rightmost derivation, every step expands the rightmost nonterminal. These are conventions for producing a unique, deterministic sequence of steps that generates a given string, out of all the equivalent unordered derivations that differ only in which nonterminal was chosen first. Top-down parsers (like recursive descent) naturally construct leftmost derivations; bottom-up parsers (like LR parsers) naturally construct the reverse of rightmost derivations. A parse tree (also called a derivation tree) for a grammar GG is a rooted, ordered tree satisfying three conditions: the root is labeled SS; every internal node is labeled by some nonterminal AA, and its children, read left to right, spell exactly the right-hand side of some rule A→X1X2⋯XkA \to X_1 X_2 \cdots X_k (with a single child labeled ε\varepsilon if the rule is A→εA \to \varepsilon); and every leaf is labeled by a terminal symbol or ε\varepsilon. The yield of the tree — its leaves read left to right — is the string generated. The tree captures only the hierarchical grouping of substitutions, discarding the temporal order in which they were performed. This is exactly why many different derivations, differing only in the interleaving of independent expansions, collapse onto the same single tree.

How it works

Building a parse tree from a grammar and a target string is the essence of parsing. Two dual algorithmic strategies correspond to leftmost and rightmost derivations respectively.

Top-down construction (leftmost derivation). Start with a single root node labeled SS. Repeatedly find the leftmost nonterminal leaf in the tree built so far, choose a rule for it, and attach children spelling that rule's right-hand side. Continue until every leaf is a terminal (or ε\varepsilon) and the yield matches the target string.

Bottom-up construction (reverse rightmost derivation). Start with the target string as a forest of terminal leaves. Repeatedly find a substring matching some rule's right-hand side, replace it with a new internal node labeled by that rule's left-hand side, and continue until only the root SS remains. Read the sequence of reductions backward to recover the rightmost derivation. Below is pseudocode for generating a leftmost derivation and simultaneously constructing its parse tree, given a grammar and (via nondeterministic choice, as in a search procedure) a target string. This models what a nondeterministic top-down parser conceptually does; deterministic parsers add lookahead and restrictions to make the rule choice computable without backtracking. ``` function LEFTMOST-DERIVE(G, target):

# G = (V, Sigma, R, S). Returns a parse tree with yield == target,

# or FAIL if no leftmost derivation of target exists. root = new TreeNode(label = S, children = []) frontier = [root] # ordered list of tree leaves, left to right derivation = [] # sequence of (nonterminal, rule) pairs function YIELD(frontier): return concatenate(node.label for node in frontier if node.isTerminalOrEpsilon) function EXPAND(frontier, target):

# find leftmost nonterminal leaf i = index of first node in frontier where node.isNonterminal if i does not exist: return (YIELD(frontier) == target) ? SUCCESS : FAIL A = frontier[i].label for each rule (A -> X1 X2 ... Xk) in R: # nondeterministic choice newChildren = [TreeNode(Xj) for Xj in X1..Xk] # or single epsilon-node if k==0 attach newChildren as children of frontier[i] newFrontier = frontier[0:i] + newChildren + frontier[i+1:] partialYield = concatenate terminal labels in newFrontier up to next nonterminal if partialYield is not a prefix of target so far: undo attachment continue # prune: this choice cannot lead to target derivation.append((A, rule)) result = EXPAND(newFrontier, target) if result == SUCCESS: return SUCCESS derivation.pop() undo attachment # backtrack return FAIL if EXPAND(frontier, target) == SUCCESS: return (root, derivation) else: return FAIL ``` The rightmost analogue is identical except that `EXPAND` always selects the last nonterminal leaf in `frontier` rather than the first, and the resulting derivation, read in the order rules are applied, is the rightmost derivation of `target`. The figure below shows the parse tree for the arithmetic string `2+3*4` under a grammar with rules E→E+E∣E∗E∣numE \to E + E \mid E * E \mid \text{num}, alongside the two canonical derivations it corresponds to.

Figure
Parse tree for 2+3*4, with leftmost and rightmost derivation orders annotated
E E + E 2 E * E 3 4 Yield (left to right): 2 + 3 * 4 This one tree ↔ one leftmost derivation ↔ one rightmost derivation

For this tree, the leftmost derivation always expands the leftmost `E`:

E⇒E+E⇒num+E⇒num+E∗E⇒num+num∗E⇒num+num∗numE \Rightarrow E{+}E \Rightarrow \text{num}{+}E \Rightarrow \text{num}{+}E{*}E \Rightarrow \text{num}{+}\text{num}{*}E \Rightarrow \text{num}{+}\text{num}{*}\text{num}

and the rightmost derivation always expands the rightmost `E`:

E⇒E+E⇒E+E∗E⇒E+E∗num⇒E+num∗num⇒num+num∗numE \Rightarrow E{+}E \Rightarrow E{+}E{*}E \Rightarrow E{+}E{*}\text{num} \Rightarrow E{+}\text{num}{*}\text{num} \Rightarrow \text{num}{+}\text{num}{*}\text{num}

Both derivations produce the exact same tree shown above — they differ only in which order the two `E` children of the root were expanded, not in the final nesting structure.

Complexity & correctness

Time and space for tree construction. For a fixed grammar GG with ∣R∣|R| rules, each of bounded right-hand-side length, generating a leftmost derivation top-down with unbounded backtracking (as in the pseudocode above) is exponential in the worst case: at each of the O(n)O(n) expansion steps for a target string of length nn, up to ∣R∣|R| rule choices must be tried, giving a search tree of size O(∣R∣n)O(|R|^n) in the naive case. This is why real parsers restrict attention to grammar subclasses (LL(1), LR(1), etc.) or use dynamic-programming parsers like CYK, which run in O(n3)O(n^3) time and O(n2)O(n^2) space for arbitrary context-free grammars by building parse trees bottom-up over all substrings, avoiding redundant recomputation. The CYK approach itself relies on rules being in Chomsky Normal Form, a normal form specifically designed to make this dynamic program clean — foreshadowing why that normal form exists at all. Independent of parsing strategy, once a specific derivation (leftmost or rightmost) of length nn steps is given, constructing its parse tree takes O(n)O(n) time and O(n)O(n) space: each step attaches O(1)O(1) amortized new nodes (bounded by the maximum rule length), and the total number of nodes in the tree is linear in the number of derivation steps plus the string length.

Correctness argument — the leftmost/tree bijection. The central fact to justify is: > For any context-free grammar GG and string w∈L(G)w \in L(G), there is a bijection between parse trees for ww and leftmost derivations of ww (and, separately, a bijection between parse trees for ww and rightmost derivations of ww). Tree → leftmost derivation. Given a parse tree TT, produce a leftmost derivation by induction on tree size. If TT is a single terminal leaf, the derivation is empty (or the trivial one-step case A⇒aA \Rightarrow a). Otherwise let the root be AA with rule A→X1⋯XkA \to X_1 \cdots X_k and subtrees T1,…,TkT_1, \ldots, T_k rooted at X1,…,XkX_1, \ldots, X_k. Emit the step A⇒X1X2⋯XkA \Rightarrow X_1 X_2 \cdots X_k, then recursively emit the leftmost derivation of T1T_1's yield (this expands all nonterminals inside T1T_1 before touching X2,…,XkX_2, \ldots, X_k, since T1T_1's internal nonterminals are, by construction, always the leftmost pending nonterminal until T1T_1 is fully expanded), then of T2T_2's yield, and so on. This produces one well-defined derivation and it is easily checked to always expand the current leftmost nonterminal, by induction on the recursive structure. Leftmost derivation → tree. Conversely, given a leftmost derivation, build the tree exactly as the top-down pseudocode does: each step αAβ⇒αγβ\alpha A \beta \Rightarrow \alpha \gamma \beta (with AA leftmost) attaches γ\gamma's symbols as children of the tree node currently representing that occurrence of AA. Because the derivation always targets the unique leftmost pending nonterminal, there is never an ambiguity about which tree node receives the new children — the construction is forced at every step, giving a well-defined tree. These two maps are mutually inverse. Running tree → derivation → tree recovers the original tree exactly, because the induction above visits subtrees in the same left-to-right order that the reconstruction consumes derivation steps; running derivation → tree → derivation recovers the original derivation exactly, because at every point the "leftmost pending nonterminal" in the partially built tree is uniquely determined by the tree's shape so far, matching the induction's recursive order. Formally this is proved by induction on the number of derivation steps, showing the invariant: after ii steps of a leftmost derivation, the frontier of the corresponding partially-built tree, read left to right, equals the current sentential form σi\sigma_i. This invariant holds trivially at i=0i = 0 (frontier is just the root SS), and is preserved at each step because expanding the leftmost nonterminal leaf in the tree corresponds exactly to rewriting the leftmost nonterminal occurrence in the string. The same argument, mirrored, gives the rightmost bijection.

Why unordered derivations do not give a bijection. A general (non-canonical) derivation need not expand nonterminals in any consistent left-to-right or right-to-left order — two independent nonterminals AA and BB present simultaneously in a sentential form can each be expanded first, giving two different derivations that nevertheless produce the identical tree (they only reorder when independent subtrees are grown, not how they nest). This is precisely why leftmost and rightmost derivations are singled out as canonical: they are the two derivation orders that break all remaining freedom by fixing a deterministic scan direction, collapsing the many equivalent unordered derivations of a tree down to exactly one representative each.

The honest tradeoff. Parse trees are the "right" object to reason about structure (operator precedence, scope nesting, semantic meaning), but they are more expensive to store and manipulate than a bare derivation string or a compressed abstract syntax tree. Compilers typically build a full parse tree (or an equivalent internal structure) only implicitly, collapsing it immediately into a leaner abstract syntax tree that omits redundant unit-production nodes, trading some traceability back to the exact grammar rules used for a smaller memory footprint and faster downstream traversal.

Worked example

Take the classic (deliberately ambiguity-prone) grammar for simple arithmetic:

E→E+E∣E×E∣(E)∣idE \to E + E \mid E \times E \mid (E) \mid \text{id}

and derive the string `id + id × id`, tracing a leftmost derivation, its rightmost counterpart, and the resulting tree — using the derivation choice that groups `+` at the top (i.e., reading the string as `id + (id × id)`).

StepLeftmost derivation (expand leftmost EE)Rightmost derivation (expand rightmost EE)
0EEEE
1E+EE + EE+EE + E
2id+E\text{id} + EE+E×EE + E \times E
3id+E×E\text{id} + E \times EE+E×idE + E \times \text{id}
4id+id×E\text{id} + \text{id} \times EE+id×idE + \text{id} \times \text{id}
5id+id×id\text{id} + \text{id} \times \text{id}id+id×id\text{id} + \text{id} \times \text{id}

Both sequences are 5 steps long and use exactly the same multiset of rules — one application of E→E+EE \to E+E, one of E→E×EE \to E \times E, and three of E→idE \to \text{id} — but applied in reverse relative order, since leftmost sweeps outer-to-inner-left while rightmost sweeps outer-to-inner-right. Both correspond to the single tree: ``` E / | \ E + E | /|\ id E × E | | id id ``` Now check the bijection claim concretely. Reading the tree top-down, left to right, the induction described above emits: root rule E→E+EE \to E+E first (step 1 above); then recurse into the left child, which is a leaf `id`, contributing nothing further to the derivation steps beyond having already appeared; then recurse into the right child EE, whose rule is E→E×EE \to E \times E (step 2's target, but note it appears as step 3 in the table because the leftmost `id` at position 1 must first be finalized) — this exactly reconstructs the leftmost derivation column. Running the same tree through the rightmost-recovery procedure (recursing right-to-left, applying the mirrored invariant) reconstructs the rightmost derivation column. Since both procedures are deterministic functions of the tree alone, this single tree provably yields exactly one leftmost and exactly one rightmost derivation — no other ordering of these same three rule applications is either leftmost or rightmost, even though several such orderings exist and all describe the same tree. Contrast this with genuine ambiguity: the same string `id + id × id` also has a second, different parse tree grouping as `(id + id) × id`: ``` E / | \ E × E / | \ | E + E id | | id id ``` This tree has a different shape (root rule is E→E×EE \to E \times E, not E→E+EE \to E+E), hence a genuinely different leftmost derivation: E⇒E×E⇒E+E×E⇒id+E×E⇒id+id×E⇒id+id×idE \Rightarrow E \times E \Rightarrow E{+}E \times E \Rightarrow \text{id}+E \times E \Rightarrow \text{id}+\text{id} \times E \Rightarrow \text{id}+\text{id}\times \text{id}. Because two structurally distinct trees both yield the same final string under this grammar, the grammar is ambiguous for this input — the precise phenomenon that the concept of Ambiguity in Context-Free Grammars formalizes and studies.

Common pitfalls & traps

PitfallWhy it happensFix
Confusing "different derivation" with "different tree"Two derivations can interleave independent expansions in different orders yet build the identical treeAlways compare parse trees, not raw derivation step sequences, when checking whether a string is genuinely ambiguous
Forgetting the ε\varepsilon-production case in a treeA rule A→εA \to \varepsilon still needs a child node (labeled ε\varepsilon) or the yield computation silently miscountsRepresent ε\varepsilon explicitly as a leaf, or define yield to skip it consistently everywhere
Assuming leftmost and rightmost derivations of a string are always differentFor strings with only one nonterminal expanded at a time (no two pending nonterminals simultaneously), leftmost and rightmost derivations can coincide step-for-stepCheck the sentential forms directly rather than assuming asymmetry
Treating parse trees and abstract syntax trees as the same objectParse trees include every grammar rule application, including unit productions like E→(E)E \to (E); ASTs collapse these awayBe explicit about which structure a given diagram or algorithm is building
Using unrestricted backtracking search to "parse" and calling it efficientThe naive top-down search shown for leftmost derivations is exponential in the worst case for ambiguous or highly branching grammarsUse CYK (O(n3)O(n^3), needs Chomsky Normal Form) or a restricted deterministic grammar class (LL/LR) for polynomial parsing

Pioneers & history

The formal machinery of derivations and parse trees emerged from the mid-20th-century convergence of linguistics and computer science, as researchers sought precise mathematical models for how sentences — in natural language and later in programming languages — could be systematically generated and structurally analyzed.

Origins · 1 minNoam Chomsky and how this was discovered
NC
Noam Chomsky
born 1928 · Linguist and cognitive scientist at MIT whose 1956 formalization of phrase-structure grammars gave derivations and parse trees their rigorous mathematical footing, directly inspiring the Chomsky hierarchy of formal languages

History
1956
— Noam Chomsky formalizes phrase-structure grammars, introducing rule-based generative derivations for natural language syntax.
1959
— John Backus and Peter Naur independently develop BNF notation to specify programming language grammars, making derivations and parse trees practical engineering tools.
1965
— Donald Knuth formalizes LR parsing, showing how rightmost derivations (read in reverse) can be recovered deterministically and efficiently from a string.
1968
— Ambiguity and parsing complexity become central research topics as compiler construction matures into a rigorous engineering discipline.
1970
s — Parser generator tools such as Yacc operationalize context-free grammars, automatically deriving parse-tree-building code from rule specifications.

Where this matters

Every modern compiler and interpreter — for C, Python, JavaScript, SQL, or any structured configuration language — relies on parsing a token stream into a parse tree (or a closely related abstract syntax tree) before any semantic analysis or code generation can proceed. Parser generators such as Yacc, Bison, ANTLR, and the Earley- or LR-based engines inside modern language toolchains all implement, at their core, the leftmost- or rightmost-derivation logic described here, differing mainly in how much lookahead and backtracking they permit before committing to a rule choice. Beyond programming languages, XML and JSON schema validators, natural language parsers used in computational linguistics, and even query optimizers for SQL that need to understand the structure of a query all build and manipulate parse-tree-like structures derived from an underlying context-free (or context-free-adjacent) grammar. The leftmost/rightmost canonical-derivation framework is also the conceptual foundation for understanding why certain grammars admit efficient, deterministic parsing (LL and LR grammars) while others require exponential search or restriction to normal forms — a distinction that directly determines which grammar classes are practical for building real-world language tools.

Ask the tutor: Can you show why an ambiguous grammar can sometimes be rewritten into an equivalent unambiguous grammar, and when that's impossible?

What exactly is a "derivation step" versus a full "derivation"?

A derivation step is a single application of one production rule: replacing one occurrence of a nonterminal in a string with the right-hand side of a matching rule, written αAβ⇒αγβ\alpha A \beta \Rightarrow \alpha \gamma \beta. A full derivation is a finite chain of such steps starting from the grammar's start symbol SS and ending at a string made entirely of terminals, written S⇒∗wS \Rightarrow^{*} w. The step is the atomic unit of rewriting; the derivation is the complete generative history showing how ww was produced. A grammar generates a language precisely by allowing all strings reachable via some derivation from SS, so derivations are the formal witness that a string belongs to the language.

Why do we bother defining leftmost and rightmost derivations specifically, rather than just any derivation order?

Any valid rewriting order proves a string is generated by the grammar, but unordered derivations are not unique — many different orderings can produce the same parse tree, making it impossible to compare derivations directly to test ambiguity. Fixing a canonical scan direction (always leftmost, or always rightmost) removes this redundancy: it is a theorem that each parse tree corresponds to exactly one leftmost derivation and exactly one rightmost derivation. This turns "does this string have two different trees" into the cleanly checkable question "does this string have two different leftmost derivations," which is the operational definition of ambiguity used throughout formal language theory.

Can a string have a leftmost derivation but no corresponding rightmost derivation, or vice versa?

No — if a string ww is generated by a grammar GG at all, meaning some parse tree exists with yield ww, then that same tree yields both a leftmost derivation and a rightmost derivation of ww, by the two symmetric constructions described in the correctness argument. The two derivations may look very different as sequences of sentential forms, since they process the tree's subtrees in opposite left-to-right order, but they always exist together, in pairs, one per tree. Their number is therefore identical — the count of leftmost derivations for ww always equals the count of rightmost derivations for ww, equal to the number of distinct parse trees.

How do parse trees relate to abstract syntax trees used in real compilers?

An abstract syntax tree (AST) is a simplified version of a parse tree that omits grammar bookkeeping irrelevant to meaning, such as nodes for punctuation tokens, parenthesization rules, or unit productions like E→(E)E \to (E) that add a layer without adding information. A parse tree faithfully mirrors every grammar rule applied, including these redundant layers, which makes it directly connected to the grammar's derivation but bulkier to store and traverse. Compilers typically construct (at least conceptually) a parse tree during parsing, then immediately simplify it into an AST for semantic analysis, type checking, and code generation, trading strict rule-by-rule fidelity for a leaner, more semantically direct structure.

Does every context-free grammar admit a leftmost derivation for every string in its language?

Yes. If w∈L(G)w \in L(G), some derivation S⇒∗wS \Rightarrow^{*} w exists by definition of language membership, and hence at least one parse tree with yield ww exists. The tree-to-leftmost-derivation construction described in the correctness argument applies to any valid parse tree, deterministically producing a leftmost derivation from it. So the existence of a leftmost derivation is guaranteed whenever the string is in the language; what is not guaranteed is uniqueness — an ambiguous grammar may admit multiple distinct leftmost derivations (one per distinct tree) for the same string.

What is the practical cost of actually building a parse tree during parsing?

Given a fixed derivation of length nn (number of rule applications), constructing the corresponding parse tree takes O(n)O(n) time and O(n)O(n) space, since each step adds a bounded number of new nodes. The expensive part is not tree construction itself but finding a valid derivation in the first place: naive backtracking search can be exponential, while general dynamic-programming parsers like CYK guarantee O(n3)O(n^3) time and O(n2)O(n^2) space for any context-free grammar (after conversion to Chomsky Normal Form), and restricted deterministic grammars (LL(1), LR(1)) achieve linear O(n)O(n) parsing time by design, at the cost of restricting which context-free languages they can express without grammar transformation.

How does this connect to detecting ambiguity in a context-free grammar?

A grammar is defined as ambiguous for a string ww exactly when ww has two or more distinct parse trees, which by the bijection is equivalent to ww having two or more distinct leftmost derivations (or, equivalently, two or more distinct rightmost derivations). This gives a concrete, checkable criterion: to prove ambiguity, exhibit two different leftmost derivations of the same string and show they build different-shaped trees, as done in the worked example with `id + id × id`. This is precisely the tool used to formally establish Ambiguity in Context-Free Grammars, one immediate and important consequence of the derivation/tree correspondence developed here.

Before this

Where this leads