Theory of Computation & Computer Graphics β Introduction to Context Free Language, NEC licence examination syllabus (Nepal Engineering Council).
Context Free Grammar (CFG)
Rules that generate languages finite automata cannot recognise β the formalism behind every programming language.
π Where this lives: Every programming language you will ever use is defined by a context-free grammar. The specification of C, Java, Python and SQL each contains a grammar in almost exactly the notation of this topic, and the compiler's parser is generated mechanically from it. The reason is precisely the limitation established in the last section: programming languages have nested structure β brackets inside brackets, blocks inside blocks β and nesting requires unbounded counting, which no regular expression can do. Search "context free grammar programming language specification parser generator".
Definition and derivation
A CONTEXT-FREE GRAMMAR IS A 4-TUPLE
G = (V, T, P, S)
V a finite set of VARIABLES (non-terminals), written in
capitals
T a finite set of TERMINALS β the alphabet of the language
itself, disjoint from V
P a finite set of PRODUCTIONS, each of the form
A β Ξ± where A β V and Ξ± β (V βͺ T)*
S the START SYMBOL, S β V
ββ WHY "CONTEXT FREE" ββββββββββββββββββββββββββββββββββββββ
THE LEFT-HAND SIDE OF EVERY PRODUCTION IS A SINGLE VARIABLE.
That is the entire content of the name. A variable A may be
replaced by Ξ± WHEREVER IT APPEARS, irrespective of what
surrounds it β the surrounding CONTEXT is irrelevant, hence
"context free".
Contrast a CONTEXT-SENSITIVE production such as
aAb β aΞ±b
which permits the replacement only when A sits between an a
and a b. That restriction is what the next level of the
Chomsky hierarchy adds.
ββ DERIVATION ββββββββββββββββββββββββββββββββββββββββββββββ
Writing Ξ± β Ξ² means Ξ² is obtained from Ξ± by applying ONE
production; Ξ± β* Ξ² means zero or more steps.
THE LANGUAGE GENERATED IS
L(G) = { w β T* : S β* w }
β the set of TERMINAL strings derivable from the start
symbol. A string still containing variables is a SENTENTIAL
FORM, not a sentence.
LEFTMOST DERIVATION β always expand the LEFTMOST variable.
RIGHTMOST DERIVATION β always expand the RIGHTMOST variable.
BOTH EXIST FOR EVERY DERIVABLE STRING, and both correspond
to the SAME parse tree. The distinction matters for parsing
algorithms: top-down parsers (LL) construct leftmost
derivations, bottom-up parsers (LR) construct rightmost
derivations in reverse.
ββ WORKED EXAMPLE 1: BALANCED PARENTHESES ββββββββββββββββββ
S β ( S ) | S S | Ξ΅
A leftmost derivation of ( ( ) ) ( ):
S β S S
β ( S ) S using S β (S) on the first S
β ( ( S ) ) S again
β ( ( ) ) S S β Ξ΅
β ( ( ) ) ( S )
β ( ( ) ) ( )
THIS LANGUAGE IS NOT REGULAR β the pumping lemma of the last
topic proves it β YET THE GRAMMAR IS THREE SHORT RULES. THAT
GAP IS THE ENTIRE MOTIVATION FOR THE CHAPTER: recursion in the
grammar supplies the unbounded memory that a finite automaton
lacks, because the derivation can nest to any depth.
ββ WORKED EXAMPLE 2: aβΏbβΏ ββββββββββββββββββββββββββββββββββ
S β a S b | Ξ΅
S β aSb β aaSbb β aaaSbbb β aaabbb
EACH STEP ADDS ONE a AND ONE b SIMULTANEOUSLY, which is
exactly how the grammar enforces the equality of counts that
no finite automaton could maintain.
ββ WORKED EXAMPLE 3: ARITHMETIC EXPRESSIONS ββββββββββββββββ
E β E + T | T
T β T * F | F
F β ( E ) | id
THIS IS THE MOST IMPORTANT GRAMMAR IN THE TOPIC, and the
layering is deliberate. THREE LEVELS OF VARIABLE ENCODE THREE
LEVELS OF PRECEDENCE:
Β· E (expression) handles +, the loosest-binding operator
Β· T (term) handles *, which binds tighter
Β· F (factor) handles parentheses and atoms, binding tightest
Because * can only be introduced BELOW +, a multiplication can
never span an addition, so id + id * id must parse as
id + (id * id).
AND THE RECURSION IS LEFT-RECURSIVE (E β E + T rather than
E β T + E), WHICH MAKES + LEFT-ASSOCIATIVE: a β b β c groups
as (a β b) β c, which is what arithmetic requires.
PRECEDENCE AND ASSOCIATIVITY ARE THEREFORE PROPERTIES OF THE
GRAMMAR'S SHAPE, not extra annotations β a fact that is
examined often.
ββ DESIGNING A GRAMMAR βββββββββββββββββββββββββββββββββββββ
THE STANDARD PATTERNS:
MATCHING PAIRS S β a S b | Ξ΅
NESTING S β ( S ) | Ξ΅
REPETITION S β a S | Ξ΅ (right-recursive)
S β S a | Ξ΅ (left-recursive)
UNION S β Sβ | Sβ
PALINDROMES S β a S a | b S b | a | b | Ξ΅
EQUAL COUNTS
(in any order) S β a S b S | b S a S | Ξ΅
THE METHOD: identify the RECURSIVE STRUCTURE of the language β
what does a string look like in terms of smaller strings of
the same language? β and write that directly as a production.
The hierarchy, and what CFGs cannot do
ββ THE CHOMSKY HIERARCHY βββββββββββββββββββββββββββββββββββ
Four grammar classes, defined by restrictions on productions,
each strictly contained in the next:
TYPE 3 β REGULAR
A β aB or A β a (right-linear)
MACHINE: finite automaton
Only one variable, at the end. No nesting possible.
TYPE 2 β CONTEXT FREE
A β Ξ± (single variable on the left)
MACHINE: PUSHDOWN AUTOMATON β a finite automaton with a
STACK, which is exactly the unbounded memory needed for
nesting.
TYPE 1 β CONTEXT SENSITIVE
Ξ±AΞ² β Ξ±Ξ³Ξ², with |Ξ³| β₯ 1 (never shortening)
MACHINE: linear bounded automaton
TYPE 0 β UNRESTRICTED
Ξ± β Ξ², Ξ± containing at least one variable
MACHINE: TURING MACHINE
THE CONTAINMENTS ARE STRICT:
REGULAR β CONTEXT FREE β CONTEXT SENSITIVE β RECURSIVELY
ENUMERABLE
with the pumping lemmas providing the separating witnesses:
aβΏbβΏ separates regular from context free, and aβΏbβΏcβΏ
separates context free from context sensitive.
ββ WHAT CONTEXT-FREE GRAMMARS CANNOT GENERATE ββββββββββββββ
{ aβΏbβΏcβΏ } β THREE counts cannot be matched;
a stack can compare two things,
not three
{ ww : w β Ξ£* } β a string repeated; the stack pops
in reverse, so it can produce
w wα΄Ώ (a palindrome) but not w w
{ aβΏ : n prime }
{ aβ±bΚ²cα΅ : i < j < k }
THE CHARACTERISTIC LIMITATION IS WORTH STATING PRECISELY: A
STACK IS LAST-IN-FIRST-OUT, SO IT CAN MATCH ONE PAIR OF
NESTED COUNTS BUT CANNOT COMPARE THREE, AND CANNOT REPLAY A
STRING IN THE ORDER IT WAS READ. That single sentence explains
every entry in the list above.
ββ THE PRACTICAL LIMITATION IN PROGRAMMING LANGUAGES βββββββ
A real and instructive consequence: MOST PROGRAMMING LANGUAGES
ARE NOT ACTUALLY CONTEXT FREE, even though their syntax is
specified by a CFG. Rules such as
Β· "a variable must be declared before use"
Β· "the number of arguments must match the function's
declaration"
Β· "types on both sides of an assignment must agree"
ARE NOT EXPRESSIBLE IN A CFG β the first is essentially the ww
problem, requiring the identifier at the use site to match one
seen arbitrarily far earlier.
THE ENGINEERING RESPONSE IS THE STANDARD COMPILER
ARCHITECTURE:
LEXICAL ANALYSIS β regular expressions handle tokens
SYNTAX ANALYSIS β a CFG handles nested structure
SEMANTIC ANALYSIS β a SYMBOL TABLE handles declarations,
types and scope
EACH PHASE USES THE WEAKEST FORMALISM THAT SUFFICES, and the
things the formalism cannot express are pushed to the next
phase. THAT LAYERING IS A DIRECT PRACTICAL APPLICATION OF
THE CHOMSKY HIERARCHY, and it is why the theory is taught to
engineers rather than only to mathematicians.
ββ SIMPLIFICATION OF GRAMMARS ββββββββββββββββββββββββββββββ
Before most algorithms are applied, a grammar is cleaned up:
1. REMOVE USELESS SYMBOLS
NON-GENERATING β variables from which no terminal
string can be derived
UNREACHABLE β symbols not reachable from S
ORDER MATTERS: remove non-generating symbols FIRST,
then unreachable ones. Doing it the other way can leave
useless symbols behind, and this is a classic exam
trap.
2. ELIMINATE Ξ΅-PRODUCTIONS (A β Ξ΅), except that S β Ξ΅ is
retained if Ξ΅ β L(G)
3. ELIMINATE UNIT PRODUCTIONS (A β B, one variable to
another)
4. The result can then be put into Chomsky or Greibach
normal form, as covered later in this section.
Precedence and associativity are properties of the grammar's shape, not annotations bolted on afterwards. Putting * at a level below + is what forces id + id * id to group correctly, and making the recursion left-handed is what makes subtraction left-associative.
π Go further: Most programming languages are not context free, despite being specified with a CFG. "A variable must be declared before use" requires matching an identifier at the use site against one seen arbitrarily far earlier β essentially the ww problem, which is provably beyond a CFG. Compilers respond with a layered architecture: regular expressions for tokens, a CFG for nested structure, and a symbol table for declarations, types and scope. Each phase uses the weakest formalism that suffices, and whatever that formalism cannot express is pushed to the next phase. The Chomsky hierarchy is, quite literally, the compiler's organisational chart. Search "why C is not context free symbol table semantic analysis".
π‘ Exam angle: give the 4-tuple definition and explain the name β a single variable on the left, so replacement ignores context. Distinguish leftmost and rightmost derivations and note that both correspond to the same parse tree. Be able to write a grammar for balanced parentheses, aβΏbβΏ, palindromes and equal counts, and to give a full derivation. The expression grammar E β E+T | T, T β T*F | F, F β (E) | id is the one to memorise, together with the explanation of how it encodes precedence and left-associativity. Know the Chomsky hierarchy with the machine for each type, and the languages CFGs cannot generate.
Syllabus points
Definition (4-tuple); productions
Derivations and language of a CFG
Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Related topics in Introduction to Context Free Language