Contenido
•
Introducción
•
Análisis léxico
•
Funciones del analizador léxico
•
Tokens y lexemas
•
Palabras reservadas
•
Estrategias de recuperación de errores léxicos
Introducción
Para la construcción de todo traductor, compilador o interprete, es necesario analizar el texto de entrada de manera eficiente.
En el ámbito de compiladores, el análisis léxico es la parte que tiene contacto directo con el código fuente, el analizador léxico hace las funciones, a la vez, de preprocesador y de scanner o lexer.
Análisis léxico
• La función principal del analizador léxico consiste en
leer los caracteres de entrada y elaborar como
salida una secuencia de componentes léxicos que utiliza el analizador sintáctico para hacer el análisis.
• Esta interacción, suele aplicarse convirtiendo al analizador léxico en una subrutina o corrutina del analizador sintáctico.
• Recibida la orden “Dame el siguiente componente léxico” del analizador sintáctico, el analizador léxico lee los caracteres de entrada hasta que pueda identificar el siguiente componente léxico.
Análisis Léxico
Analizador léxico Analizador Sintáctico Tabla de símbolos Programa Fuente Al análisis semántico token ObtenerSiguiente TokenInteracciones entre el analizador léxico y el analizador sintáctico
Funciones del analizador léxico
1. Eliminar o saltar comentarios, espacios en blanco, tabuladores, retorno de carro, ..., y en general, todo aquello que carezca de significado según la sintaxis del lenguaje. (Preprocesamiento).
2. Reconocer los tokens: identificadores del usuario, números, palabras reservadas del lenguaje, ..., y tratarlos correctamente con respecto a la tabla de símbolos (solo en los casos que debe de tratar con la
tabla de símbolos).
Para reconocer el token usa un patrón o regla que describe como se forman las cadenas que corresponden a un token.
Funciones del analizador léxico
3. Llevar la cuenta del número de línea por la que
va leyendo, por si se produce algún error, dar información sobre donde se ha producido.
4. Avisar de errores léxicos. P.g., si @ no
pertenece al lenguaje, avisar de un error, es posible que recupere el error. *No se encuentre el
patrón
5. Puede hacer funciones de preprocesador.
Tokens y lexemas
•
Token:
• Elemento básico del lenguaje
• Unidad léxica indivisible
• Identifica una entidad lógica dentro del lenguaje
• Incluyen: Palabras Reservadas, Constantes, Operadores, Signos de
Puntuación e Identificadores
•
Lexema:
• La cadena original que se identifica como token
• No hay correspondencia 1-1 entre token-lexema
Palabras Reservadas
• Una palabra reservada es aquella que inicia con una letra, y es seguida por letras o dígitos.
• Las palabras clave cumplen con este mismo patrón de construcción por lo tanto.
• Se hace necesario un mecanismo que permita decidir cuando una
cadena es una palabra clave o un identificador
• Solución sencilla: Las palabras reservadas no pueden ser usadas como
errores léxicos
• Modo Pánico: obvia los siguientes caracteres de la
entrada hasta encontrar un token bien formado.
• Tratar de Arreglar la entrada:
• Borrar el carácter extraño • Insertar el carácter perdido
• Reemplazar un carácter incorrecto por uno correcto
• Encontrar que cambio genera el menor numero de errores sintácticos, y aplicarlo
Manejo de búferes
• El manejo de búferes tiene la intención de mejorar el rendimiento de esta primera fase donde se hace necesario el acceso al archivo con el código fuente de entrada.
• El estar continuamente accediendo a llamadas del sistema que operan con archivos, no siempre es eficiente. Es bien conocido que el realizar una transferencia previa de la información de un archivo a memoria, permitirá obtener una mayor eficiencia a la hora de procesar dicha información.
Manejo de búferes
• Cuando se implementa analizador léxico se hace necesario manejar un búfer de entrada para hacer mas eficiente la lectura de la cadena de entrada y así evitar la sobrecarga requerida en el procesamiento de un solo carácter de entrada.
Manejo de búferes
• Generalmente se define un búfer del tamaño de un
bloque de disco (4096 bytes).
• Se maneja un apuntador que marca el inicio del
lexema que se esta analizando, y un apuntador que
marca el carácter que esta siendo analizado.
v e l = d i s / t i
inicioLexema
…
avance
Manejo de búferes
• Existen ocasiones en que es necesario buscar uno o más caracteres más allá del siguiente lexema para poder estar seguros de que tenemos el lexema correcto.
• P.g. en C los caracteres -, = o < podrán ser un operador o el principio de otros ->, == o <=.
Manejo de búferes
v e l = d i s / t i inicioLexema … avance PosibilidadesUn búfer Final del buffer
Par de búferes
v e l = d
Manejo de búferes
v e l = d i s EOF inicioLexema … avance Centinelas Final del bufferEs un carácter especial que no puede formar parte del programa fuente. (P.g. EOF) .
v e l = EOF
= … d … / t i e ;
inicioLexema avance Entonces EOF significa:
Se llego al final del 1er búfer y debe ser cargado el segundo.
Se llego al final del 2do búfer y debe ser cargado el primero
Implementación del algoritmo
• Se construyen dos buffers, cada búfer de tamaño N, por lo general de un bloque de disco (4096 bytes). Mediante un comando de lectura del sistema podemos leer N caracteres y colocarlos en el buffer, en vez de utilizar una llamada al sistema por cada carácter. Si quedan menos de N caracteres en el archivo de entrada, entonces se coloca un EOF, marcando el final del archivo fuente.
• Se mantienen dos apuntadores a la entrada:
• El apuntador inicioLexema marca el inicio del lexema actual, cuya extensión se está tratando de determinar.
Implementación del algoritmo
• Una vez que se determina el siguiente lexema,
avance se coloca en el carácter que se encuentra en
su extremo derecho. Después una vez que el lexema se registra como un valor de atributo de un token devuelto al analizador sintáctico, inicioLexema se coloca en el carácter que va justo después del lexema que acabamos de encontrar.
Implementación del algoritmo
• Para desplazar avance hacia adelante primero tenemos que probar si hemos llegado al final de uno de los dos búferes, y de ser así, debemos recargar el otro búfer de la entrada, y mover avance al principio del búfer recién cargado. Siempre y cuando no tengamos que alejarnos tanto del lexema como para que la suma de su longitud más la distancia que nos alejamos sea mayor que N (Evitar sobrescribir el lexema en su búfer antes de poder determinarlo).