0% found this document useful (0 votes)
3 views24 pages

7 CD-PPT-4 Unit

The document discusses error recovery in compiler design, focusing on syntax errors and the importance of effective error handling. It outlines goals for error detection and reporting, various error recovery strategies such as panic mode, phrase level, error productions, and global correction, and emphasizes the need for quick recovery to detect subsequent errors. Additionally, it covers error recovery techniques in recursive descent and table-driven predictive parsers, including the use of skipErrors and parsing algorithms.

Uploaded by

anandbarot1350
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views24 pages

7 CD-PPT-4 Unit

The document discusses error recovery in compiler design, focusing on syntax errors and the importance of effective error handling. It outlines goals for error detection and reporting, various error recovery strategies such as panic mode, phrase level, error productions, and global correction, and emphasizes the need for quick recovery to detect subsequent errors. Additionally, it covers error recovery techniques in recursive descent and table-driven predictive parsers, including the use of skipErrors and parsing algorithms.

Uploaded by

anandbarot1350
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 24

1010043418

Compiler Design
Unit No 3: Error Recovery

SEMESTER: 7
PREPARED BY:
Syntax Error Recovery

• A syntax error happens when the stream of tokens


coming from the lexical analyzer does not comply with
the grammatical rules defining the programming
language.
• The next token in input is not expected according to the
syntactic definition of the language
• One of the main roles of a compiler is to identify
programming errors and give meaningful indications
about the location and nature of errors in the input
program.

2
2
Goals of Error Handling

• Detect all compile-time errors


• Report the presence of errors clearly and accurately
• Recover from each error quickly enough to be able
to detect subsequent errors
• Should not slow down the processing of correct
programs
• Beware of spurious errors that are just a
consequence of earlier errors
3
3
Reporting Errors

• Give the position of the error in the source file, maybe print the
offending line and point at the error location
• If the nature of the error is easily identifiable, give a meaningful
error message
• The compiler should not provide erroneous information about the
nature of errors
• If the error is easily correctable, a solution can be proposed or
applied by the compiler and a simple warning issued

4
4
Good Error Recovery

• Good error recovery highly depends on how quickly the error is


detected. Often, an error will be detected only after the faulty token
has passed. It will then be more difficult to achieve good error
reporting, as well as good error recovery.
• Should recover from each error quickly enough to be able to detect
subsequent errors. Error recovery should skip as less tokens as
possible.
• Should not identify more errors than there really is. Cascades of errors
should be avoided.
• Should give meaningful information about the errors, while avoiding to
give erroneous information.
• Error recovery should induce processing overhead only when errors
are encountered.
• Should not report errors that are consequences of the application of
error recovery, e.g. semantic errors.

5
5
Error Recovery Strategies

• There are many different strategies that a


parser can employ to recover from syntactic
errors.
• Although some are better than others, none of
these methods provide a universal solution.
– Panic mode, or don’t panic (Nicklaus Wirth)
– Phrase level
– Error productions
– Global correction

6
Error Recovery Strategies

• Panic Mode
– On discovering an error, the parser discards input
tokens until an element of a designated set of
synchronizing tokens is found. Synchronizing tokens
are typically delimiters such as semicolons or end of
block delimiters.
– Skipping tokens often has a side-effect of skipping
other errors. Choosing the right set of synchronizing
tokens is of prime importance.
– Simplest method to implement.
– Can be integrated in most parsing methods.
– Cannot enter an infinite loop.
7
7
Error Recovery Strategies

• Phrase Level
– On discovering an error, the parser performs a local
correction on the remaining input, e.g. replace a
comma by a semicolon, delete an extraneous
semicolon, insert a missing semicolon, etc.
– Replacements are done in specific contexts. There
are myriads of different such contexts.
– Cannot cope with errors that occurred before the
point of detection.
– Can enter an infinite loop, e.g. insertion of an
expected token.
8
8
Error Recovery Strategies

• Error Productions
– The grammar is augmented with “error”
productions. For each possible error, an error
production is added. An error is trapped when an
error production is used.
– Assumes that all kinds of errors are known in
advance.
– One error production is needed for each possible
error.
– Error productions are specific to the rules in the
grammar. A change in the grammar implies a
change of the corresponding error productions. 9
9

Error Recovery Strategies

• Global Correction
– Ideally, a compiler should make as few changes as
possible in processing an incorrect token stream.
– Global correction is about choosing the minimal sequence
of changes to obtain a least-cost correction.
– Given an incorrect input token stream x, such an algorithm
will find a parse tree for a related token stream y, such
that the number of insertions, deletions, and changes of
tokens required to transform x into y is as small as
possible.
– Too costly to implement.
– The closest correct program does not carry the meaning
intended by the programmer anyway.
– Joey
CanPaquet,
be used as2002,
2000, a benchmark for other error correction
2008, 2012, 2014
10
10
techniques.
Error Recovery in Recursive
Descent Predictive Parsers

• Two possible cases:


– The lookahead symbol or ε are not in FIRST(RHSs)
– The match() function is called in a no match
situation
• Solution:
– Create a skipErrors() function that skips tokens
until an element of FIRST(LHS) or FOLLOW(LHS) is
encountered
– Upon entering any production function, evaluate this
11
Joey Paquet, 2000, 2002, 2008, 2012, 2014 11
condition, and call skipErrors() if it is met.
skipErrors([FIRST],[FOLLOW])
if ( lookahead is in [FIRST ∪ FOLLOW] )

Cont.
return (true) // no error detected
else
write (“syntax error at “ lookahead.location)
while (lookahead not in [FIRST ∪ FOLLOW] )
lookahead = nextToken()
write (“parsing resumed at “ lookahead.location)
return (false) // error detected

match(token)
if ( lookahead == token )
lookahead = nextToken()
return (true)
else
write (“syntax error at” lookahead.location. “expected” token)
lookahead = nextToken()
return (false)

12
Joey Paquet, 2000, 2002, 2008, 2012, 2014 12
Constructing the Parser
LHS(){ // LHS→RHS1 | RHS2 | … | ε
success = skipErrors( FIRST(LHS),FOLLOW(LHS) )
if (lookahead ∈ FIRST(RHS1) )
if (non-terminals() ∧ match(terminals) )
write(“LHS→RHS1”)
else success = false
else if (lookahead ∈ FIRST(RHS2) )
if (non-terminals() ∧ match(terminals) )
write(“LHS→RHS2”)
else success = false
else if … // other right hand sides
else if (lookahead ∈ FOLLOW(LHS) ) // only if LHS→ε exists
write(“LHS→ε”)
else success = false
return (success)

13
Joey Paquet, 2000, 2002, 2008, 2012, 2014 13
Example
E(){
success = skipErrors([0,1,(],[),$])
if (lookahead is in [0,1,(]) //FIRST(TE')
if (T();E'();) write(E->TE')
else success = false
else success = false
return (success)
}

14
Joey Paquet, 2000, 2002, 2008, 2012, 2014 14
Example
E'(){
success = skipErrors([+],[),$])
if (lookahead is in [+]) //FIRST[+TE']
if (match('+');T();E'()) write(E'->TE')
else success = false
else if (lookahead is in [$,)] //FOLLOW[E'](epsilon)
write(E'->epsilon);
else success = false
return (success)
}

15
Joey Paquet, 2000, 2002, 2008, 2012, 2014 15
Example
T(){
success = skipErrors([0,1,(],[+,),$])
if (lookahead is in [0,1,(]) //FIRST[FT']
if (F();T'();) write(T->FT')
else success = false
else success = false
return (success)
}

16
Joey Paquet, 2000, 2002, 2008, 2012, 2014 16
Example
T'(){
success = skipErrors([*],[+,),$])
if (lookahead is in [*]) //FIRST[*FT']
if (match('*');F();T'()) write(T'->*FT')
else success = false
else if (lookahead is in [+,),$] //FOLLOW[T'] (epsilon)
write(T'->epsilon)
else success = false
return (success)
}

17
Joey Paquet, 2000, 2002, 2008, 2012, 2014 17
F(){
Example
success = skipErrors([0,1,(],[*,+,$,)])
if (lookahead is in [0]) //FIRST[0]
match('0') write(F->0)
else if (lookahead is in [1]) //FIRST[1]
match('1') write(F->1)
else if (lookahead is in [(]) //FIRST[(E)]
if (match('(');E();match(')')) write(F->1);
else success = false
else success = false
return (success)
}

18
Joey Paquet, 2000, 2002, 2008, 2012, 2014 18
Error Recovery in Table-Driven
Predictive Parsers

• All empty cells in the table represent


the occurrence of a syntax error
• Each case represents a specific kind of
error
• Task when an empty (error) cell is read:
– Recover from the error
• Either pop the stack or scan tokens
– Output an error message
19
Joey Paquet, 2000, 2002, 2008, 2012, 2014 19
Building the table with error
• Two possible cases: cases

skipError(){ // A is top()
write (“syntax error at “ lookahead.location)
if (lookahead is $ or in FOLLOW(A))
pop() // pop. equivalent to A → ε
else
lookahead = nextToken() // scan.
}

20
Joey Paquet, 2000, 2002, 2008, 2012, 2014 20
Original table, grammar and
r1:
r2:
E
E′


TE′
+TE′
sets
FST(E)
FST(E’)
:
:
{
{
0,1,( }
ε,+ }
FLW(E)
FLW(E’)
:
:
{
{
$,) }
$,) }
r3: E′ → ε FST(T) : { 0,1,( } FLW(T) : { +,$,) }
r4: T → FT′ FST(T’) : { ε,* } FLW(T’) : { +,$,) }
r5: T′ → *FT′ FST(F) : { 0,1,( } FLW(F) : { *,+,$,) }
r6: T′ → ε
r7: F → 0
r8: F → 1
r9: F → ( E )

0 1 ( ) + * $
E r1 r1 r1
E’ r3 r2 r3
T r4 r4 r4
T’ r6 r6 r5 r6
F r7 r8 r9
21
21
Parsing table with error actions
0 1 ( ) + * $
E r1 r1 r1 pop scan scan pop
E’ scan scan scan r3 r2 scan r3
T r4 r4 r4 pop pop scan pop
T’ scan scan scan r6 r6 r5 r6
F r7 r8 r9 pop pop pop pop

22
22
parse(){
push($)
Parser Algorithm push(S)
a = nextToken()
while ( stack ≠ $ ) do
x = top()
if ( x ∈ T )
if ( x == a )
pop(x) ; a = nextToken()
else
skipError() ; success = false
else
if ( TT[x,a] ≠ ‘error’ )
pop(x) ; inverseMultiplePush(TT[x,a])
else
skipError() ; success = false
if ( (a ≠ $) ∨ (success == false ) )
return(false)
else
return(true)}

23
23
Disambiguating Rules for Parsing Conflict

• Shift-reduce conflict
• Prefer shift over reduce
• In case of nested if statements, preferring shift over reduce
implies most closely nested rule for dangling else
• Reduce-reduce conflict
• Error in design

24

You might also like