PROGRAMA DE COMPILADORES 1. Introducción 1.1. Tipos de traductores 1.2. Autómatas 1.3. Gramáticas formales 1.4. Fases de un compilador 2. Análisis Léxico 2.1. Definir un reconocedor de cadenas no trivial 2.2. Programar sistemáticamente el reconocedor en lo referente a la obtención del autómata, almacenarlo eficientemente y manejar adecuadamente el archivo fuente 2.3. Utilería LEX 2.4. Notaciones y nomenclatura en LEX 2.5. Programación LEX del mismo reconocedor 2.6. Comparación de dos tipos de técnicas 3. Análisis Sintáctico 3.1. Parsers LR 3.2. Gramáticas LR 3.3. Métodos SLR, LR canónico, LARL 3.4. Construcción de tablas de análisis SLR, LR canónico y LARL 3.5. Manejo de gramáticas ambiguas 3.6. Recuperación de errores 3.7. Empleo de YACC 3.8. Notación de YACC 3.9. Manejo de errores en YACC 4. Problemas de Implementación 4.1. Estrategias de acceso a memoria. Técnicas de acceso dinámico 4.2. Acceso a nombres no locales, bloques, alcance 4.3. Paso de parámetros 4.4. Tablas de datos, hashing, representación del alcance. Diferentes tipos de tablas 5. Generación de Código Intermedio 5.1. Representaciones de código intermedio 5.2. Generación de código intermedio y análisis semántico en compilación top-down 5.3. Generación de código intermedio y análisis semántico en compilación bottom-up 5.4. Instrucciones de asignación. Expresiones booleanas. Instrucciones de control. Instrucciones de entrada y salida 6. Generación de Código 6.1. Aspectos generales de la generación de código. Manejo de memoria 6.2. Selección de instrucciones. Acceso de registros 6.3. Aspectos relacionados con la máquina anfitriona 6.4. Bloques básicos y gráficas de flujo 6.5. Gráficas dirigidas acíclicas 6.6. Algoritmos para generación de código 6.7. Generación de código en YACC 7. Optimización de Código 7.1. Optimización de código 7.2. Optimización de código intermedio 7.3. Fuentes principales de optimización. Subexpresiones comunes 7.4. Propagación de copias. Eliminación de código muerto. Ciclos 7.5. Optimización de bloques básicos 7.6. Ciclos de gráfica de flujo 7.7. Análisis de flujo de datos 8. Proyectos 8.1. Definición del proyecto 8.2. Análisis y diseño del compilador BIBLIOGRAFÍA 1. Compilers: Principles, Techniques and Tools. A.V. Aho, M.S. Lam, R. Sethi, J.D. Ullman. Addison-Wesley; 2nd edition (August 31, 2006) Se encuentra en las bibliotecas: FISMATIN-Xalapa y ECONOMIA-Xalapa. (QA76.76.C65 A36) 2. Compilers: Construction for Digital Computers D. Gries. Wiley International Edition. Se encuentra en las bibliotecas: USBI-Xalapa, FISMATIN-Xalapa y MIA-Xalapa (QA76.5 G74). 3. The Theory and Practice of Compiler Writing. L.P. Tremblay, P.G. Serenson. McGraw Hill (1985). Se encuentra en la biblioteca: ECONOMIA-Xalapa. (QA76.6 T73) 4. Machines, Languages and Computations. P.J. Denning, J.B. Dennis, J.E Qualitz. Prentice Hall (July 1978). Se encuentra en la biblioteca: INVESBIO-Xalapa. (QA267.D46) 5. Theory of Computation: Formal Languages, Automata and Complexity. J. Glenn Benjamin/Cummings Series in Computer Science (January 1989). Se encuentra en las bibliotecas: USBI-Xalapa y ECONOMIA-Xalapa. (QA267.B76) 6. Fundamentos de Compiladores: Cómo Traducir al Lenguaje Máquina. Karen A. Lemone. Editorial Continental. Se encuentra en las bibliotecas: USBI-Xalapa, FISMATIN-Xalapa y ECONOMIA-Xalapa. (QA76.76.C65 L45) 7. Construcción de Compiladores: Principios y Práctica. Kenneth C. Louden. San Jose State University. Ed. Thomson (2004). Se encuentra en la biblioteca: USBI-Xalapa y ECONOMIA-Xalapa. (QA76.76.C65 L68 C6). 8. Engineering a Compiler. Keith D. Cooper and Linda Torczon. Morgan Kaufman; 1st edition (September 2003). 9. Introduction to the Theory of Computation (Second Edition) Michael Sipser. Ed. Thomson (2006). EVALUACIÓN Dos exámenes parciales (20% cada uno) Programas computacionales (Proyecto) Participación en clase (individual y equipo), Dicha participación incluye trabajos de investigación redactados de forma adecuada • Prácticas individuales y por equipo • • • ------------------- 40% 40% 10% ------- 10% Importante: - - - - - Para poder exentar el examen ordinario, la mínima calificación parcial deberá ser de 8. Dicha calificación estará conformada por cada uno de los criterios de evaluación arriba descritos. Para tener derecho a presentar los exámenes parciales, deberán cubrir como mínimo el 80% de las asistencias. Se pasará lista 15 minutos después de iniciar la clase. Pasado este tiempo, si el estudiante no está presente, se considerará inasistencia (no se consideran retardos). La fecha de entrega de los programas computacionales será exclusivamente los siguientes días: la primera parte del proyecto deberá entregarse el 22 de Abril de 2009 y la segunda parte el 15 de Junio de 2009 durante la clase. No se recibirán programas enviados vía electrónica. Para integrar la calificación de las personas que presenten examen ordinario, se promediarán las participaciones, prácticas y programas computacionales de los exámenes parciales. En otras palabras, el examen ordinario valdrá un máximo de 40% de la calificación final mientras que el 60% restante estará integrado por los criterios de evaluación arriba descritos. En el examen extraordinario se aplicará el criterio anterior. El reporte escrito de los programas computacionales, deberá contener los siguientes puntos. 1. Introducción 2. Planteamiento del problema 3. Solución Análisis Diseño 4. Pruebas y Discusión 5. Conclusiones 6. Referencias Descripción del Proyecto (Tomado del libro “Construcción de compiladores: principios y práctica”. Autor: Kenneth C. Louden. Páginas: 491a 501). Convenciones Léxicas de C— 1) Las palabras clave o reservadas del lenguaje son las siguientes: else if int return void while. Todas las palabras reservadas o clave están reservadas, y deben ser escritas en minúsculas. 2) Los símbolos especiales son los siguientes: + - * / < <= > >= == != = ; , ( ) [ ] { } /* */ 3) Otros tokens son ID y NUM definidos mediante las siguientes expresiones regulares: ID = letra letra* NUM = digito digito* letra = a|....|z|A|.....|z digito = 0|....|9 Se distingue entre letras minúsculas y mayúsculas. 4) Los espacios en blanco se componen de blancos, retornos de línea y tabulaciones. El espacio en blanco es ignorado, excepto cuando deba separar ID, NUM y palabras reservadas. 5) Los comentarios están encerrados entre las anotaciones habituales del lenguaje C /*....*/. Los comentarios se pueden colocar en cualquier lugar donde pueda aparecer un espacio en blanco (es decir, los comentarios no pueden ser colocados dentro de los token) y pueden incluir más de una línea. Los comentarios no pueden estar anidados. Sintaxis y Semántica de C— Una gramática BNF para C— es como se describe a continuación: 1) program declaration-list 2) declaration-list declaration-list declaration | declaration 3) declaration var-declaration | fun-declaration 4) var-declaration type-specifier ID ; | type-specifier ID [ NUM ] ; 5) type-specifier int | void 6) fun-declaration type-specifier ID ( params ) compound-stmt 7) params param-list | void 8) param-list param-list , param | param 9) param type-specifier ID | type-specifier ID [ ] 10) compound-stmt { local-declarations statement-list } 11) local-declarations local-declarations var-declarations | empty 12) statement-list statement-list statement | empty 13) statement expression-stmt | compound-stmt | selection-stmt | iteration-stmt | return-stmt 14) expression-stmt expression ; | ; 15) selection-stmt if ( expression ) statement | if ( expression ) statement else statement 16) iteration-stmt while (expression) statement 17) return-stmt return ; | return expression ; 18) expression var = expression | simple-expression 19) var ID | ID [ expression ] 20) simple-expression additive-expression relop additive-expression | additive-expression 21) relop <= | < | > | >= | == | != 22) additive-expression additive-expression addop term | term 23) addop + | 24) term term mulop factor | factor 25) mulop * | / 26) factor (expression) | var | call | NUM 27) call ID (args) 28) args arg-list | empty 29) arg-list arg-list , expression | expression Programas de Muestra en C— El siguiente es un programa que introduce dos enteros, calcula su máximo común divisor y lo imprime: /* un programa para realizar el algoritmo de euclides para calcular mcd */ int gcd(int u, int v){ if (v==0) return u; else return gcd (v, u-u/v*v); } void main (void){ int x; int y; x=input( ); y=input( ); output(gcd(x,y)); } A continuación tenemos un programa que introduce una lista de 10 enteros, los clasifica por orden de selección, y los exhibe otra vez: /* un programa para realizar ordenación por selección en un arreglo de 10 elementos */ int x[10]; int minloc (int a[], int low, int high) { int i; int x; int k; k = low; x = a[low]; i = low+1; while (i<high){ if (a[i] < x) { x = a[i]; k = i; } i = i+1; } return k; } void sort (int a[ ], int low, int high){ int i; int k; i = low; while ( i< high-1) { int t; k = minloc (a, i, high); t = a[k]; a[k] = a[i]; a[i] = t; i = i+1; } } void main (void){ int i; i = 0; while (i < 10) { x[i] = input( ); i = i+1; } sort (x,0,10); i = 0; while (i < 10) { output (x[i]); i = i+1; } } Primera Parte del Proyecto: 1) Implementar una utilería de tabla de símbolos adecuada para el lenguaje C—. Esto requerirá una estructura de tabla que incorpore información de ámbito, ya sea como tablas separadas vinculadas en conjunto o con un mecanismo de eliminación que funcione de manera basada en pilas, como se describió en el capitulo 6. (“Construcción de compiladores: principios y práctica”. Autor: Kenneth C. Louden.) 2) Implementar un analizador léxico de C—, ya sea a mano como un DFA o utilizando Lex, como se describio en el capítulo 2. (“Construcción de compiladores: principios y práctica”. Autor: Kenneth C. Louden.). 3) Diseñe una estructura de árbol sintáctico para C— apropiada para la generación mediante un analizador sintáctico. Segunda Parte del Proyecto: 1) Implementar un analizador sintáctico de C— (esto requiere un analizador léxico de C—), ya sea a mano utilizando descendentes recursivos o mediante el uso de Yacc, como se describió en el capitulo 4 ó 5. (“Construcción de compiladores: principios y práctica”. Autor: Kenneth C. Louden.) Y si el tiempo lo permite: 1) Implemente un analizador semántico para C—. El requerimiento principal del analizador, además de obtener información en la tabla de símbolos, es realizar verificación de tipo en el uso de variables y funciones. Como no hay apuntadores o estructuras, y el único tipo básico es el entero, los tipos que necesitan ser tratados mediante el verificador de tipo son los tipos void, integer, array y function. 2) Implemente un generador de código para C—, de acuerdo con el ambiente de ejecución descrito en la sección anterior. ((“Construcción de compiladores: principios y práctica”. Autor: Kenneth C. Louden)