 
 
 
 
 
 
 
 
 
 










 
yapp proporciona un token especial,
error, que puede ser utilizado en el programa fuente
para extender el traductor con ``producciones de error'' 
que lo doten de cierta capacidad para 
recuperase de  una entrada errónea y poder continuar 
analizando el resto de la entrada.
Consideremos lo que ocurre al ejecutar nuestra calculadora
yapp con una entrada errónea. Recordemos 
la gramática:
 9  %right  '='
10  %left   '-' '+'
11  %left   '*' '/'
12  %left   NEG
13  %right  '^'
14
15  %%
16  input:  # empty
17          |   input line  { push(@{$_[1]},$_[2]); $_[1] }
18  ;
19
20  line:       '\n'       { $_[1] }
21          |   exp '\n'   { print "$_[1]\n" }
22          |   error '\n' { $_[0]->YYErrok }
23  ;
La regla line 
 
 error '\n' es una producción de
error. La idea general de uso es que, a traves de la misma, el programador 
le indica a yapp que, cuando se produce un error
dentro de una expresión, descarte todos los tokens hasta llegar al
retorno del carro y prosiga con el análisis. 
Además, mediante la llamada al método YYErrok el programador
anuncia que, si se alcanza este punto, la recuperación puede considerarse 
``completa''  y que yapp puede emitir a partir de ese momento 
mensajes de error
con la seguridad de que no son consecuencia de un comportamiento inestable
provocado por el primer error.
El resto de la gramática de la calculadora era como sigue:
24
25  exp:        NUM
26          |   VAR                 { $_[0]->YYData->{VARS}{$_[1]} }
27          |   VAR '=' exp         { $_[0]->YYData->{VARS}{$_[1]}=$_[3] }
28          |   exp '+' exp         { $_[1] + $_[3] }
29          |   exp '-' exp         { $_[1] - $_[3] }
30          |   exp '*' exp         { $_[1] * $_[3] }
31          |   exp '/' exp         {
32                                    $_[3]
33                                    and return($_[1] / $_[3]);
34                                    $_[0]->YYData->{ERRMSG}
35                                      =   "Illegal division by zero.\n";
36                                    $_[0]->YYError;
37                                    undef
38                                  }
39          |   '-' exp %prec NEG   { -$_[2] }
40          |   exp '^' exp         { $_[1] ** $_[3] }
41          |   '(' exp ')'         { $_[2] }
42  ;
en la ejecución activamos el flag yydebug a 0x10 para 
obtener información sobre el tratamiento de errores:
$self->YYParse( yylex => \&_Lexer, yyerror => \&_Error, yydebug => 0x10 );Pasemos a darle una primera entrada errónea:
$ ./usecalc.pl 3-+2 Syntax error. **Entering Error recovery. **Pop state 12. **Pop state 3. **Shift $error token and go to state 9. **Dicard invalid token >+<. **Pop state 9. **Shift $error token and go to state 9. **Dicard invalid token >NUM<. **Pop state 9. **Shift $error token and go to state 9. **End of Error recovery.
El esquema general del algoritmo de recuperación de errores usado 
por la versión actual de yapp es el siguiente:
error.
error. 
En el ejemplo anterior el analizador estaba en el estado 12 y lo retira
de la pila. Los contenidos del estado 12 son:
	exp -> exp '-' . exp	(Rule 10)
	'('	shift 7 '-'	shift 2 NUM	shift 6 VAR	shift 8
	exp	go to state 21
Obviamente no esperabamos ver un '+' aqui. El siguiente
estado en la cima de la pila es el 3, el cual tampoco
tiene ninguna transición ante el terminal error:
line -> exp . '\n' (Rule 4) exp -> exp . '+' exp (Rule 9) exp -> exp . '-' exp (Rule 10) exp -> exp . '*' exp (Rule 11) exp -> exp . '/' exp (Rule 12) exp -> exp . '^' exp (Rule 14) '*' shift 17 '+' shift 13 '-' shift 12 '/' shift 15 '\n' shift 14 '^' shift 16El pop sobre el estado 3 deja expuesto en la superficie al estado 1, el cuál ``sabe'' como manejar el error:
	$start -> input . $end	(Rule 0)
	input -> input . line	(Rule 2)
	$end	shift 4 '('	shift 7 '-'	shift 2 '\n'	shift 5
	NUM	shift 6 VAR	shift 8
	error	shift 9
	exp	go to state 3
	line	go to state 10
error. 
En consecuencia, con lo dicho, en el ejemplo se va al estado 9:
line -> error . '\n' (Rule 5) '\n' shift, and go to state 20
**Dicard invalid token >+<. **Pop state 9. **Shift $error token and go to state 9. **Dicard invalid token >NUM<. **Pop state 9. **Shift $error token and go to state 9. **End of Error recovery.
 
 
 
 
 
 
 
 
 
 










