miércoles, 18 de mayo de 2011

UNIDAD 7: MANEJO DE ERRORES


UNIDAD 7 MANEJO DE ERRORES

¡¡Los programas no siempre son correctos!!

Un compilador es un sistema que en la mayoría de los casos tiene que manejar una entrada incorrecta. Sobre todo en las primeras etapas de la creación de un programa, es probable que el compilador se utilizará para efectuar las características que debería proporcionar un buen sistema de edición dirigido por la sintaxis, es decir, para determinar si las variables han sido declaradas antes de usarla, o si faltan corchetes o algo así. Por lo tanto, el manejo de errores es parte importante de un compilador y el escritor del compilador siempre debe tener esto presente durante su diseño.

 Hay que señalar que los posibles errores ya deben estar considerados al diseñar un lenguaje de programación. Por ejemplo, considerar si cada proposición del lenguaje de programación comienza con una palabra clave diferente (excepto la proposición de asignación, por supuesto). Sin embargo, es indispensable lo siguiente:


El compilador debe ser capaz de detectar errores en la entrada;

·         El compilador debe recuperarse de los errores sin perder demasiada información;

·         Y sobre todo, el compilador debe producir un mensaje de error que permita al programador encontrar y corregir fácilmente los elementos (sintácticamente) incorrectos de su programa.





7.1 Tipos de Errores

¢  Léxicos
¢  Sintácticos
¢  Semánticos
¢  Lógicos











Errores léxicos

Los errores léxicos se detectan cuando el analizador léxico intenta reconocer componentes léxicos en el código fuente.


Errores sintácticos

Un error de sintaxis se detecta cuando el analizador sintáctico espera un símbolo que no corresponde al que se acaba de leer. Los analizadores sintácticos LL y LR tienen la ventaja de que pueden detectar errores sintácticos lo más pronto posible, es decir, se genera un mensaje de error en cuanto el símbolo analizado no sigue la secuencia de los símbolos analizados hasta ese momento.


Error semántico

Los errores semánticos corresponden a la semántica del lenguaje de programación, la cual normalmente no está descrita por la gramática. Los errores semánticos más comunes son la omisión de declaraciones.



Errores Lógicos

 Los comete el programador
 Ejemplo: una llamada infinitamente recursiva




















7.2 Tratamiento de los errores léxicos

TRATAMIENTO DE LOS ERRORES LEXICOS
Un traductor debe adoptar alguna estrategia para detectar, informar y recuperarse para seguir analizando hasta el final.
Las respuestas ante el error pueden ser:
·         Inaceptables: Provocadas por fallos del traductor, entrada en lazos infinitos, producir resultados erróneos, y detectar sólo el primer error y detenerse.
·         Aceptables: Evitarla avalancha de errores (mala recuperación) y, aunque más complejo, informar y reparar el error de forma automática. La conducta de un Analizador de Léxico es el de un Autómata finito o “scanner”.
·         Detección del error: El analizador de Léxico detecta un error cuando no existe transición desde el estado que se encuentra con el símbolo de la entrada. El símbolo en la entrada no es el esperado.

Los errores léxicos se detectan cuando el analizador léxico intenta reconocer componentes léxicos y la cadena de caracteres de la entrada no encaja con ningún patrón. Son situaciones en las que usa un carácter invalido (@,$,",>,...), que no pertenece al vocabulario del lenguaje de programación, al escribir mal un identificador, palabra reservada u operador.

Errores léxicos típicos son:
·         Nombre ilegales de identificadores: un nombre contiene caracteres inválidos.
·         Números incorrectos: Un numero contiene caracteres inválidos o no está formado correctamente, por ejemplo 3,14 en vez de 3.14 o 0.3.14.
·         Errores de ortografía en palabras reservadas: caracteres omitidos, adicionales o cambiados de sitio, por ejemplo la palabra while en vez de hwile.
·         Fin de archivo: se detecta un fin de archivo a la mitad de un componente léxico.

Los errores léxicos se deben a descuidos del programador. En general, la recuperación de errores léxicos es sencilla y siempre se traduce en la generación de un error de sintaxis que será detectado más tarde por el analizador sintáctico cuando el analizador léxico devuelve un componente léxico que el analizador sintáctico no espera en esa posición.
Los métodos de recuperación de errores léxicos se basan bien en saltarse caracteres en la entrada hasta que un patrón se ha podido reconocer; o bien usar otros métodos más sofisticados que incluyen la inserción, borrado, sustitución de un carácter en la entrada o intercambio de dos caracteres consecutivos.
 Una buena estrategia para la recuperación de errores léxicos:
Universidad Nacional del Santa Curso: Teoría de Compiladores
·         Si en el momento de detectar el error ya hemos pasado por algún estado final ejecutamos la acción correspondiente al último estado final visitado con el lexema formado hasta que salimos de él; el resto de caracteres leídos se devuelven al flujo de entrada y se vuelve al estado inicial;

·         Si no hemos pasado por ningún estado final, advertimos que el carácter encontrado no se esperaba, lo eliminamos y proseguimos con el análisis.
TRATAMIENTO DE LOS ERRORES SINTACTICOS


7.3 Tratamiento de errores sintácticos

Muchos errores de naturaleza sintáctica Recuperación: Al producirse un error el compilador debe ser capaz de informar del error y seguir compilando. (Ideal)
El manejo de errores de sintaxis es el más complicado desde el punto de vista de la creación de compiladores. Nos interesa que cuando el compilador encuentre un error, se recupere y siga buscando errores. Por lo tanto el manejador de errores de un analizador sintáctico debe tener como objetivos:

·         Indicar los errores de forma clara y precisa. Aclarar el tipo de error y su localización.
·         Recuperarse del error, para poder seguir examinando la entrada.
·         No ralentizar significativamente la compilación.

Un buen compilador debe hacerse siempre teniendo también en mente los errores que se  pueden producir; con ello se consigue:

·         Simplificar la estructura del compilador.
·         Mejorar la respuesta ante los errores.

Tenemos varias estrategias para corregir errores, una vez detectados:


Ignorar el problema (Panicmode)

Consiste en ignorar el resto de la entrada hasta llegar a una condición de seguridad.
Una condición tal se produce cuando nos encontramos un token especial (por ejemplo un ‘;’ o un ‘END’). A partir de este punto se sigue analizando normalmente.

Recuperación a nivel de frase

Intenta recuperar el error una vez descubierto. En el caso anterior, por ejemplo, podría haber sido lo suficientemente inteligente como para insertar el token ‘;’. Hay que tener cuidado con este método, pues puede dar lugar a recuperaciones infinitas.




Reglas de producción adicionales para el control de errores

La gramática se puede aumentar con las reglas que reconocen los errores más comunes. En el caso anterior, se podría haber puesto algo como:
sent_erróne a Ú sent_sin_acabar sentencia_acabada ’;’
sentencia_acabada Ú sentencia ‘;’
sent_sin_acabar Ú sentencia
Lo cual nos da mayor control en ciertas circunstancias


Corrección Global

Dada una secuencia completa de tokens a ser reconocida, si hay algún error por el que no se puede reconocer, consiste en encontrar la secuencia completa más
parecida que sí se pueda reconocer. Es decir, el analizador sintáctico le pide toda la secuencia de tokens al léxico, y lo que hace es devolver lo más parecido a la cadena de entrada pero sin errores, así como el árbol que lo reconoce.


7.4 Tratamiento errores semánticos

Comprobacion de tipos

Aspectos generales

Un lenguaje con comprobación fuerte de tipos es capaz de garantizar que los programas se pueden ejecutar sin errores de tipo, por lo que los errores de tipo se detectarán siempre en tiempo de compilación.
Como mínimo, ante un error, un comprobador de tipos debe informar de la naturaleza y posición del error y recuperarse para continuar con la comprobación del resto del programa a analizar.

Veamos algunas de las operaciones a tener en cuenta en una comprobación de tipos:
·         Conversión de tipos: A veces es necesario transformar el tipo de una expresión para utilizar correctamente un operador o para pasar de forma adecuada un parámetro a una función.
·         Coerción: Es una conversión de tipos que realiza de forma implícita el propio compilador. Si es el programador el que realiza la conversión se tratará entonces de una conversión explícita.
·         Sobrecarga de operadores: La sobrecarga se resuelve determinando el tipo de cada una de las expresiones intervinientes en la sobrecarga.
·         Funciones polimórficas: Son aquellas que trabajan con argumentos cuyo tipo puede cambiaren distintas llamadas a la función.


Especificación de un comprobador de tipos básico

Básicamente se deberán realizar dos tareas:
a)    Asignación de tipos: en las declaraciones.
b)    Evaluación y comprobación de tipos: En las expresiones y en las funciones, así como en las sentencias.



Otras comprobaciones semánticas y recuperación de errores semánticos

Dentro de las comprobaciones estáticas (en el momento de la compilación), tenemos la detección e información de errores como:

·         Comprobaciones de tipos: operadores aplicados a operandos incompatibles, asignación de tipos incompatibles, llamadas a funciones con tipos no adecuados, etc.
·         Comprobaciones de flujo de control: las sentencias que hacen que el flujo de control abandone una construcción debe tener alg ´un lugar a donde transmitir el control. Por ejemplo: Unbreak debe estar dentro de una proposición while,  for o switch en C.
·         Comprobaciones de unicidad: situaciones en las que solo se puede definir un objeto una vez exactamente. Por ejemplo: Un identificador, las etiquetas case dentro de un switch.

Solo nos hemos centrado en las comprobaciones de tipo. Las otras son e  cierto modo rutinarias y se pueden realizar fácilmente insertando acciones intercaladas en el código para realizarlas, por eje. Cuando se introduce un identificador en la Tabla de Símbolos.

1 comentario:

Vistas a la página totales