Compiladores Compiladores Tema 3 Tema 3 Análisis Lexicográfico Análisis Lexicográfico Scanners Scanners
Sc
Scanneranner
Scanner Scanner
(autómata finito determinista (autómata finito determinista
o específico) o específico) Programa fuente Programa fuente (secuencia de caracteres) (secuencia de caracteres) Secuencia de símbolos Secuencia de símbolos Categoría sintáctica: Categoría sintáctica: número, identificador
número, identificador, , if, sumif, suma, abrir paréntesisa, abrir paréntesis
Atributos: Atributos:
valor, nombre, string. valor, nombre, string.
Símbolo Símbolo
Ejemplos de Sí mbolos
Identificador:
± Forma: una letra seguida de letras o números. Ej. a, b1, c3D ± Atributo nombre: string con la secuencia de caracteres que
forma el identificador en mayúsculas. Ej. ³A´, ³B1´, ³C3D´
Número:
± Forma: secuencia de dígitos que puede empezar con el signo menos y puede contener un punto. Ej. 10, -3, 15.4, -54.276, .10 ± Atributo valor: double con el valor numérico.
± Precisión: entero o real.
Punto y Coma:
± Forma: ;
Palabra clave if:
± Forma: if, If, IF, iF
Fin de fichero:
Separación en Sí mbolos
Los comentarios, saltos de línea, espacios y tabs no forman parte de la secuencia de símbolos.
Al definir los símbolos se ha de considerar como se separan.
± Entre dos símbolos se encuentra cararcteres separadores (espacios, tabs, comentarios, etc.)
± Siempre se intenta leer el símbolo más largo Ejemplos: ± if ( a > 10 ) bc = 30 * - 4 ± if ( a >= 10 ) bc = 30 * - 4 ± int * * a ; ± zz /* comentario */ + dd
Especificación
Símbolos: identificador, abrir paréntesis, string, etc.
± Forma:
Expresiones regulares para cada categoría sintáctica.
± Atributos:
Algoritmo para el cálculo de cada atributo a partir de la secuencia de caracteres del
símbolo.
Separadores: espacios, comentarios, salto de línea, tab, etc.
± Forma:
Expresión regular que especifica las
secuencias de caracteres que separan los símbolos.
Expresiones Regulares
es una expresión regular que representa el conjunto vacío.
Pes una expresión regular que representa el conjunto con un único elemento que es la secuencia vacía
un string s es una expresión regular que
representa un conjunto que solo contiene s. Para evitar confusiones, los metacaracteres que contenga s van entre comillas (µ|¶,¶-¶,...).
V es el conjunto de todos los caracteres (vocabulario).
Expresiones Regulares Operadores AB Concatenación {ab| a A y b B} A|B unión {x| x A ó x B} A * repetición P`%`%%`%%% A + repetición de uno o más %`%%`%%% A n repetición de n veces (A-B) resta {x| x A y x B}
Ejemplos de Expresiones Regulares dígito d=0|1|2|3|4|5|6|7|8|9 entero_sin_signo=d + entero=(+|-| P)d+ real=d +.d+(P|e(+|-|P) d+) letra l=a|...|z|A...|Z identificador=l(l|d) * string=³(V-´) *´
Scanner implementado a mano
El scanner es un procedimiento que lee un símbolo del programa fuente
± Entrada: caracteres de un istream
istream *IScan; // Stream de entrada ± Salida: símbolo en variable global
enum Categoria {
SNumero,SIdentificador,SString, Sif... };
Categoria ScanCat; // Categorita sintáctica
double ScanEntero; // Valor numérico
double ScanReal; // Valor numérico
bool ScanEsEntero; // Tipo de número
string ScanString; // String del símbolo
Condiciones que cumple el scanner ± Lee caracteres hasta conseguir leer un
símbolo
± En caso de duda lee el símbolo más largo ± Al salir del scanner, el último carácter leído
pertenece al símbolo. Si se ha leído alguno más se devuelve a la entrada
Scanner en C++ void Scanner() { int c; for (;;) { c=IScan->get(); switch (c) { // Separadores case '\r': case '\n': case '\t': case ' ': break; default:
if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c=='_')) { ScanIdentificador(c);
return; }
else {
COut << "No se tratar el caracter " << (char) c << endl;
} } } }
Scanner de Identificadores en C++
void ScanIdentificador(int c) {
char buf[256]; int i;
for (i=0; (c>='a' && c<='z') || (c>='A' && c<='Z') || (c=='_') ||
(c>='0' && c<='9');) { if (i>254) {
throw CVException(³Identificador demasiado largo"); } buf[i++]=c; c=IScan->get(); } buf[i]='\0'; ScanCat=SIdentificador; ScanString=buf; IScan->putback(c); }
Autómatas Finitos
Autómata finito determinista (K,T,M,S,Z)
± K conjunto finito de estados.
± T conjunto de terminales (símbolos/caracteres de entrada).
± M:K vTpK función de transición. ± S K estado inicial.
± Z K conjunto de estados finales.
Autómata finito no determinista (K,T,M,S,Z)
Representación de los Autómatas Finitos 1 Estado Transición 1 Estado 1 inicial Estado final 1 2 3 4 a b d c
Acepta las secuencias: abc(dc)*
Paso de Expresión Regular a AFND a P Exp. a Exp. P Exp. A|B AFND de A AFND de B P P P P
Paso de Expresión Regular a AFND Exp. AB AFND de A AFND de B P P P
Paso de Expresión Regular a AFND Exp. A* AFND de A P P P P
Ejemplo del Paso de Exp. Regular a AFND Expresión: ab|ac* AFND: ab AFND: ac* P P P P Expresión: ab AFND: a AFND: b P P P
Ejemplo del Paso de Exp. Regular a AFND Expresión: ac* AFND: a AFND: c* P P P Expresión: a a Expresión: b b Expresión: c* AFND: c P P
Ejemplo del Paso de Exp. Regular a AFND a b Expresión: ab|ac* a 2 1 c 3 4 AFND Problema:
± Un a AFND puede seguir más de un camino durante su interpretación. Solución:
Paso de AFND a AFD
El conjunto de estados del nuevo AFD es el conjunto de las partes del conjunto de estados del AFND.
El estado inicial del AFD es el mismo que el del AFND.
Un estado del AFD es final si contiene algún estado final del AFND.
Cálculo del Con junto de Transiciones
Poner el estado inicial en el conjunto de estados K del AFD. El conjunto de
transiciones M=
Repetir hasta que K y M no varíen:
± Para cada estado de K y carácter de entrada aplicar las transiciones posibles del AFND y acumular en K y M el nuevo estado y la nueva transición.
Ejemplo del Paso de AFND a AFD a b Expresión: ab|ac* a 2 1 c 3 4 AFND I S F 1 a 2,4 2,4 b 3 2,4 c 4 4 c 4
Tabla de Transiciones AFD
b a 1 3 4 2,4 c AFD
Implementación de un AFD
Variable de estado S.
Tabla de transiciones T: dado un estado y un carácter de entrada específica el nuevo o error.
Algoritmo:
± S=estado inicial. ± Repetir
C=leer_caracter()
si T[S][C]==error entonces salir del bucle S=T[S][C]
Ejemplo de Tabla de Transiciones Tabla de Transiciones b a 1 c 3 4 c a b c 1 2 Err Err 2 Err 3 4
3 Err Err Err
4 Err Err 4
Scanner Basado en AFD
Un AFD no es un scanner. Falta
± Poder leer una secuencia de símbolos y separadores
± Diferenciar las categorías sintácticas de los símbolos
Consideraciones Prácticas
Las palabras reservadas se pueden
considerar como identificadores para evitar crear un AFD demasiado grande (2n
estados del AFND).
Hay que marcar el final del código fuente. Este indicador pertenecerá al alfabeto.
Los símbolos tienen atributos que hay que calcular.
Consideraciones Prácticas
Los estados finales del AFD se han de marcar con el símbolo que reconocen. Como hay que reconoce más de un
símbolo puede ser necesario tener que leer varios caracteres hacia delante.
La creación de un scanner se puede hacer directamente sin considerar los autómatas finitos.
Errores Lexicográficos
Tener un símbolo de error que se pasa al parser.
Señalar el error e ignorarlo. Tratamiento específico.
Falta información para corregir los errores lexicográficos.