Grammars & Formal Languages

A rigorous guide to grammars as generative rewrite systems: derivations and parse trees, ambiguity, the Chomsky hierarchy, right-linear grammar–automaton equivalence, recursive structure, and the differences among BNF, EBNF, and ABNF.

A formal grammar is a finite set of local rewriting rules that can generate an infinite language. Its power comes from separating reusable structural categories—nonterminals—from the terminal symbols that appear in finished words. Derivations describe the rewrite history; parse trees reveal the hierarchical structure that history builds.

The notation used to print a grammar is a separate concern. BNF, ISO EBNF, the EBNF used by W3C specifications, and ABNF are metalanguages with different operator conventions. A reader must first understand the underlying productions, then apply the notation legend of the particular specification.

A grammar is a generator #

For a context-free grammar, each production has the form

A→α,A∈N,α∈(N∪Σ)∗.A\to\alpha, \qquad A\in N,\quad \alpha\in(N\cup\Sigma)^*.

If a string of grammar symbols contains AA, one derivation step may replace that occurrence by α\alpha:

xAy⇒xαy.xAy\Rightarrow x\alpha y.

The reflexive, transitive closure ⇒∗\Rightarrow^* allows zero or more steps. A sentential form is any string reachable from SS; the generated language retains only completed terminal strings:

L(G)={w∈Σ∗∣S⇒∗w}.L(G)=\{w\in\Sigma^*\mid S\Rightarrow^*w\}.

This is different from an automaton's direction of work. A grammar starts with one abstract symbol and expands toward a word; a recognizer starts with a word and decides whether it belongs. The descriptions can characterize the same language, but their mechanisms are not identical.

Derivations record order; parse trees record structure #

Consider a grammar for bracketed lists of zero or more item tokens:

L→[ O ],O→ε∣I,I→item∣item,I.\begin{aligned} L &\to [\ O\ ],\\ O &\to \varepsilon\mid I,\\ I &\to \mathtt{item}\mid \mathtt{item},I. \end{aligned}

One leftmost derivation of [item,item] is

L⇒[O]⇒[I]⇒[item,I]⇒[item,item].L\Rightarrow[O]\Rightarrow[I] \Rightarrow[\mathtt{item},I] \Rightarrow[\mathtt{item},\mathtt{item}].

A leftmost derivation always expands the leftmost nonterminal; a rightmost derivation chooses the rightmost. Those are scheduling policies for constructing a tree. The parse tree itself records which production expanded each nonterminal and preserves the ordered children.

Reading terminal leaves from left to right gives the yield [item,item]. Several unrestricted derivation sequences can expand independent subtrees in different orders while producing the same tree, so “two derivation sequences” alone is not yet evidence of ambiguity.

The grammar's construction also exposes an invariant: every generated word begins with [, ends with ], and its interior is either empty or alternates an item with zero or more comma–item pairs. A soundness proof follows the productions. A completeness proof works backward: any intended nonempty list has a first item and either stops or has a comma followed by a shorter list.

Ambiguity is competing structure #

The deliberately ambiguous expression grammar

E→E+E∣E∗E∣idE\to E+E\mid E*E\mid \mathtt{id}

gives id + id * id two structures:

The terminal sequence is the same, but the root operation—and therefore grouping—is different. A precedence-bearing grammar separates levels:

Expr→Expr+Term∣Term,Term→Term∗Atom∣Atom,Atom→id∣(Expr).\begin{aligned} \mathit{Expr} &\to \mathit{Expr}+\mathit{Term}\mid\mathit{Term},\\ \mathit{Term} &\to \mathit{Term}*\mathit{Atom}\mid\mathit{Atom},\\ \mathit{Atom} &\to \mathtt{id}\mid(\mathit{Expr}). \end{aligned}

Now multiplication is constructed below addition, and the left recursion makes repeated operators group to the left in the structural reading. Showing that this one word has one intended tree demonstrates the repair locally; proving the grammar unambiguous for every word is a stronger induction over expression structure.

Left recursion is also not synonymous with ambiguity. It is a structural form that some parsing strategies cannot handle directly, while other parsers can; ambiguity remains a property of generated parse structure.

Production restrictions form the Chomsky hierarchy #

The grammar types differ by which replacements are permitted. The historical definitions and modern textbook conventions vary around empty-word exceptions, so the convention must be declared rather than inferred.

Type Core production restriction Structural effect
0: unrestricted α→β\alpha\to\beta, where α\alpha contains a nonterminal no length or context restriction beyond a meaningful left side
1: context-sensitive historically xAy→xγyxAy\to x\gamma y with nonempty γ\gamma; commonly presented as noncontracting rules replacement may depend on surrounding context and does not shorten the form, apart from a separately handled start-symbol exception
2: context-free A→γA\to\gamma one nonterminal may be expanded independently of neighbors
3: regular consistently right-linear rules such as A→aBA\to aB or A→aA\to a, with a declared empty-word convention at most one continuing nonterminal, always on the same side

Each stronger restriction yields a language family contained in the less restricted one. Chomsky's finite-state correspondence proves that type-3 languages are precisely finite-state languages, and his separation result shows that type 2 contains languages not generated by type-3 grammars.

The memory labels in this diagram are orientation, not definitions. A full treatment of pushdown, linear-bounded, and Turing-machine recognizers belongs in their own chapters; compressing them into one hierarchy picture would hide their mechanisms.

Right-linear grammars and finite automata are equivalent #

Use the right-linear convention

A→aB,A→a,A\to aB, \qquad A\to a,

plus a separately declared S→εS\to\varepsilon rule when the language contains the empty word. Other equivalent conventions allow epsilon from accepting-state nonterminals; consistency matters more than punctuation.

Grammar to NFA #

For each nonterminal create one NFA state, and add a fresh accepting state ff:

  • A→aBA\to aB becomes A→aBA\xrightarrow{a}B;
  • A→aA\to a becomes A→afA\xrightarrow{a}f;
  • if the declared convention permits A→εA\to\varepsilon, mark AA accepting or add an equivalent epsilon path.

The start nonterminal becomes the start state. A derivation emitting a1…ana_1\ldots a_n corresponds step for step to a path labeled by those terminals. Induction on the number of productions proves both soundness and completeness.

NFA to grammar #

For each NFA state qq, create a nonterminal AqA_q. For every transition p→aqp\xrightarrow{a}q, add

Ap→aAq.A_p\to aA_q.

For each accepting state qq, add Aq→εA_q\to\varepsilon under this conversion convention. The start state's nonterminal is the grammar start. Induction on path length shows that a labeled path to an accepting state exists exactly when the corresponding terminal derivation exists.

Worked correspondence: words ending in ab #

Consider

S→aS∣bS∣aA,A→b.\begin{aligned} S&\to aS\mid bS\mid aA,\\ A&\to b. \end{aligned}

The alternatives S→aSS\to aS and S→aAS\to aA are the same nondeterministic choice as “keep scanning” versus “guess that this a starts the final suffix.” The conversion produces:

Production NFA transition
S→aSS\to aS S→aSS\xrightarrow{a}S
S→bSS\to bS S→bSS\xrightarrow{b}S
S→aAS\to aA S→aAS\xrightarrow{a}A
A→bA\to b A→bfA\xrightarrow{b}f

For bbab, the derivation and path align:

S⇒bS⇒bbS⇒bbaA⇒bbab,S\Rightarrow bS\Rightarrow bbS\Rightarrow bbaA\Rightarrow bbab,

S→bS→bS→aA→bf.S\xrightarrow{b}S\xrightarrow{b}S\xrightarrow{a}A\xrightarrow{b}f.

For baba, every guessed final a either meets the wrong next symbol or finishes before the input does. Correspondingly, no derivation removes every nonterminal while yielding baba.

Recursive grammars express unbounded nesting #

The grammar

B→ε∣[B]BB\to\varepsilon\mid [B]B

generates balanced bracket strings. Each use of [B]B contributes one matched pair: the first BB generates the nested interior and the second generates what follows.

Two invariants characterize the intended structure:

  1. Every generated word has equally many [ and ] symbols.
  2. Every prefix has at least as many [ as ] symbols.

Soundness follows by structural induction on the parse tree. For completeness, take any nonempty balanced word. Its first [ has a matching ]; split the word into the balanced interior and balanced remainder, then apply induction to both.

No finite automaton can recognize exact unbounded balance. Prefixes consisting of nn opening brackets require different residual behavior: the suffix of nn closing brackets completes exactly the matching depth. By Myhill–Nerode, there are infinitely many distinguishable prefixes.

A finite automaton can approximate the language up to a fixed depth kk, because it needs only k+1k+1 depth states plus overflow/error. The gap is not that finite automata cannot count at all; they cannot retain an unbounded exact count.

BNF, EBNF, and ABNF are metalanguages #

The mathematical grammar and the notation used to serialize it are separate layers. ISO/IEC 14977 standardizes one Extended BNF. The W3C XML specification declares its own EBNF notation, including grouping, alternation, optionality, repetition, and subtraction. RFC 5234 defines ABNF for Internet specifications, including its rule form, repetition syntax, numeric terminals, and incremental alternatives.

The same bracketed-list language can be written several ways, provided each block carries its own legend.

Metalanguage convention Example
declared plain BNF <list> ::= "[" <items-opt> "]" with separate recursive productions
W3C-style EBNF list ::= '[' ('item' (',' 'item')*)? ']'
RFC 5234 ABNF style list = "[" [ "item" *( "," "item" ) ] "]"

These lines are translations of one intended structure, not a claim that ?, [], quotes, or repetition markers have universal meaning. In ABNF, for example, bracketed elements and repetition are defined by RFC 5234; in W3C's XML grammar, the specification's own notation section governs.

Proving that a grammar describes the intended language #

Testing sample strings can reveal errors but cannot establish equivalence for an infinite language. A reusable proof has two directions:

Soundness #

Show that every production preserves an invariant satisfied by intended words. Induction may be over derivation length or parse-tree structure. For the bracket grammar, every constructor adds a matched outer pair around a balanced interior and concatenates a balanced remainder.

Completeness #

Show that every intended word has a structural decomposition corresponding to some production. Apply induction to the smaller pieces. For a comma-separated list, split off the first item; for balanced brackets, split at the closing bracket matching the first opener.

When a proposed grammar is wrong, seek the shortest witness:

  • an extra word generated by the grammar but outside the intended language, or
  • a missing word in the intended language that has no derivation.

Shortest witnesses localize the faulty choice because all shorter structures already behave correctly.

Useful static analyses on a grammar #

Three finite fixed-point analyses expose dead structure before parsing begins:

Nullable
A nonterminal is nullable if it derives $\varepsilon$.
Productive
A nonterminal is productive if it derives at least one terminal word.
Reachable
A nonterminal is reachable if some derivation from $S$ contains it.

Compute each set by repeatedly adding nonterminals whose production right sides satisfy the current condition until no set changes. A nonterminal that is unreachable or unproductive cannot participate in any completed start-symbol derivation. Removing it is safe only after that claim is established; deleting a nullable or merely inconvenient symbol can change the language.

Normal forms and parsing algorithms build on these analyses, but their transformations need exact side conditions—especially around ε\varepsilon and the start symbol. They should not be treated as name-only rewrite recipes.

Diagnostic checklist #

  • Are terminals and nonterminals disjoint and visually distinguishable?
  • Does every displayed terminal word have all nonterminals eliminated?
  • Are ⇒\Rightarrow and ⇒∗\Rightarrow^* being used as rewrite relations rather than automaton transitions?
  • Are two derivations actually two parse trees, or merely two expansion orders for the same tree?
  • Is ambiguity attributed to the grammar rather than automatically to the language?
  • Does a claimed right-linear grammar keep the continuing nonterminal consistently on one side?
  • Is the empty-word convention stated before translating accepting states?
  • Does the grammar-to-automaton proof align one emitted terminal with one transition?
  • Is an EBNF/ABNF operator interpreted from the local official legend?
  • Do soundness and completeness cover all generated and all intended words, rather than a sample?

The core mental model is structural generation: productions define which trees may be built, and terminal words are their yields. Regular grammars restrict those trees until only finite-state continuation remains; context-free recursion permits unbounded nesting. The notation printed around those rules is important, but it is never a substitute for their semantics.

Sources

  1. paperChomsky — Three Models for the Description of Language
  2. paperChomsky — On Certain Formal Properties of Grammars
  3. docsISO/IEC 14977:1996 — Syntactic metalanguage — Extended BNF
  4. docsW3C — Extensible Markup Language (XML) 1.0, Fifth Edition
  5. docsRFC 5234 / STD 68 — Augmented BNF for Syntax Specifications

Searches titles, aliases, headings, summaries, and full text.↑↓ move ↵ open esc close