notesonly.in

One notebook for every subject — open it anywhere.

Log in

Context-Free Grammars and Languages With easy examples.

A context-free grammar (CFG) is a set of rules for generating strings in a language, written as productions like S → aSb. Each rule replaces one nonterminal symbol with a mix of terminals (actual characters) and nonterminals, regardless of context — hence "context-free". A context-free language is any set of strings some CFG can generate.

This matters because CFGs describe the structure of programming languages: every if-statement, expression, and function call you write follows grammar rules. Compilers use CFGs to parse code into syntax trees. CFGs are also strictly more powerful than regular expressions — they can describe nested, balanced structures like parentheses that regex fundamentally cannot.

Key Concepts

  • Terminal: an actual symbol in the final string (like a, b, +, or if).
  • Nonterminal: a placeholder symbol (like S or Expr) that gets rewritten.
  • Production: a rewrite rule, e.g. Expr → Expr + Term.
  • Start symbol: the nonterminal derivations begin from, usually S.
  • Derivation: the step-by-step rewriting from S to a final string of terminals.
  • Parse tree: a tree showing the grammar structure of a derived string; its leaves read left to right give the string.
  • Ambiguity: a grammar is ambiguous if some string has two different parse trees (bad for compilers — one code, two meanings).
  • Pushdown automaton: the machine model matching CFGs — a finite automaton plus a stack, which is what handles nesting.

How It Works

  1. To check whether a string belongs to a grammar's language, you derive it: start with S and repeatedly replace a nonterminal using a production until only terminals remain — this left-to-right replacement order is a leftmost derivation.
  2. The same derivation drawn as a tree is the parse tree, which is what compilers actually build to understand code structure.
  3. Language designers write grammars for expressions, statements, and declarations; parser generators turn those grammars into parsing code automatically.
  4. If a grammar is ambiguous — say Expr → Expr + Expr lets 1+2+3 group two ways — designers rewrite it with layered rules (Expr → Expr + Term) to force one correct tree.
  5. Because productions can nest nonterminals inside themselves (S → aSb), CFGs generate the balanced, recursive patterns that define real languages.

Worked Example

Grammar: S → aSb | ε (ε means the empty string). Derive "aaabbb" with a leftmost derivation:

  1. S ⇒ aSb (apply S → aSb).
  2. ⇒ aaSbb (rewrite the inner S again).
  3. ⇒ aaaSbbb (rewrite once more).
  4. ⇒ aaabbb (apply S → ε, erasing the last S).

Result "aaabbb" — three a's then three b's, perfectly balanced. This grammar generates exactly the language a^n b^n for n ≥ 0 — strings no regex can describe, since matching the counts needs the stack-like nesting of the recursive rule. The parse tree is a straight chain of S nodes, each wrapping one a…b pair — the visual signature of nesting.

Common Misconceptions

  • "CFGs are just fancier regexes." They are a strictly bigger class — every regular language is context-free, but a^n b^n is context-free and not regular.
  • "Ambiguity is harmless." In programming languages it means one program could mean two things; grammar designers eliminate it deliberately.
  • "Longer derivations mean more powerful grammars." Power comes from the shape of the rules (recursion, nesting), not derivation length.

Real-World Applications

  • Programming language syntax — Python, C, and Java all have published grammars.
  • JSON and XML formats, and parser generators like yacc and ANTLR.
  • Natural language sentence structure and markup languages.

A CFG rewrites nonterminals with productions until only terminals remain, and the a^n b^n derivation shows nesting that regex can never do. Parse trees turn strings into structure — the basis of every compiler. Grammars are where languages, human or machine, get their shape.