Professional Documents
Culture Documents
Compiler Design
Compiler Design
ERROR RECOVERY
One of the important tasks that a compiler must perform is the detection of and recovery
from errors. Recovery from errors is important, because the compiler will be scanning and
compiling the entire program, perhaps in the presence of errors; so as many errors as
possible need to be detected . After detecting an error, the first thing that a compiler is
supposed to do is to report the error by producing a suitable diagnostic. A good error
diagnostic should possess the following properties.
a. The message should be produced in terms of the original source program
rather than in terms of some internal representation of the source program.
b. The error message should be easy to understand by the user .
c. The error message should be specific and should localize the problem.
id
E
1
Accept
S 3/ R
S 4/ R
S 3/ R
S 4/ R
5
6
The conflict is resolved by giving higher precedence to * and using left associativity, as
shown in Table 2.
id
E
1
Accept
5
6
The parsing table with error routines is shown in Table 3, where routine e 1 is called from
states I , I 3 , and I 4 , which pushes an imaginary id onto the stack and covers it with state I 2 .
The routine e 2 is called from state I 1 , which pushes + onto stack and covers it with state I 3 .
id
Accept
5
6
$I
$ I id I
$ I EI
$ I EI 1 + I
$ I EI 1 + I 3 id I
Unspent Input
Moves
id+*id$
+*id$
+*id$
*id$
*id$
*id$
id$
Accept
(id I 2 pushed by e 1)
$ I EI 1 + I 3 EI
$ I EI 1 + I 3 E I 5 * I
$ I EI 1 + I 3 E I 5 * I 4 id I
$ I EI 1 + I 3 E I 5 * I 4 EI
$ I EI 1 + I 3 EI
$ I EI
Similarly, if we trace the behavior of the parser for the input id id*id $:
Stack Contents
$I
$ I id I
$ I EI
Unspent Input
Moves
id id*id$
id*id$
id*id$
Stack Contents
$ I EI 1 + I
Unspent Input
Moves
id*id$
*id$
*id$
id$
Accept
( I 3 pushed by e 2)
$ I EI 1 + I 3 id I
$ I EI 1 + I 3 EI
$ I EI 1 + I 3 EI 5 * I
$ I EI 1 + I 3 EI 5 * I 4 id I
$ I EI 1 + I 3 EI 5 * I 4 EI
$ I EI 1 + I 3 EI
$ I EI
Another method of error recovery that can be implemented is called "phrase level recovery".
In phrase level recovery, each error entry in the LL parsing table is examined, and based on
language usage, an appropriate error-recovery procedure is constructed
A phrase level error-recovery implementation for an LL parser is shown in Tables 4 and 5.
The parsing table is constructed for the following grammar:
Id
E TE
T FT
F id
T 1
id
+ TE
T 1 * FT
E 1
T 1
pop
Pop
Pop
Accept
E TE
T FT
F id
F
E
E 1
T 1
T 1
id
+
*
+ TE
E 1
T 1 * FT
pop
Pop
Pop
E 1
T 1
Accept
Unspent Input
Moves
$E
id+*id$
derive using E TE
$ E 1T
id+*id$
derive using T FT
$ E 1T 1F
id+*id$
derive using F id
$ E 1 T 1 id
id+*id$
Pop
$ E 1T
+*id$
derive using T 1
+*id$
derive using E 1 + TE
$ E 1T +
+*id$
Pop
$ E 1T
*id$
$ E 1T
id*id$
derive using T FT
$E
(imaginary id is pushed by e 1 )
$ E 1T 1F
id*id$
derive using F id
$ E 1 T 1 id
id*id$
Pop
$ E 1T
*id$
derive using T 1 * FT
$ E 1T 1F
id$
derive using F id
$ E 1 T 1 id
id$
Pop
$ E 1T
derive using T
Stack Contents
$E
Unspent Input
Moves
derive using E 1
Accept
Unspent Input
Moves
$E
id id*id$
derive using E TE
$ E 1T
id+*id$
derive using T FT
$ E 1T 1F
id+*id$
derive using F id
$ E 1 T 1 id
id+*id$
Pop
$ E 1T
id*id$
derive using T 1
id*id$
derive using E 1
id*id$
Accept
$E
(id*id$ is removed by e 2 )
$