Resumen: Semana del 24 al 31 de abril
(1/8)
(f)lex y los autómatas finitos
- (f)lex es un programa cuya función es generar parsers, es decir, programas de análisis léxico
- Para funcionar, (f)lex hace un uso intensivo de los autómatas finitos
(2/8)
(f)lex y los autómatas finitos no deterministas
- Primero, las reglas de traducción son convertidas en autómatas finitos no deterministas
- Los AFN son computacionalmente más sencillos de crear que los AFD, y pueden convertirse en AFD posteriormente, por lo que se usan como primer paso para traducir las reglas
(3/8)
(f)lex y los autómatas finitos deterministas
- Las reglas de traducción, ya convertidas a un AFN, son posteriormente convertidas en un AFD
- Como se vio antes, los AFD eliminan la ambigüedad de los AFN, lo que permite generar un programa con tiempo de ejecución finito
- Las reglas de conversión de AFN a AFD se vieron en estas lecciones
(4/8)
(f)lex y la compactación de autómatas finitos deterministas
- Ya con un AFD, se puede reducir aun más el tamaño de este mediante algoritmos de minimización
- Minimizar el AFD reduce la redundancia, así como el tamaño del programa resultante
- Al igual que la anterior, las reglas de minimización de AFD se vieron en estas lecciones
(5/8)
El siguiente tema: recursividad
- La recursividad en una gramática consiste en sustituir una regla gramatical, en todo o en parte, por sí misma
- Un ejemplo de recursividad es la gramática para XML vista en estas lecciones
- Si se tiene que A es una regla gramatical, y x un conjunto de terminales y no terminales que no empiezan con A, la recursividad puede ser:
- Hacia la izquierda, cuando se tiene una forma A → A x
- Hacia la derecha, cuando se tiene una forma A → x A
(6/8)
Recursividad izquierda (LL): caso inmediato
- La recursividad izquierda se da a menudo en casos inmediatos; es decir, cuando la regla se repite directamente en sí misma
- Para resolver un caso A → A α | β donde α, β son conjuntos de terminales y no terminales que no empiezan con A, se reemplaza por lo siguiente:
- A → β A'
- A' → α A' | ε (terminación épsilon)
(7/8)
Recursividad izquierda (LL): caso inmediato generalizado
- Este procedimiento puede generalizarse para una cantidad indeterminada de terminales y no terminales
- Si se tiene una lista de producciones A → A α1 | α2 | (...) | αn | β1 | β2 | (...) | βm, se pueden sustituir por lo siguiente:
- A → β1 A' | β2 A' | (...) | βm A'
- A' → α1 A' | α2 A' | (...) | αn A'| ε
(8/8)
Recursividad izquierda (LL): algoritmo general
- El procedimiento anterior no funciona si se tienen recursiones no inmediatas (es decir, es hasta que se hace un número de sustituciones que se nota la recursión inmediata)
- Para eliminar la recursividad en forma generalizada, se tiene un algoritmo que tiene por entrada una gramática sin ciclos ni producciones épsilon, y de ella se obtiene una gramática con la misma función, pero ahora sí sin recursividad por la izquierda (aunque puede haber recursividad por la derecha, y usualmente así es)
- El algoritmo es el siguiente:
- Ordenar los no terminales de A1 a An
- De i = 1 a n
- De j = 1 a 1 - i
- Cambiar cada Ai → Ajγ por todas las producciones de Aj: Ai → δ1γ | δ2γ | (...) | δkγ
- Eliminar la recursividad inmediata por la izquierda para todas las producciones Ai, como se vio arriba
- De j = 1 a 1 - i