Skip to main content

7.1 Context-Free Grammars: Parse Trees, Leftmost & Rightmost Derivations

📚Module 01Topic 1.1⏱️18 min read
🎯High-Yield For:Semester Exams • GATE CSE • Technical Interviews

💡 Core Intuition: The Sentence Blueprint & Branching Tree​

In natural language and programming languages alike, sentences are not merely linear streams of beads on a string; they possess deep nested, hierarchical structure.

Regular expressions and finite automata can count modulo a number or verify sequential prefixes, but they are powerless when syntactic structures must nest indefinitely—such as matching parentheses (( ( ) )), matching HTML tags <div><span></span></div>, or evaluating mathematical expressions with operator precedence like (3 + (4 * 5)).

To capture this recursive hierarchy, linguist Noam Chomsky introduced Context-Free Grammars (Type-2). A grammar is called context-free because any syntactic variable (non-terminal) on the left-hand side of a rule can be replaced by its right-hand expansion regardless of what symbols surround it (independent of its linguistic context).

🍳 The Everyday Analogy: The Russian Matryoshka Nesting Doll​

Consider a Russian nesting doll (Matryoshka):

  • You open the outer doll labeled Doll. Inside, you find another Doll and a small wooden Toy.
  • You can write this rule as:

Doll⟶ToyDollToy∣ϵ\text{Doll} \longrightarrow \text{Toy} \quad \text{Doll} \quad \text{Toy} \quad \mid \quad \epsilon

  • If you repeat this replacement three times and terminate with ϵ\epsilon, you get three layers of matching toys: Toy Toy Toy followed by Toy Toy Toy.
  • You do not need to inspect what is outside the doll to open the next layer. The rule applies purely from the inside out.

When you draw the parent-child relationships of how each doll revealed smaller dolls, you obtain a branching tree. The root is the largest doll, the internal branches are intermediate open dolls, and the leaves on the table are the physical toys.

💻 Bridging to Computer Science​

In computer science, a Context-Free Grammar (CFG) serves as the formal architectural blueprint for programming language parsers (such as GCC, Clang, V8, and Python's AST parser):

  • Lexical Tokens (Terminals TT): Identifiers, numbers, keywords (if, while), and operators (+, *).
  • Syntactic Categories (Variables / Non-Terminals VV): Expressions, statements, blocks, function declarations.
  • Production Rules (PP): Rewrite specifications that define valid syntactic expansion.

Every valid program is derived through a sequential rewrite process called a derivation:

  • Expanding the leftmost variable at every step produces a Leftmost Derivation (LMD) (the foundation of top-down parsers like recursive descent and LL parsers).
  • Expanding the rightmost variable at every step produces a Rightmost Derivation (RMD) (the reverse of bottom-up shift-reduce parsers like LR, LALR, and Yacc/Bison).
  • The visual geometric representation of this derivation is the Parse Tree (Concrete Syntax Tree), where the left-to-right sequence of leaves forms the final source code string (the yield of the tree).


🧱 The Formal Definition of a Context-Free Grammar​

A Context-Free Grammar is formally defined as a 4-tuple:

G=(V,T,P,S)G = (V, T, P, S)

The 4 Components of a Context-Free Grammar

Mathematical anatomy of the Type-2 phrase-structure grammar tuple

🔠

Variables / Non-Terminals (V)

Syntactic Categories
  • A finite set of placeholder symbols representing abstract syntactic structures.
  • Variables can be expanded into other variables and terminals.
  • Commonly denoted by uppercase letters: S, A, B, C, E, T, F.
🔡

Terminals (T)

Alphabet Symbols
  • A finite set of atomic, immutable symbols that form the actual language strings.
  • Terminals cannot be replaced or expanded further.
  • Commonly denoted by lowercase letters (a, b, c), digits (0, 1), and punctuation.
📜

Production Rules (P)

Rewrite Mappings
  • A finite set of rewriting rules of the strict form: A → α.
  • LHS must consist of a SINGLE non-terminal: A ∈ V.
  • RHS is any finite string of variables and terminals: α ∈ (V ∪ T)*.
🏁

Start Symbol (S)

Root Variable
  • A distinguished non-terminal symbol from V: S ∈ V.
  • All derivations in the language begin from this single starting point.
  • Represents the entire program, document, or sentence.

The Defining Constraint of Type-2 Grammars​

What separates a Context-Free Grammar from a Type-1 (Context-Sensitive) or Type-0 (Unrestricted) grammar is the strict structural constraint on the Left-Hand Side (LHS) of every production:

A⏟Strictly ONE variable ∈V⟶α⏟Any string ∈(V∪T)∗\underbrace{A}_{\text{Strictly ONE variable } \in V} \longrightarrow \underbrace{\alpha}_{\text{Any string } \in (V \cup T)^*}

  • In a Type-1 Grammar, a production has the form αAβ→αγβ\alpha A \beta \to \alpha \gamma \beta, where variable AA can only be replaced when flanked by context strings α\alpha and β\beta.
  • In a Type-2 CFG, there are no context strings on the LHS. Variable AA stands alone. Whether AA appears at the start of a line, inside a loop, or deeply nested in an expression, it can freely rewrite to α\alpha.

🔀 Derivations & Sentential Forms​

A derivation is a step-by-step sequence of production replacements that starts at the start symbol SS and terminates in a string composed entirely of terminals.

The Single-Step Yield Relation (⇒)​

Let αAβ\alpha A \beta be a string in (V∪T)∗(V \cup T)^*, where A∈VA \in V. If there exists a production rule A→γ∈PA \to \gamma \in P, then we say that αAβ\alpha A \beta directly derives (or yields) αγβ\alpha \gamma \beta:

αAβ⟹αγβ\alpha A \beta \Longrightarrow \alpha \gamma \beta

Transitive Closure (⇒*)​

  • If α1⇒α2⇒⋯⇒αm\alpha_1 \Rightarrow \alpha_2 \Rightarrow \cdots \Rightarrow \alpha_m, we say that α1\alpha_1 derives αm\alpha_m in zero or more steps, denoted:

α1⟹∗αm\alpha_1 \Longrightarrow^* \alpha_m

Sentential Forms vs. Sentences​

  • Sentential Form: Any string α∈(V∪T)∗\alpha \in (V \cup T)^* such that S⇒∗αS \Rightarrow^* \alpha. A sentential form may contain both non-terminals and terminals.
  • Sentence: A sentential form containing only terminal symbols: w∈T∗w \in T^* such that S⇒∗wS \Rightarrow^* w.
  • Language of a Grammar L(G)L(G): The complete set of all sentences derivable from SS:

L(G)={w∈T∗∣S⟹∗w}L(G) = \{w \in T^* \mid S \Longrightarrow^* w\}

A language LL is called a Context-Free Language (CFL) if there exists at least one Context-Free Grammar GG such that L=L(G)L = L(G).


🌲 Leftmost vs. Rightmost Derivations​

When a sentential form contains two or more non-terminals, the order in which we choose to expand them determines the derivation path. Two canonical derivation strategies dominate formal language theory and compiler design:

Derivation Duality: Leftmost vs Rightmost

Contrasting the expansion strategies that govern top-down and bottom-up parsing architectures

Top-Down Strategy

Leftmost Derivation (LMD)

👈
Dominant Architecture / DomainPredictive & LL Parsers
  • •At every single derivation step, the LEFTMOST non-terminal is chosen for replacement.
  • •Generates terminal prefixes from left to right as the derivation progresses.
  • •Denoted mathematically by: α ⇒_lm β.
  • •Directly mirrors the execution trace of recursive-descent and LL(k) compilers.
"Always expand the variable closest to the front of the input stream."
Bottom-Up Strategy

Rightmost Derivation (RMD)

👉
Dominant Architecture / DomainShift-Reduce & LR Parsers
  • •At every single derivation step, the RIGHTMOST non-terminal is chosen for replacement.
  • •Generates terminal suffixes from right to left as the derivation progresses.
  • •Denoted mathematically by: α ⇒_rm β. Also called the Canonical Derivation.
  • •The reverse of an RMD forms the exact shift-reduce sequence executed by LR(k) and LALR parsers.
"Always expand the variable closest to the end of the input stream."

Concrete Walkthrough: Arithmetic Expressions​

Consider the standard expression grammar GG:

E⟶E+E∣E∗E∣idE \longrightarrow E + E \quad \mid \quad E * E \quad \mid \quad \mathbf{id}

We wish to derive the target terminal string:

w=id+id∗idw = \mathbf{id} + \mathbf{id} * \mathbf{id}

Leftmost Derivation (LMD)​

At every step, we underline the leftmost non-terminal and replace it:

E‾⟹lmE‾+E(applied E→E+E)⟹lmid+E‾(applied E→id)⟹lmid+E‾∗E(applied E→E∗E)⟹lmid+id∗E‾(applied E→id)⟹lmid+id∗id(applied E→id)\begin{aligned} \underline{E} &\Longrightarrow_{lm} \underline{E} + E && (\text{applied } E \to E + E) \\ &\Longrightarrow_{lm} \mathbf{id} + \underline{E} && (\text{applied } E \to \mathbf{id}) \\ &\Longrightarrow_{lm} \mathbf{id} + \underline{E} * E && (\text{applied } E \to E * E) \\ &\Longrightarrow_{lm} \mathbf{id} + \mathbf{id} * \underline{E} && (\text{applied } E \to \mathbf{id}) \\ &\Longrightarrow_{lm} \mathbf{id} + \mathbf{id} * \mathbf{id} && (\text{applied } E \to \mathbf{id}) \end{aligned}

Rightmost Derivation (RMD)​

At every step, we underline the rightmost non-terminal and replace it:

E‾⟹rmE+E‾(applied E→E+E)⟹rmE+E∗E‾(applied E→E∗E)⟹rmE+E∗id(applied E→id)⟹rmE+E‾∗id(applied E→id)⟹rmE‾+id∗id(applied E→id)⟹rmid+id∗id(applied E→id)\begin{aligned} \underline{E} &\Longrightarrow_{rm} E + \underline{E} && (\text{applied } E \to E + E) \\ &\Longrightarrow_{rm} E + E * \underline{E} && (\text{applied } E \to E * E) \\ &\Longrightarrow_{rm} E + E * \mathbf{id} && (\text{applied } E \to \mathbf{id}) \\ &\Longrightarrow_{rm} E + \underline{E} * \mathbf{id} && (\text{applied } E \to \mathbf{id}) \\ &\Longrightarrow_{rm} \underline{E} + \mathbf{id} * \mathbf{id} && (\text{applied } E \to \mathbf{id}) \\ &\Longrightarrow_{rm} \mathbf{id} + \mathbf{id} * \mathbf{id} && (\text{applied } E \to \mathbf{id}) \end{aligned}

Both derivations produced the exact same string ww, but through fundamentally different orderings of variable expansions.


🌳 Parse Trees: The Geometric Hierarchy​

A Parse Tree (also known as a Derivation Tree or Concrete Syntax Tree) is an ordered, rooted, labeled tree that provides an invariant geometric representation of a derivation, filtering out the chronological order of replacement.

The Anatomical Invariants of a Parse Tree

Formal structural conditions defining a valid Type-2 derivation tree

Root Node

The Start Symbol (S)

🌱

The root of the entire tree must be labeled with the grammar start symbol S ∈ V.

Single entry pointLevel 0 of hierarchyRepresents full source construct
↓Downward Expansion via Production Rules
Interior Nodes

Syntactic Variables (Non-Terminals)

🌿

Every internal node must be a variable A ∈ V. If node A has children X₁, X₂, ..., X_k from left to right, then A → X₁ X₂ ... X_k MUST be a valid production in P.

Node labeling ∈ VOrdered childrenExact production matching
↓Base Case Terminations
Leaf Nodes

Terminals or Epsilon (T ∪ {ε})

🍂

Every leaf node is labeled with a terminal symbol a ∈ T or the empty string ε. If a leaf is labeled ε, it must be the solitary child of its parent.

Node labeling ∈ T ∪ {ε}Zero outgoing edgesImmutable atomic tokens
↓Left-to-Right Concatenation
Tree Yield

The Derived Terminal Sentence (w)

🎯

Concatenating all leaf labels from left to right yields the final string w ∈ T* generated by the parse tree.

Yield(Tree) = wLeft-to-right tree walkIdentical for LMD and RMD

The Master Theorem of Parse Trees​

Fundamental Theorem: For any context-free grammar GG and any string w∈L(G)w \in L(G):

  1. Every distinct parse tree corresponds to exactly one unique Leftmost Derivation (LMD).
  2. Every distinct parse tree corresponds to exactly one unique Rightmost Derivation (RMD).
  3. An LMD and an RMD are structurally equivalent if and only if they map to the same parse tree.
Architecture Flow

The Derivation-to-Tree Mapping Pipeline

How different derivation paths converge onto an identical parse tree geometry

👈Leftmost Path

LMD Sequence

Top-down prefix-first replacement order.

→
Structural Abstraction
🌳Geometric Core

Canonical Parse Tree

Hierarchy of parent-child production links invariant to expansion timing.

→
Suffix-First Trace
👉Rightmost Path

RMD Sequence

Bottom-up canonical shift-reduce order.


🏭 Real-World Production Context: Compilers & AST Generation​

In modern software engineering, raw source code strings cannot be executed directly by hardware. They must first be parsed into an Abstract Syntax Tree (AST), which is directly derived from the CFG parse tree.

Architecture Flow

Production Compiler Pipeline: From Source Code to AST

How industrial compiler frontends transform text streams into actionable execution trees

🔡Lexical Analysis

Lexer / Tokenizer

Scans raw characters via DFA and regex to emit token stream: [KEYWORD_IF, LPAREN, ID, RPAREN].

→
Token Stream
🌳Syntactic Analysis

CFG Parser (Yacc / ANTLR)

Validates token stream against CFG rules via LMD (LL parser) or RMD (LR parser).

→
Concrete Syntax Tree
✂️AST Synthesis

Tree Pruning & Simplification

Eliminates syntactic noise (parentheses, commas, semicolons); preserves operands and operator hierarchy.

→
Clean Execution Tree
⚡Code Generation

LLVM IR / Bytecode

Traverses AST to perform type checking, register allocation, and machine code optimization.

Industrial Production Case Studies​

  1. JavaScript V8 Engine (Google Chrome / Node.js): When JavaScript code executes, V8's parser uses an LL(k) parser to construct a concrete syntax tree from the ECMA-262 grammar specification. The parser builds a concise AST in memory, which the Ignition interpreter converts into bytecode in under a millisecond.
  2. TypeScript Compiler (tsc): TypeScript specifies its formal grammar using a recursive-descent parser (pure LMD). The parser transforms source files into TypeScript AST nodes (ts.Node), allowing the type checker to traverse expressions and enforce interface contracts.
  3. Domain-Specific Language (DSL) Parsing (Terraform & SQL): HashiCorp's HCL (HashiCorp Configuration Language) and PostgreSQL's SQL query planner use CFG parsers (Bison / Flex) implementing LALR(1) grammars (RMD in reverse). SQL queries like SELECT a, b FROM users WHERE id = 1 are parsed into query execution plan trees using context-free derivation rules.

📐 Numerical Applications & Worked Examples​

Problem 1: Systematic Derivations & Parse Tree Yield​

Problem Statement:
Consider the Context-Free Grammar G=(V,T,P,S)G = (V, T, P, S) where:

  • V={S,A,B}V = \{S, A, B\}
  • T={a,b}T = \{a, b\}
  • Productions PP:
S⟶aB∣bAA⟶a∣aS∣bAAB⟶b∣bS∣aBB\begin{aligned} S &\longrightarrow a B \quad \mid \quad b A \\ A &\longrightarrow a \quad \mid \quad a S \quad \mid \quad b A A \\ B &\longrightarrow b \quad \mid \quad b S \quad \mid \quad a B B \end{aligned}

Derive the string w=aaabbabbbaw = \mathbf{aaabbabbba} by showing:

  1. The complete Leftmost Derivation (LMD).
  2. The complete Rightmost Derivation (RMD).
  3. The formal yield verification of the resulting parse tree.

Step-by-Step Solution:

Step 1: Leftmost Derivation (LMD)​

We systematically expand the leftmost non-terminal at every derivation step:

S‾⟹aB‾(using S→aB)⟹aaB‾B(using B→aBB)⟹aaaBB‾B… (select B→b strategically)⟹aaaB‾BB(using B→aBB to obtain third ’a’)\begin{aligned} \underline{S} &\Longrightarrow a \underline{B} && (\text{using } S \to aB) \\ &\Longrightarrow a a \underline{B} B && (\text{using } B \to aBB) \\ &\Longrightarrow a a a B \underline{B} B \dots \text{ (select } B \to b \text{ strategically)} \\ &\Longrightarrow a a a \underline{B} B B && (\text{using } B \to aBB \text{ to obtain third 'a'}) \end{aligned}

Let us carefully trace the target string w=aaabbabbbaw = a a a b b a b b b a:

  1. S⟹aB‾S \Longrightarrow a \underline{B} (matching 1st symbol a)
  2. ⟹aaB‾B\Longrightarrow a a \underline{B} B (matching 2nd symbol a)
  3. ⟹aaaB‾BB\Longrightarrow a a a \underline{B} B B (matching 3rd symbol a)
  4. ⟹aaabB‾B\Longrightarrow a a a b \underline{B} B (using B→bB \to b, matching 4th symbol b)
  5. ⟹aaabbB‾\Longrightarrow a a a b b \underline{B} (using B→bB \to b, matching 5th symbol b)
  6. ⟹aaabbaB‾B\Longrightarrow a a a b b a \underline{B} B (using B→aBBB \to aBB, matching 6th symbol a)
  7. ⟹aaabbabB‾\Longrightarrow a a a b b a b \underline{B} (using B→bB \to b, matching 7th symbol b)
  8. ⟹aaabbabbS‾\Longrightarrow a a a b b a b b \underline{S} (using B→bSB \to bS, matching 8th and 9th symbols bb)
  9. ⟹aaabbabbbA‾\Longrightarrow a a a b b a b b b \underline{A} (using S→bAS \to bA, matching 9th symbol b)
  10. ⟹aaabbabbba\Longrightarrow a a a b b a b b b a (using A→aA \to a, matching final symbol a)

All 10 steps replaced strictly the leftmost non-terminal. This proves w∈L(G)w \in L(G).

Step 2: Rightmost Derivation (RMD)​

We derive the same string ww by strictly replacing the rightmost non-terminal:

S⟹aB‾⟹aaBB‾⟹aaBbS‾⟹aaBbbA‾⟹aaBbba⟹aaaBB‾bba⟹aaaBaBB‾bba⟹aaaBaB‾bbba⟹aaaBabbbba⟹aaabbabbba\begin{aligned} S &\Longrightarrow a \underline{B} \\ &\Longrightarrow a a B \underline{B} \\ &\Longrightarrow a a B b \underline{S} \\ &\Longrightarrow a a B b b \underline{A} \\ &\Longrightarrow a a B b b a \\ &\Longrightarrow a a a B \underline{B} b b a \\ &\Longrightarrow a a a B a B \underline{B} b b a \\ &\Longrightarrow a a a B a \underline{B} b b b a \\ &\Longrightarrow a a a B a b b b b a \\ &\Longrightarrow a a a b b a b b b a \end{aligned}

Step 3: Yield Verification​

Counting the terminal leaves of the parse tree from left to right:

Leaves=[a,a,a,b,b,a,b,b,b,a]\text{Leaves} = [a, a, a, b, b, a, b, b, b, a]

Yield=aaabbabbba=w\text{Yield} = \mathbf{aaabbabbba} = w

The length ∣w∣=10|w| = 10, and the number of terminal leaves in the parse tree is exactly 10.


Problem 2: Balanced Parentheses Language & Derivation Trees​

Problem Statement:
The language of well-formed (balanced) parentheses over Σ={(,)}\Sigma = \{(, )\} is generated by the CFG:

S⟶(S)∣SS∣ϵS \longrightarrow ( S ) \quad \mid \quad S S \quad \mid \quad \epsilon

For the string w=()()w = \mathbf{()()}:

  1. Construct two distinct leftmost derivations.
  2. Determine whether the grammar produces two distinct parse trees for ww.

Step-by-Step Solution:

Step 1: First Leftmost Derivation (LMD 1)​

Expand using the binary split S→SSS \to SS first:

S‾⟹S‾S(using S→SS)⟹(S‾)S(using S→(S))⟹(ϵ)S‾(using S→ϵ)⟹()(S‾)(using S→(S))⟹()(ϵ)(using S→ϵ)⟹()()\begin{aligned} \underline{S} &\Longrightarrow \underline{S} S && (\text{using } S \to SS) \\ &\Longrightarrow ( \underline{S} ) S && (\text{using } S \to (S)) \\ &\Longrightarrow ( \epsilon ) \underline{S} && (\text{using } S \to \epsilon) \\ &\Longrightarrow () ( \underline{S} ) && (\text{using } S \to (S)) \\ &\Longrightarrow () ( \epsilon ) && (\text{using } S \to \epsilon) \\ &\Longrightarrow ()() \end{aligned}

Step 2: Second Leftmost Derivation (LMD 2)​

Expand using the split S→SSS \to SS, but decompose the right sibling:

S‾⟹S‾S(using S→SS)⟹ϵS‾(using S→ϵ on first variable)⟹S‾S(using S→SS on remaining variable)⟹(S‾)S(using S→(S))⟹()(S‾)(using S→ϵ then S→(S))⟹()()\begin{aligned} \underline{S} &\Longrightarrow \underline{S} S && (\text{using } S \to SS) \\ &\Longrightarrow \epsilon \underline{S} && (\text{using } S \to \epsilon \text{ on first variable}) \\ &\Longrightarrow \underline{S} S && (\text{using } S \to SS \text{ on remaining variable}) \\ &\Longrightarrow ( \underline{S} ) S && (\text{using } S \to (S)) \\ &\Longrightarrow () ( \underline{S} ) && (\text{using } S \to \epsilon \text{ then } S \to (S)) \\ &\Longrightarrow ()() \end{aligned}

Alternatively, using S→SS→SSSS \to SS \to SSS:

  1. S⟹SS⟹SSS…S \Longrightarrow SS \Longrightarrow SSS \dots
  2. In Tree 1, the root splits into S→SSS \to SS, where the left child produces () and the right child produces ().
  3. In Tree 2, the root expands to S→SSS \to SS, where the left child expands to SSSS (producing () and ϵ\epsilon) and the right child produces ().

Step 3: Conclusion​

Because the string w=()()w = ()() admits more than one distinct parse tree, the grammar is formally ambiguous.


Problem 3: Palindromes and Derivation Tree Depth Analysis​

Problem Statement:
Consider the standard palindrome CFG over {0,1}\{0, 1\}:

S⟶0S0∣1S1∣0∣1∣ϵS \longrightarrow 0 S 0 \quad \mid \quad 1 S 1 \quad \mid \quad 0 \quad \mid \quad 1 \quad \mid \quad \epsilon

  1. Construct the parse tree for the even-length palindrome w=1001w = \mathbf{1001}.
  2. Compute the exact depth of the parse tree and the total number of internal vs. leaf nodes.

Step-by-Step Solution:

Step 1: Derivation Sequence​

To generate w=1001w = 1001:

S⟹1S1(applied S→1S1)⟹10S01(applied S→0S0)⟹10ϵ01(applied S→ϵ)=1001\begin{aligned} S &\Longrightarrow 1 S 1 && (\text{applied } S \to 1S1) \\ &\Longrightarrow 1 0 S 0 1 && (\text{applied } S \to 0S0) \\ &\Longrightarrow 1 0 \epsilon 0 1 && (\text{applied } S \to \epsilon) \\ &= 1001 \end{aligned}

Step 2: Parse Tree Topology​

  • Level 0 (Root): Node SS
    • Children: Leaf 1 (left), Internal Node SS (middle), Leaf 1 (right).
  • Level 1 (Middle Child): Node SS
    • Children: Leaf 0 (left), Internal Node SS (middle), Leaf 0 (right).
  • Level 2 (Middle Child): Node SS
    • Children: Single Leaf ϵ\epsilon.

Step 3: Node Count & Depth Calculation​

  • Depth of Tree: The longest path from root to leaf is S→S→S→ϵS \to S \to S \to \epsilon, which has 3 edges. Depth = 3.
  • Internal Nodes:
    • Root SS (Level 0)
    • Middle SS (Level 1)
    • Deepest SS (Level 2)
    • Total internal nodes = 3.
  • Leaf Nodes:
    • Terminal 1 (from Level 0)
    • Terminal 0 (from Level 1)
    • Epsilon ϵ\epsilon (from Level 2)
    • Terminal 0 (from Level 1)
    • Terminal 1 (from Level 0)
    • Total leaf nodes = 5 (44 visible terminals + 11 empty string marker ϵ\epsilon).
  • Total Nodes in Tree: 3+5=83 + 5 = \mathbf{8} nodes.

🎯 Exam & Interview Pitfall Check​

Core Conceptual Questions
  • Does every string generated by a CFG have both an LMD and an RMD?
    Yes! If a string ww belongs to L(G)L(G), there exists at least one derivation tree for ww. By traversing that derivation tree in pre-order (visiting children left-to-right), you obtain the Leftmost Derivation. By traversing the tree visiting children right-to-left, you obtain the Rightmost Derivation. Every valid sentence has at least one LMD and at least one RMD.
  • If a string has two different derivations, does that mean the grammar is ambiguous?
    Not necessarily! A string can have two different derivations simply because one is an LMD and the other is an RMD. That is completely normal! A grammar is ambiguous only if there are two different Leftmost derivations, or two different Rightmost derivations, or two distinct Parse Trees for the same string.
  • Can a CFG production have an empty string on the RHS (A→ϵA \to \epsilon)?
    Yes. In a context-free grammar, A→ϵA \to \epsilon is a valid production (called a null or ϵ\epsilon-production). However, the left-hand side must strictly be a single non-terminal (A∈VA \in V). A production like ϵ→A\epsilon \to A or ab→ϵab \to \epsilon is strictly prohibited in Type-2 grammars.
Common Interview Traps
  • Trap: Confusing Abstract Syntax Trees (AST) with Parse Trees (CST):
    A parse tree (CST) contains every single grammar symbol, including punctuation, semicolons, and parentheses that do not hold semantic meaning. An AST discards syntax noise and retains only the operational structure (e.g. operator node + with left child a and right child b).
  • Trap: Assuming the Yield Includes Non-Terminals:
    The yield of a parse tree is strictly the concatenation of its leaf nodes. During derivation, intermediate steps are sentential forms; but the final yield of a completed parse tree generating a sentence must consist solely of terminal symbols (and ϵ\epsilon markers).
  • Trap: Believing LMD and RMD Can Produce Different Strings:
    An LMD and RMD of the same parse tree always yield the exact same terminal string. They differ only in the chronological sequence of node expansion, not in the final sentence generated.

💬

Discussion & Doubts