El objetivo de esta práctica es la construcción de un compilador que acepte programas escritos en el lenguaje de programación ALFA (entrada) y los traduzca a lenguaje ensamblador NASM (salida).
El lenguaje de programación ALFA de esta práctica es una AMPLIACIÓN del lenguaje de programación ALFA utilizado durante el curso. La descripción de los nuevos elementos del lenguaje se describen a continuación.
El lenguaje de programación ALFA utilizado durante el curso se amplía con los siguientes elementos:
Nueva sentencia iterativa similar a la sentencia "for" de otros lenguajes de programación de alto nivel
Nueva sentencia de control de flujo similar a la sentencia "case" de otros lenguajes de programación de alto nivel
Procedimientos sin parámetros ni variables locales
La nueva sentencia iterativa es similar a la sentencia "for" de otros lenguajes de programación de alto nivel.
La producción que describe la sintaxis de esta nueva
sentencia es la siguiente:
100: |
<bucle> |
::= |
DESDE <identificador> = <exp> HASTA <exp> HACER <sentencias> FIN |
Obsérvese que aparecen dos nuevas palabras reservadas (DESDE y HASTA)
Las restricciones semánticas aplicables son las siguientes:
El identificador que aparece después de la palabra reservada DESDE tiene que ser declarado de tipo entero y con un nivel de indirección igual a 1.
Las dos expresiones debe de ser de tipo entero y con nivel de indirección no superior a 1.
El grupo de sentencias situado entre las palabras reservadas HACER y FIN sólo se ejecuta si el valor de la segunda expresión es mayor o igual al valor de la primera expresión.
Cuando termina la ejecución del bucle, el identificador contiene el valor de la segunda expresión.
Ejemplo: programa que calcula la suma de los elementos de un vector.
INICIO // INICIALIZACIÓN DEL VECTOR
DESDE I = 0 HASTA 9 HACER // CÁLCULO DE LA SUMA
SUMA = 0; ESCRIBIR
I; FIN |
La nueva sentencia de control de flujo es similar a la sentencia "case" de otros lenguajes de programación de alto nivel
Las producciones que describen su sintaxis son las siguientes:
200: |
<sentencia> |
::= |
<seleccion> |
|
201: |
<seleccion> |
::= |
SELECCIONAR ( <exp> ) <casos_seleccion> FIN |
|
202: |
<casos_seleccion> |
::= |
<casos_estandar> <caso_defecto> |
|
203: |
<casos_estandar> |
::= |
<caso_estandar> |
|
204: |
| |
<casos_estandar> <caso_estandar> |
||
205: |
<caso_estandar> |
::= |
CASO <constante_entera> : <sentencias> |
|
206: |
<caso_defecto> |
::= |
DEFECTO <sentencias> |
Obsérvese que aparecen tres palabras reservadas nuevas (SELECCIONAR, CASO y DEFECTO) y un nuevo símbolo (:)
Las restricciones semánticas aplicables son las siguientes:
La expresión que aparece encerrada entre paréntesis detrás de las palabra reservada SELECCIONAR debe de ser de tipo entero y con nivel de indirección 0 ó 1.
No está permitido el anidamiento de esta sentencia de control de flujo.
Cuando termina la ejecución de un caso (estándar o defecto), termina la ejecución de la sentencia de control de flujo (a diferencia de la sentencia "switch" de C en la que es posible la ejecución de varios casos)
Ejemplo: programa que calcula la conjunción o la disyunción de los elementos de un vector.
INICIO // INICIALIZACIÓN DEL VECTOR
DESDE I = 0 HASTA 4 HACER LEER S; SELECCIONAR
(S) FIN |
La regla número 1 de la gramática original del lenguaje alfa será modificada para incluir una sección de procedimientos:
1: |
<programa> |
::= |
INICIO <declaraciones> <procedimientos> <sentencias> FIN |
Además se incluirán las siguientes producciones adicionales que determinan la sintaxis de los procedimientos:
300: |
<procedimientos> |
::= |
<procedimiento> <procedimientos> |
|
301: |
|
| |
/* palabra vacía */ |
|
302: |
<procedimiento> |
::= |
PROCEDIMIENTO <identificador> INICIO <sentencias> FIN |
|
303: |
<sentencia> |
::= |
LLAMAR <identificador> |
Obsérvese que aparecen dos palabras reservadas nuevas (PROCEDIMIENTO y LLAMAR).
En bison podemos crear una producción cuya parte derecha sea la palabra vacía simplemente dejando la parte derecha de la producción en blanco.
Las reglas semánticas que afectarían a los procedimientos son:
Desde un procedimiento se pueden utilizar todas las variables del programa alfa. En este sentido las variables que aparecen en la sección de declaraciones serían globales.
Desde un procedimiento sólo se puede llamar a otros procedimientos que hayan sido declarados más arriba o al mismo procedimiento. No se podría llamar a procedimientos declarados más abajo.
Los procedimientos deben tener nombres únicos y deben de ser diferentes de cualquier otra variable declarada.
El identificador que aparece a continuación de LLAMAR debe ser el nombre de un procedimiento.
Generación de código:
La sentencia LLAMAR pasa a ejecutar el código del procedimiento indicado. Al finalizar dicho procedimiento se continúa ejecutando la sentencia siguiente a LLAMAR.
Nada más ejecutarse el programa el control pasa al grupo de sentencias que aparece después de la declaración de procedimientos.
Sugerencias: utilizar la tabla de símbolos para comprobar la semántica de los procedimientos, y las sentencias CALL y RET en la generación de código.
Ejemplo de un programa que utiliza los procedimientos cuya salida es 108:
INICIO ENTERO numero; PROCEDIMIENTO sumar INICIO numero = numero + 1 FIN PROCEDIMIENTO duplicar INICIO numero = numero * 2 FIN PROCEDIMIENTO triplicar INICIO numero = numero * 3 FIN PROCEDIMIENTO triplicarHastaCien INICIO SI (numero < 100) ENTONCES LLAMAR triplicar; LLAMAR triplicarHastaCien FIN FIN numero = 1; LLAMAR sumar; LLAMAR duplicar; LLAMAR triplicarHastaCien; ESCRIBIR numero FIN |
El compilador deberá cumplir los siguientes requisitos:
Nombre del programa fuente que
llame al analizador sintáctico generado por bison:
alfa.c
El ejecutable que contenga el compilador se llamará
alfa
y se invocará de la siguiente manera:
alfa [ <nombre fichero entrada> [<nombre fichero salida>] ]
Es decir, el programa se puede llamar:
Con 0 argumentos, entonces se utilizan la entrada y la salida estándares
Con 1 argumento, entonces se utiliza la salida estándar y el argumento como nombre del fichero de entrada.
Con 2 argumentos, entonces el primero se interpreta como el nombre del fichero de entrada y el segundo como el nombre del fichero de salida.
Se deberá
incluir un fichero compatible con la herramienta make que
para el objetivo all genere el ejecutable de nombre alfa
.
La práctica se realizará de manera individual
Cada alumno entregará un fichero empaquetado (.zip), que contenga:
Todos los fuentes (ficheros .h y .c) necesarios para solucionar el problema.
Un fichero compatible con la herramienta make que para el objetivo all genere el ejecutable de nombre alfa.
El nombre del fichero zip será ps_nombre_apellido1_apellido2.zip
La práctica deberá entregarse antes del 31 de agosto de 2007 inclusive a través de la zona de entrega de prácticas de la web de la EPS en la carpeta del turno de laboratorio en el que el alumno esté inscrito.
Las normas de calificación pueden consultarse en la página web general del laboratorio de Procesadores del Lenguaje.
El resto de las normas son las descritas en la página web general del laboratorio de Procesadores del Lenguaje, en las páginas web de cada grupo y las mencionadas por los profesores de cada grupo.
Las prácticas que no cumplan los requisitos descritos en este enunciado se considerarán como no entregadas