Principles of Compiler Design
Chapter 4: Syntax Analysis
Contents
• Role of parser
• Context free grammar
• Derivation & Ambiguity
– Left Recursion & Left Factoring
• Classification of parsing
– Top down parsing
– Bottom up parsing
Syntax Analysis
Syntax analyzer receives the source code in the
form of tokens from the lexical analyzer and
performs syntax analysis, which create a tree-like
intermediate representation that depicts the
grammatical structure of the token stream.
Syntax analysis is also called parsing.
Syntax Analysis
• They are then checked for proper syntax
– the compiler checks to make sure the statements and expressions are
correctly formed.
– It checks whether the given input is in the correct syntax of the
programming language or not.
– It construct the Parse Tree for checking.
– It helps you to detect all types of Syntax errors.
The Role of the Parser
Parser obtains a string of token from the lexical analyzer and
reports syntax error if any otherwise generates syntax tree.
The Role of the Parser
Major task conducted during parsing(syntax analysis):
– the parser obtains a stream of tokens from the lexical analyzer
and verifies that the stream of token names can be generated by
the grammar for the source language.
– Determine the syntactic validity of a source string, a tree is built
for use by the subsequent phases of the compiler.
– Collecting information about various tokens into the symbol
table, performing type checking and other kinds of semantic
analysis.
Context-Free Grammars
• A grammar is a list of rules which can be used to produce or
generate all the strings of a language.
• According to Noam Chomsky, there are four types of
grammars
– Type 3 (Regular expression),
– Type 2 (Context Free Grammar)
– Type 1 (Context Sensitive Grammar) and
– Type 0 (Unrestricted Grammar).
Type - 3 Grammar
• Type-3 grammars generate regular languages.
• Type-3 grammars must have a single non terminal on the left-
hand side and a right-hand side consisting of a single terminal or
single terminal followed by a single non-terminal.
• The productions must be in the form X → a or X → aY, where X,
Y ∈ N (Nonterminal) and a ∈ T (Terminal).
• The rule S → ε is allowed if S does not appear on the right side of
any rule.
Type - 2 Grammar
• Type-2 grammars generate context-free languages.
• The productions must be in the form A → γ where A ∈ N
Non-terminal and γ∈(T ∪ N)* string of terminals and non-
terminals.
• The languages generated by these grammars are recognized
by a non-deterministic pushdown automaton.
Type - 1 Grammar
• Type-1 grammars generate context-sensitive languages.
• The productions must be in the form αAβ → αγβ, where A∈N (Non-
terminal) and α, β, γ ∈ T ∪ N* (Strings of terminals and non-
terminals).
– | αAβ | ≤ | αγβ |
• The strings α and β may be empty, but γ must be non empty.
• The rule S → ε is allowed if S does not appear on the right side of
any rule.
• The languages generated by these grammars are recognized by a
Linear Bounded Automaton.
Type - 0 Grammar
• Type-0 grammars generate recursively enumerable languages.
• The productions have no restrictions.
• They are any phase structure grammar including all formal grammars.
• They generate the languages that are recognized by a Turing machine.
• The productions can be in the form of α → β where α is a string of
terminals and non-terminals with at least one non-terminal and α
cannot be null and β is a string of terminals and non-terminals.
Example
S → ACaB
Bc → acB
CB → DB
aD → Db
Context-Free Grammars
Context-Free Grammar is a powerful tool for describing the syntax of
programming languages.
A context-free grammar is a 4-tuple (V, T, S, P), where
(i) V is a finite set called the variables(non-terminals)
(ii) T is a finite set, disjoint from V, called the terminals
(iii) S ∈V is the start variable.
(iv) P is a finite set of rules, with each rule being a variable and a
string of variables and terminals, and
– If u, v and w are strings of variables and terminals, and A → w is a
rule of the grammar, we say that uAv yields uwv, written uAv ⇒ uwv.
Example #1 - Context-Free Grammars
• Assume the grammar G is given as;
G: E E O E| (E) | -E | id
O+|-|*|/|↑
• Write terminals, non terminals, start symbol, and productions for
following grammar.
– Terminals: id + - * / ↑ ( )
– Non terminals: E, O
– Start symbol: E
– Productions: E E O E| (E) | -E | id
O+|-|*|/|↑
Example #2 - Context-Free Grammars
• G: S AB
A aAA
A aA
Aa
B bB
Bb
1. Q1. Identify Start variable, Terminal symbols , Non terminals and
Production rules.
2. Q2. Check if the following input string is accepted or not by the given G.
Input string= ab, aab, aaab , aabba.
Context-Free Grammars
• A context-free grammar -
– Gives a precise syntactic specification of a programming
language.
– The design of the grammar is an initial phase of the design
of a compiler.
– A grammar can be directly converted into a parser by
some tools.
• Parser: program that takes tokens and grammars (CFGs) as
input and validates the output tokens against the grammar.
Context-Free Grammars(CFG)
CFG
Right Linear Left Linear
Grammar Grammar
Conversion of Left-linear to Right-Linear Grammar
• Algorithm
• If the left linear grammar has a rule with the start symbol S on the
right hand side, simply add this rule: S0 → S
• Symbols used by the algorithm
– Let S denote the start symbol
– Let A, B denote non-terminal symbols
– Let p denote zero or more terminal symbols
– Let ε denote the empty symbol
Conversion of Left-linear Grammar into Right-Linear Grammar
1) If the left linear grammar has a rule S → p, then make that a rule in
the right linear grammar
2) If the left linear grammar has a rule A →p, then add the following
rule to the right linear grammar: S → p A
3) If the left linear grammar has a rule B → Ap, add the following rule
to the right linear grammar: A → pB
4) If the left linear grammar has a rule S → Ap, then add the following
rule to the right linear grammar: A → p
5) If the left linear grammar has a rule S → A, then add the following
rule to the right linear grammar: A →
Conversion of Left-linear Grammar into Right-Linear Grammar
Left Linear
S → Aa
A → ab
Right Linear
left linear
S → abA
S → Aa
A → ab
2) If the left linear grammar has this rule A → p, then add the
following rule to the right linear grammar: S → pA
20
Right hand side of S has non-terminal
Left Linear Right Linear
S → Aa S → abA
A → ab A→a
4) If the left linear grammar has S → Ap, then add the following rule to
the right linear grammar: A → p
Left Linear Right Linear
S → Aa S → abA
A → ab A→a
Both grammars generate this language: {aba}
21
Convert this left linear grammar
Original Grammar Left Linear
S → Ab S0 → S
S → Sb
S → Ab
A → Aa
A→a
make a new
start symbol
S → Sb
A → Aa
A→a
Convert this
22
Right hand side has terminals
left linear right linear
S0 → S S0 → aA
S → Ab
S → Sb
A → Aa
A→a
2) If the left linear grammar has this rule A → p, then add the
following rule to the right linear grammar: S → pA
23
Right hand side has non-terminal
Left Linear Right Linear
S0 → S S0 → aA
S → Ab A → bS
S → Sb A → aA
A → Aa S → bS
A→a
3) If the left linear grammar has a rule B → Ap, add the
following rule to the right linear grammar: A → pB
24
Right hand side of start symbol has non-
terminal
Left Linear Right Linear
S0 → S S0 → aA
S → Ab A → bS
S → Sb A → aA
A → Aa S → bS
A→a S→ε
4) If the left linear grammar has S → Ap, then add the
following rule to the right linear grammar: A → p
25
Equivalent!
Left Linear Right Linear
S0 → S S0 → aA
S → Ab A → bS
S → Sb A → aA
A → Aa S → bS
A→a S→ε
Both grammars generate this language: {a+b+}
26
Derivation & Ambiguity
• Derivation: Derivation is used to find whether the string belongs to a
given grammar or not.
– Derivation is a sequence of production rules.
Production Rules Derivations
• Types of derivations are:
1. Leftmost derivation
2. Rightmost derivation
Leftmost Derivation
• A derivation of a string 𝑊 in a grammar 𝐺 is a left most derivation if at
every step the left most non terminal is replaced.
• Grammar: SS+S | S-S | S*S | S/S | a Output string: a*a-a
Rightmost Derivation
• A derivation of a string 𝑊 in a grammar 𝐺 is a rightmost derivation
if at every step the right most non terminal is replaced.
• It is all called canonical derivation.
• Grammar: SS+S | S-S | S*S | S/S | a Output string: a*a-a
Example #2 - Leftmost rightmost Derivation
• Consider the grammar S S+S | S*S | a| b. Find leftmost and
rightmost derivation for the string w = a*a+b.
• Solution:
Leftmost derivation Rightmost derivation
DERIVATION TREES
A derivation tree is a graphical representation of derivation that
filters out the order of replacing non-terminals.
– Root node = start symbol
– Interior nodes = non-terminals
– Leaves = terminals.
Example:
Rules: E E+E | E*E | -E | (E) | id
Input: –(id + id )
DERIVATION TREES
• Example -1: A grammar G which is context-free has the productions
S → aAB
A → Bba
B → bB
B→c
• The word w = acbabc is derived as follows:
S ⇒ aAB
⇒ a(Bba)B
⇒ acbaB
⇒ acba(bB)
⇒ acbabc.
• Obtain the derivation tree.
DERIVATION TREES
Exercise- Derivation
1. Perform leftmost derivation and draw parse tree.
S A1B
A 0A | 𝜖
B 0B | 1B | 𝜖
Output string: 1001
2. Perform leftmost derivation and draw parse tree.
S 0S1 | 01
Output string: 000111
3. Perform rightmost derivation and draw parse tree.
E E+E | E*E | id | (E) | -E
Output string: id + id * id
Exercise- Derivation
Ambiguity
• Ambiguity, is a word, phrase, or statement which contains more
than one meaning.
Ambiguity
A grammar that produces more than one parse tree for some sentence is
said to be ambiguous. Or
Ambiguous grammar is one that produces more than one leftmost or more
than one rightmost derivation for the same sentence.
Ambiguous grammar
Ambiguous grammar is one that produces more than one leftmost or
more than one rightmost derivation for the same sentence.
Grammar: S→S+S | (S) | a Output string: a+a+a
Here, Two leftmost derivation for string a+a+a is possible because Rule of
associativity is not maintained.
Ambiguous grammar
Consider the CFG S → S + S | S* S | a | b and string w = a*a +b,
show the leftmost derivations.
Exercise
Shows that the following grammars are ambiguous or not.
a) S → SS | a | b
b) S → A | B | b , A → aAB | ab, B → abB | ϵ
Causes of ambiguity
There are two causes of ambiguity in grammar:
1. Precedence is not maintained in grammar.
2. Associativity is not maintained in grammar.
Associativity of Operators
If an operand has operator on both the sides, the side on which
operator takes this operand is the associativity of that operator.
In (a+b)+c b is taken by left
+, -, *, / are left associative and ^, = are right associative.
Example
– 1+2+3 first we evaluate (1+2)+3 left associative
– 1^2^3 => 1 ^(2^ 3) right associative
– a=b=c right associative
Precedence of Operator
Most programming languages have operator precedence rules
that state the order in which operators are applied.
Operators precedence rules can be incorporated directly into a
Context Free Grammar to obtain only one parse tree for the
input expression.
Eliminating Ambiguity - Left Recursion
A grammar is said to be left recursive if it has a non terminal 𝐴
such that there is a derivation.
𝑨 → 𝑨𝜶 for some string 𝛼.
In other words , in the derivation process starting from any non – terminal A,
if the sentential form starts with the same non-terminal A, then we say that
the grammar is having left recursion.
Left Recursion Elimination
The left recursion in the grammar G can be eliminated as shown
below. Consider the A – production of the form
A → Aα1 | A α2 | A α3 |……. |A αn | 1 | 2 | 3 |……. | m ,
Where i don't start with A.
Then the A- production can be replaced by:
Left Recursion Elimination
Example #1:
𝐴 → 𝐴𝛼| 𝛽 A →𝛽 A
A → 𝛼 A | ϵ
#2: Eliminate the left recursion from the following grammars:
E → E+T | T
T → T* F | F
F → (E) | id
Left Recursion Elimination
Exercise #1: eliminate left recursion from the following
grammar
S → Ab | a
A → Ab | Sa
• Solution: substituting for S in A – production can eliminate the
S → Ableft
indirect | a recursion from S. So the grammar can be written
A → aaA
?
1
as, 1
A →b A | ba A | ϵ
1 1
S → Ab | a
A → Ab | Aba | aa
Example #2: eliminate left recursion
Eliminating Ambiguity - Left Factoring
Left factoring is a grammar transformation that is useful for
producing a grammar suitable for predictive parsing.
Two or more productions of a variable A of the grammar G = (V, T,
P, S) are said to be have left factoring if A – productions are of the
form
A → α1 | α2 | α3 |…….. |αn , where I (V T)* and does not
start (prefix) with α. All these A- productions have common left factor α.
Left Factoring - Elimination
Let the variable A has (left factoring ) productions as follows:
A → α1 | α2 | α3 |…….. |αn |1 | 2 | …… | m , where
1, 2 ,3,…….. , n |1 , 2 , …… ,m don't contain α as
prefix, then we replace A-productions by:
A → αA’| 1 | 2 | …… | m , where
A’ → 1 | 2 | 3 |…….. |n
Left Factoring - Elimination
Example #1:
Example #2: consider the grammar S → aSa | aa, and remove
the left factoring(if any).
Solution –
S → aSa | aa have α = a as left factor, so removing the left
factoring, we get the productions :
S →aS’
S’ → Sa | a
Basic Parsing Techniques
Parsing is a technique that takes input string and produces
output either a parse tree if string is valid sentence of grammar,
or an error message indicating that string is not a valid.
Types of parsing:
1. Top down parsing - parser build parse tree from top to bottom.
2. Bottom up parsing- parser starts from leaves and work up to the
root.
Classification of Parsing Methods
Top down Parsing - Backtracking
• In backtracking, expansion of nonterminal symbol we choose
one alternative and if any mismatch occurs then we try another
alternative.
• Grammar: S cAd Input string: cad
A ab
Top down Parsing - LL(1) parser (predictive parser)
• LL(1) is non recursive top down parser.
1. First L indicates input is scanned from left to right.
2. The second L means it uses leftmost derivation for input
string
3. 1 means it uses only input symbol to predict the parsing
process.
Top down Parsing - LL(1) parsing (predictive parsing)
• Steps to construct LL(1) parser:
1. Remove left recursion / Perform left factoring (if any).
2. Compute FIRST and FOLLOW of non terminals.
3. Construct predictive parsing table.
4. Parse the input string using parsing table.
Top down Parsing - LL(1) parsing (predictive parsing)
• Rules to compute first of non terminal
1. If 𝐴 → 𝛼 and 𝛼 is terminal, add 𝛼 to 𝐹𝐼𝑅𝑆𝑇(𝐴).
2. If 𝐴 → ∈, add ∈ to 𝐹𝐼𝑅𝑆𝑇(𝐴).
3. If 𝑋 is nonterminal and 𝑋𝑌1 𝑌2 … . 𝑌𝑘 is a production, then
place 𝑎 in 𝐹𝐼𝑅𝑆𝑇(𝑋) if for some 𝑖, a is in 𝐹𝐼𝑅𝑆𝑇(𝑌𝑖 ), and 𝜖 is in all
of 𝐹𝐼𝑅𝑆𝑇(𝑌1), …… , 𝐹𝐼𝑅𝑆𝑇(𝑌𝑖 −1 );that is 𝑌1 … 𝑌𝑖 −1 ⇒ 𝜖. If 𝜖 is
in 𝐹𝐼𝑅𝑆𝑇(𝑌𝑗 ) for all 𝑗 = 1,2, … . . , 𝑘 then add 𝜖 to 𝐹𝐼𝑅𝑆𝑇(𝑋).
Everything in 𝐹𝐼𝑅𝑆𝑇(𝑌1) is surely in 𝐹𝐼𝑅𝑆𝑇(𝑋) If 𝑌1 does not derive 𝜖,
then we do nothing more to 𝐹𝐼𝑅𝑆𝑇(𝑋), but if 𝑌1 ⇒ 𝜖, then we add
Top down Parsing - LL(1) parsing (predictive parsing)
Simplification of Rule 3
• If 𝐴 → 𝑌1𝑌2 … … . . 𝑌𝐾 ,
– If 𝑌1 does not derives ∈ 𝑡ℎ𝑒𝑛,
𝐹𝐼𝑅𝑆𝑇(𝐴) = 𝐹𝐼𝑅𝑆𝑇(𝑌1)
– If 𝑌1 derives ∈ 𝑡ℎ𝑒𝑛,
𝐹𝐼𝑅𝑆𝑇 (𝐴) = 𝐹𝐼𝑅𝑆𝑇 (𝑌1 )− 𝜖 U 𝐹𝐼𝑅𝑆𝑇(𝑌2)
– If 𝑌1 & Y2 derives ∈ 𝑡ℎ𝑒𝑛,
𝐹𝐼𝑅𝑆𝑇 (𝐴) = 𝐹𝐼𝑅𝑆𝑇 (𝑌1 ) − 𝜖 U 𝐹𝐼𝑅𝑆𝑇(𝑌2) − 𝜖 𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌3)
Top down Parsing - LL(1) parsing (predictive parsing)
Simplification of Rule 3
• If 𝐴 → 𝑌1𝑌2 … … . . 𝑌𝐾 ,
– If 𝑌1 , Y2 & Y3 derives ∈ 𝑡ℎ𝑒𝑛,
𝐹𝐼𝑅𝑆𝑇 (𝐴) = 𝐹𝐼𝑅𝑆𝑇 (𝑌1) − 𝜖 𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌2) − 𝜖 𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌3) − 𝜖
𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌4)
• If 𝑌1 , Y2 , Y3 …..YK all derives ∈ 𝑡ℎ𝑒𝑛,
𝐹𝐼𝑅𝑆𝑇 (𝐴) = 𝐹𝐼𝑅𝑆𝑇 (𝑌1) − 𝜖 𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌2) − 𝜖 𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌3) −
𝜖 𝑈 𝐹𝐼𝑅𝑆𝑇(𝑌4) − 𝜖 𝑈 … … … … 𝐹𝐼𝑅𝑆𝑇(𝑌𝑘) (note: if all non
terminals derives ∈ then add ∈ to FIRST(A))
Top down Parsing - LL(1) parsing (predictive parsing)
Rules to compute FOLLOW of non terminal
1. Place $ 𝑖𝑛 𝑓𝑜𝑙𝑙𝑜𝑤(𝑆) . (S is start symbol)
2. If A → 𝛼𝐵𝛽 , then everything in 𝐹𝐼𝑅𝑆𝑇(𝛽) except for 𝜖 is placed in
𝐹𝑂𝐿𝐿𝑂𝑊(𝐵)
3. If there is a production A → 𝛼𝐵 or a production A → 𝛼𝐵𝛽, where
𝐹𝐼𝑅𝑆𝑇(𝛽) contains 𝜖 then everything in F𝑂𝐿𝐿𝑂𝑊(𝐴) = 𝐹𝑂𝐿𝐿𝑂𝑊(𝐵)
Top down Parsing - LL(1) parsing (predictive parsing)
Top down Parsing - LL(1) parsing (predictive parsing)
Rules to construct predictive parsing table:
1. For each production 𝐴 → 𝛼 of the grammar, do steps 2 and 3.
2. For each terminal 𝑎 in 𝑓𝑖𝑟𝑠𝑡(𝛼), Add 𝐴 → 𝛼 to 𝑀[𝐴, 𝑎].
3. If 𝜖 is in 𝑓𝑖𝑟𝑠𝑡(𝛼), Add 𝐴 → 𝛼 to 𝑀[𝐴, 𝑏] for each terminal 𝑏
in 𝐹𝑂𝐿𝐿𝑂𝑊(𝐵). If 𝜖 is in 𝑓𝑖𝑟𝑠𝑡(𝛼), and $ is in
𝐹𝑂𝐿𝐿𝑂𝑊(𝐴), add 𝐴 → 𝛼 to 𝑀[𝐴, $].
4. Make each undefined entry of M be error.
Example - LL(1) parsing
Example - LL(1) parsing
Example - LL(1) parsing
Example - LL(1) parsing
Top down Parsing - Recursive Descent Parsing
• Recursive descent parser executes a set of recursive procedure
to process the input without backtracking.
– There is a procedure for each non terminal in the grammar.
– Consider RHS of any production rule as definition of the
procedure.
– As it reads expected input symbol, it advances input pointer to next
position.
Example - Recursive Descent Parsing
Bottom up parsing
Bottom up parsing - SHIFT-REDUCE PARSING
Shift-reduce parsing is a type of bottom-up parsing that
attempts to construct a parse tree for an input string beginning
at the leaves and working up towards the root.
Example: Consider the grammar:
S → aABe
A → Abc | b
B→d
Bottom up parsing - SHIFT-REDUCE PARSING
Handles:
– A handle of a string is a substring that matches the right side of a production, and whose reduction to the
non-terminal on the left side of the production represents one step along the reverse of a rightmost
derivation.
– Example: Consider the grammar:
E → E+E
E → E*E
E → (E)
E → id
And the input string id1+id2*id3
The rightmost derivation is :
E → E+E
→ E+E*E
→ E+E*id3
→ E+id2*id3
→ id1+id2*id3
In the above derivation the underlined substrings are called handles.
Bottom up parsing - SHIFT-REDUCE PARSING
Actions in shift-reduce parser:
– shift – The next input symbol is shifted onto the top of the stack.
– reduce – The parser replaces the handle within a stack with a
non-terminal.
– accept – The parser announces successful completion of parsing.
– error – The parser discovers that a syntax error has occurred
and calls an error recovery routine.
Bottom up parsing
Bottom up parsing- LR Parsing Approach:
• Build Tables (Algorithm to follow)
– Each table entry will have one action (SHIFT, REDUCE, ACCEPT, or ERROR)
• Failure when building the tables? Some entry has multiple actions!
– The grammar is not LR
• LR Grammars are unambiguous
– Only one rightmost derivation
– There is only one handle at each step.
Bottom up parsing -
Bottom up parsing –LR parsing
Bottom up parsing –LR parsing
Bottom up parsing - OPERATOR-PRECEDENCE PARSING
The operator-precedence parser is a shift –reduce parser that can be easily
constructed by hand.
Operator precedence parser can be constructed from a grammar called
Operator-grammar.
These grammars have the property that
no production on right side is ε
And no production right side has two adjacent nonterminal.
Example: Consider the grammar:
E → EAE | (E) | -E | id
A→+|-|*|/|↑
Since the right side EAE has three consecutive non-terminals, the grammar
can be written as follows: E → E+E | E-E | E*E | E/E | E↑E | -E |
id
Bottom up parsing - Operator-precedence Parsing
Operator-precedence relation:
In operator-precedence parsing, there are three disjoint precedence
relations namely:
<• - less than
=• - equal to
•> - greater than
The relations give the following meanings:
Bottom up parsing - Operator-precedence Parsing
Example: Operator-precedence relations for the grammar
E → E+E | E-E | E*E | E/E | E↑E | (E) | -E | id , is given in the following
table
assuming
1. ^ is of highest precedence and right-associative
2. * and / are of next higher precedence and left-associative, and
3. + and - are of lowest precedence and left-associative
Note that the X in the table denote error entries
Syntax Error Handling
Most programming language specifications do not describe how a
compiler should respond to errors
Planning the error handling right from the start can both
– simplify the structure of a compiler and improve its handling of
errors.
Error handler goals:
– Report the presence of errors clearly and accurately
– Recover from each error quickly enough to detect subsequent errors
– Add minimal overhead to the processing of correct programs
Syntax Error Handling
• A good compiler should assist in identifying and locating errors
1) Lexical errors: occurs when the compiler does not recognize a sequence of characters
as a proper lexical token.
– Exceeding length of identifier or numeric constants.
– The appearance of illegal characters
– Unmatched string,(such as 2ab is not a valid C token)
– Example : printf("Geeksforgeeks");$
2) Syntax errors: misplaced semicolons, extra or missing braces; that is, " { " or " } "
Example : swich(ch)
• Typical syntax errors are: {
– Errors in structure .......
– Missing operator .......
– Misspelled keywords }
– Unbalanced parenthesis The keyword switch is incorrectly written as a
swich. Hence, an “Unidentified keyword/
• Example - int 2; identifier” error occurs.
Syntax Error Handling
3) Semantic errors: type mismatches between operators and
operands.
• Typical semantic errors are
– Incompatible type of operands
– Undeclared variables
– Not matching of actual arguments with a formal one
4) Logical errors: hard or impossible to detect.
– In c programming use assignment operator = instead of the
comparison operator ==.
Error Recovery Strategies-
1) Panic mode
– Discard input until a token in a set of designated synchronizing tokens
is found.
– On discovering an error, the parser discards input symbols one at a
time until semicolon or end.
– It has the advantage of simplicity and does not go into an infinite loop.
– When multiple errors in the same statement are rare, this method is
quite useful.
• Example: In case of an error like: a=b + c // no semi-colon
d=e + f ;
2) Phrase-level recovery
– Perform local correction on the input to repair the error.
– Example: Insert a missing semicolon or delete an extraneous semicolon.
Error Recovery Strategies-
3) Error productions
– The parser is constructed using augmented grammar with error
productions.
– If an error production is used by the parser, appropriate error diagnostics
can be generated to indicate the erroneous constructs recognized by the
input.
– Example – write 5X instead of 5*X.
Error Recovery Strategies-
4) Global correction
– Choose a minimal sequence of changes to obtain a global least-cost
correction.
– Given an incorrect input string x and grammar G, certain algorithms
can be used to find a parse tree for a string y, such that the number of
insertions, deletions and changes of tokens is as small as possible.
– However, these methods are in general too costly in terms of time and
space.
Exercises
Question : Consider the following statements about the context free grammar
G = {S -> SS, S -> ab, S -> ba, S -> ?}
I. G is ambiguous
II. G produces all strings with equal number of a’s and b’s
III. G can be accepted by a deterministic PDA
Which combination below expresses all the true statements about G?
A. I only
B. I and III only
C. II and III only
D. I, II and III
Exercises
Solution : There are different LMD’s for string abab which can be
S => SS => SSS => abSS => ababS => abab
S => SS => abS => abab, So the grammar is ambiguous. Therefore statement I is true.
Statement II states that the grammar G produces all strings with equal number of a’s and b’s but it
can’t generate aabb string. So statement II is incorrect.
Statement III is also correct as it can be accepted by deterministic PDA. So correct option is (B).
Question : Which one of the following statements is FALSE?
A. There exist context-free languages such that all the context-free grammars generating
them are ambiguous.
B. An unambiguous context free grammar always has a unique parse tree for each string of
the language generated by it.
C. Both deterministic and non-deterministic pushdown automata always accept the same set
of languages.
D. A finite set of string from one alphabet is always a regular language.
Exercises
Solution : (A) is correct because for ambiguous CFL’s, all CFG corresponding to it are
ambiguous.
(B) is also correct as unambiguous CFG has a unique parse tree for each string of the
language generated by it.
(C) is false as some languages are accepted by Non – deterministic PDA but not by
deterministic PDA.
(D) is also true as finite set of string is always regular.
So option (C) is correct option.