Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
43 views

Chapter 4 Syntax Analysis

The document discusses syntax analysis in compiler design. It defines syntax analysis as the process where the syntax analyzer receives source code tokens from the lexical analyzer and performs parsing to create a tree-like representation of the code's grammatical structure. Context-free grammars are described as a tool for specifying programming language syntax precisely. The roles of the parser are discussed, including validating the token stream against the grammar and generating a syntax tree. Top-down and bottom-up parsing approaches are also mentioned.

Uploaded by

Yohannes Dereje
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views

Chapter 4 Syntax Analysis

The document discusses syntax analysis in compiler design. It defines syntax analysis as the process where the syntax analyzer receives source code tokens from the lexical analyzer and performs parsing to create a tree-like representation of the code's grammatical structure. Context-free grammars are described as a tool for specifying programming language syntax precisely. The roles of the parser are discussed, including validating the token stream against the grammar and generating a syntax tree. Top-down and bottom-up parsing approaches are also mentioned.

Uploaded by

Yohannes Dereje
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 90

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
Aa
B  bB
Bb
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: SS+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: SS+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.

You might also like