The Timpson Lyceum · Computation Theory
Lecture 8 (Computation Theory) Pumping Lemma, Right Linear Grammars, and Context-Free Grammars
Overview
This lecture closes out the theory of regular languages and opens the study of grammars. It begins by reviewing the pumping lemma — the standard tool for proving that a language is not regular — restating the pumping property and the contradiction argument behind it. It then introduces right linear grammars, a rule-based way of generating strings that turns out to be logically equivalent to DFAs, NFAs, and regular expressions. Along the way it fixes the vocabulary of grammars (variables, terminals, rules, yields, derives, language of a grammar) and surveys which yes/no questions about regular languages are decidable. Finally it moves up one level to context-free grammars (CFGs), introducing parse trees, ambiguity, and why precedence-preserving grammars matter for compilers.
Key Concepts
Regular language. A language is regular if some DFA recognizes it. DFAs, NFAs, and regular expressions are all logically equivalent, so any of them can describe exactly the regular languages.
The pumping lemma (pumping property). Every regular language has the pumping property, so contrapositively, lacking it proves non-regularity. Formally: for every regular language there is a number (the pumping length, typically the number of states in a recognizing DFA) such that every string with can be split as with
- ,
- , and
- for every .
The intuition: a DFA with states reading a string of length must revisit a state, so the string contains a loop. The looped portion can be repeated ("pumped up") or removed ("pumped down") any number of times and the result still lands in an accept state.
Negation (how it is used). To show is not regular, show the property fails: for any an adversary names, you can exhibit a string of length such that for every legal split (, ) there is some with .
Right linear grammar (a regular grammar). A 4-tuple where is a finite set of variables (capital letters), is a finite set of terminals (everything else), , is a finite set of rules, and is the start variable. Every rule has one of three forms:
- (terminal then variable),
- (single terminal), or
- (empty string),
with and . The variable always sits at the right end of the string, so generation proceeds left to right. A left linear grammar simply puts the variable on the left; both are regular grammars and are logically equivalent. Right linear grammars are logically equivalent to DFAs/NFAs: the rules mirror a DFA's transitions ( plays the role of ) and marks accept states.
Grammar vocabulary (all grammars). For strings of terminals and variables:
- Yields (): if is a rule, then — one rule application.
- Derives (): if or there is a finite chain — any number of yields.
- Language of a grammar: — the terminal-only strings derivable from the start variable.
Decidable questions about regular languages. All of the following can always be answered yes/no for DFAs/NFAs/regex/linear grammars (in contrast to Turing machines, where they become undecidable):
- Membership: does a machine accept string ? (Simulate it.)
- Equivalence: do two machines accept the same language? Check and . Since regular languages are closed under intersection and complement, is regular; build its DFA and check whether its minimal form is the single-state machine with no accept state (recognizes ).
- Infiniteness: is the language infinite? Convert to a regular expression — it is infinite iff a Kleene star appears (equivalently, the machine has a loop on a path to an accept state).
- Subset: is ? Check .
Context-free grammar (CFG). Same 4-tuple , but rules are relaxed to where the left side is a single variable and the right side is any string of variables and terminals. "Context-free" means a variable may be replaced regardless of its surrounding symbols. (A context-sensitive grammar allows more than one symbol on the left, e.g. , so replacement depends on context.) Right linear grammars are a subset of CFGs, and CFGs are strictly more powerful than DFAs — e.g. generates , a non-regular language.
Parse trees. A derivation can be drawn as a tree whose root is , whose internal nodes are variables, and whose leaves (read left to right) spell the generated string. A well-chosen arithmetic grammar makes the tree encode operator precedence: forcing multiplication to bind before addition.
Ambiguity. A string is derived ambiguously if it has two or more distinct parse trees. A grammar is ambiguous if it generates any string ambiguously. Compilers avoid this by using restricted, unambiguous CFGs (the LR(k) grammars). Deciding whether an arbitrary CFG is ambiguous is undecidable in general (though decidable for particular cases and for LR(k) grammars) — like how there is no general solution formula for degree-5 polynomials even though specific ones are solvable.
Worked Example
Prove is not regular (pumping lemma, by contradiction).
Rule first, then the work: assume is regular with pumping length , choose a witness string longer than , then show every legal split can be pumped out of .
Every admissible split yields a string outside , contradicting the pumping property. Therefore no such exists and is not regular.
Summary
- The pumping lemma states a property all regular languages share; proving a language lacks it (pick a worst-case string, show every legal split pumps out of the language) proves non-regularity.
- Right linear grammars (, , ) generate exactly the regular languages and join DFAs, NFAs, and regular expressions as four equivalent descriptions of the same class.
- Grammar terminology: a rule application yields (); a chain of applications derives (); the language of a grammar is all terminal strings derivable from .
- For regular languages, membership, equivalence, infiniteness, and subset are all decidable — equivalence reduces to checking and via closure under intersection and complement.
- Context-free grammars allow any string on the right side of a rule (left side stays one variable); they are strictly more powerful than DFAs and capture languages like .
- Parse trees visualize derivations and can encode precedence; a grammar is ambiguous if some string has two or more parse trees — compilers rely on unambiguous LR(k) grammars to avoid this.