26
PRÁCTICA DE PROCESADORES DE LENGUAJE EVALUACIÓN CONTINUA CURSO 2009/2010 OBJETIVO DE LA PRÁCTICA El objetivo de la práctica es desarrollar un compilador utilizando las herramientas flex y bison y el leguaje de programación C. El lenguaje fuente que se compila es diseñado por el alumno y debe cumplir las especificaciones que el profesor le haya comunicado y el lenguaje destino es el ensamblador NASM. Dado que se van a describir varias versiones del lenguaje, a lo largo de este enunciado vamos a llamar ALFAi, de forma genérica, a cada una de ellas. PARTE 1: DISEÑO DEL LENGUAJE En cada grupo de prácticas, el profesor asignará a cada equipo de alumnos uno de los lenguajes ALFAi descritos en este enunciado. En esta primera parte de la práctica debe diseñar una gramática independiente del contexto completa para un lenguaje ALFAi que cumpla con la descripción que se le proporcione. Para entregar la gramática al profesor debe escribir un fichero de texto plano con el siguiente formato: [TERMINALES] Una línea para cada terminal [NO TERMINALES] Una línea para cada no terminal [AXIOMA] Una línea para el axioma [REGLAS] Una línea para cada regla. Cada regla se representará con el no terminal de su parte izquierda, seguido de dos puntos, y a continuación los símbolos (terminales y no terminales) de la parte derecha separados entre ellos por un espacio en blanco. Para las reglas lamba, la parte derecha se dejará vacía. En la tabla adjunta se muestra un ejemplo de gramática y su correspondiente fichero de especificación. Gramática Fichero de especificación <exp> <exp> + <exp> <exp> <exp> - <exp> <exp> <cte> <cte> <digito> <cte> <digito> <cte> <digito> 0 1 [TERMINALES] + - 0 1 [NO TERMINALES] exp cte digito [AXIOMA] exp [REGLAS] exp : exp + exp exp : exp - exp

PRÁCTICA DE PROCESADORES DE LENGUAJE …arantxa.ii.uam.es/.../compiladores/2009_2010/enunciado_09_10.pdf · PRÁCTICA DE PROCESADORES DE LENGUAJE EVALUACIÓN CONTINUA CURSO 2009/2010

  • Upload
    buikiet

  • View
    220

  • Download
    0

Embed Size (px)

Citation preview

PRÁCTICA DE PROCESADORES DE LENGUAJE EVALUACIÓN CONTINUA

CURSO 2009/2010

OBJETIVO DE LA PRÁCTICA El objetivo de la práctica es desarrollar un compilador utilizando las herramientas flex y bison y

el leguaje de programación C. El lenguaje fuente que se compila es diseñado por el alumno y

debe cumplir las especificaciones que el profesor le haya comunicado y el lenguaje destino es el

ensamblador NASM. Dado que se van a describir varias versiones del lenguaje, a lo largo de

este enunciado vamos a llamar ALFAi, de forma genérica, a cada una de ellas.

PARTE 1: DISEÑO DEL LENGUAJE En cada grupo de prácticas, el profesor asignará a cada equipo de alumnos uno de los lenguajes

ALFAi descritos en este enunciado.

En esta primera parte de la práctica debe diseñar una gramática independiente del contexto

completa para un lenguaje ALFAi que cumpla con la descripción que se le proporcione.

Para entregar la gramática al profesor debe escribir un fichero de texto plano con el siguiente

formato:

[TERMINALES]

Una línea para cada terminal

[NO TERMINALES]

Una línea para cada no terminal

[AXIOMA]

Una línea para el axioma

[REGLAS]

Una línea para cada regla. Cada regla se representará con el no terminal de su parte izquierda,

seguido de dos puntos, y a continuación los símbolos (terminales y no terminales) de la parte

derecha separados entre ellos por un espacio en blanco. Para las reglas lamba, la parte derecha

se dejará vacía.

En la tabla adjunta se muestra un ejemplo de gramática y su correspondiente fichero de

especificación.

Gramática Fichero de especificación

<exp> →<exp> + <exp>

<exp> →<exp> - <exp>

<exp> → <cte>

<cte> → <digito>

<cte> → <digito> <cte>

<digito> → 0 1

[TERMINALES]

+

-

0

1

[NO TERMINALES]

exp

cte

digito

[AXIOMA]

exp

[REGLAS]

exp : exp + exp

exp : exp - exp

Gramática Fichero de especificación

exp : cte

cte : digito

cte : digito cte

digito :0

digito :1

NORMAS DE ENTREGA

Debe entregar mediante la web de entregas de prácticas de la escuela un fichero

empaquetado (.zip) que deberá cumplir los siguientes requisitos:

• El fichero zip deberá contener la plantilla anteriormente descrita para la

gramática del lenguaje que se le ha asignado.

• El nombre del fichero zip será gr_gg_pp.zip, donde gg corresponde al grupo de

prácticas y pp al número del equipo. Por ejemplo, el fichero comprimido del

equipo 5 del grupo Ma se llamará gr_ma_05.zip

PARTE 2: ANÁLISIS MORFOLÓGICO Y CASOS DE PRUEBA

Tras comprobar con su profesor en el laboratorio que su gramática es adecuada, debe completar

en esta segunda parte de la práctica el analizador morfológico que utilizará el compilador final y

el diseño y codificación de los casos de prueba necesarios.

CASOS DE PRUEBA Sus casos de prueba son un conjunto de programas que sigan la sintaxis descrita en su gramática

y la semántica habitual en los lenguajes de programación completada por la descripción que se

proporciona más adelante en este enunciado.

Los casos de prueba están divididos en dos partes:

• Los comunes a todos los compiladores (7 casos)

• Los específicos para cada uno de ellos (3 casos)

Casos de prueba comunes

En la tabla adjunta se describen los 7 casos de prueba comunes a todos los compiladores junto

con un ejemplo en ALFA. Es muy importante respetar los nombres que aparecen en la tabla de

los ficheros que contienen los programas de prueba.

Descripción del caso de prueba Ejemplo en ALFA

Fichero: ej_aritmeticas1.alf

Comentario con el siguiente texto: Tratamiento

de operaciones aritméticas.

Declaración de 2 variables enteras o reales

(dependiendo del compilador): x, y.

Lectura de los valores de dichas variables.

Impresión de resultado de sumar, restar,

multiplicar y dividir dichas variables.

Impresión de resultado de negar la variable x.

// Tratamiento de operaciones aritmeticas

main

{

int x, y;

scanf x;

scanf y;

printf x+y;

printf x-y;

printf x*y;

printf x/y;

printf -x;

} Fichero: ej_aritmeticas2.alf

Comentario con el siguiente texto: Tratamiento

de operaciones aritmeticas, comprobando la

precedencia de operandos

Declaración de 3 variables enteras o reales

(dependiendo del compilador): x, y, z.

Lectura de los valores de dichas variables.

Impresión de: x+y*z

Impresión de: (x+y)*z

Impresión de: -x*y*-z

// Tratamiento de operaciones aritmeticas,

// comprobando la precedencia de operandos

main

{

int x, y, z;

scanf x;

scanf y;

scanf z;

printf x+y*z;

printf (x+y)*z;

printf -x*y*-z;

}

Descripción del caso de prueba Ejemplo en ALFA

Fichero: ej_funciones1.alf

Comentario con el siguiente texto: Tratamiento

de funciones: suma

Declaración de 1 variable entera o real

(dependiendo del compilador): z.

Una función llamada "suma" que lea 2

argumentos de entrada, los sume y devuelva el

resultado.

En el programa principal llamada a esa función,

siendo sus argumentos 2 constantes.

En el programa principal impresión del resultado

de esa función.

// Tratamiento de funciones: suma

main

{

int z;

function int suma(int x ; int y)

{

int s;

s=x+y;

return s;

}

z=suma(2,3);

printf z;

}

Fichero: ej_funciones2.alf

Comentario con el siguiente texto: Tratamiento

de funciones: factorial

Declaración de 1 variable entera o real

(dependiendo del compilador): z.

Una función llamada "factorial" que lea 1

argumento de entrada y calcule su factorial de

forma recursiva.

En el programa principal llamada a esa función,

siendo su argumento una constante.

En el programa principal impresión del resultado

de esa función.

// Tratamiento de funciones: factorial

main

{

int z;

function int factorial (int n)

{

if (n==0) {

return 1;

} else {

return (n*factorial(n-1));

}

}

z=factorial(6);

printf z;

}

Descripción del caso de prueba Ejemplo en ALFA

Fichero: ej_ifs1.alf Comentario con el siguiente texto: Tratamiento

de sentencias condionales (if). Ubica un punto

(x, y) en un cuadrante (1, 2, 3, 4) o en los ejes (0)

Declaración de 2 variables enteras o reales

(dependiendo del compilador): x, y.

Lectura de los valores de dichas variables.

Serie de sentencias que permitan realizar los ifs

para identificar el cuadrante:

x>0, y>0 --> cuadrante 1

x>0, y<0 --> cuadrante 2

x<0, y<0 --> cuadrante 3

x<0, y>0 --> cuadrante 4

x==0 --> eje 0

y==0 --> eje 0

// Tratamiento de sentencias condionales (if)

// Tratamiento de sentencias condionales (if).

// Ubica un punto (x, y) en un cuadrante (1, 2, 3,

4)

// o en los ejes (0)

main

{

int x, y;

scanf x;

scanf y;

if (x>0) {

if (y>0) {

printf 1;

} else {

if (y==0) {

printf 0;

} else {

printf 2;

}

}

} else {

if (x==0) {

printf 0;

} else {

if (y>0) {

printf 4;

} else {

if (y==0) {

printf 0;

} else {

printf 3;

}

}

}

}

}

Descripción del caso de prueba Ejemplo en ALFA

Fichero: ej_logicas1.alf Comentario con el siguiente texto: Tratamiento

de sentencias logicas. Salida: false true false

Declaración de 3 variables lógicas: a, b,

resultado.

Asignación de los siguientes valores: a <- true, b

<- false.

Asignación: resultado <- a and b.

Impresión de resultado.

Asignación: resultado <- a or b.

Impresión de resultado.

Asignación: resultado <- not a.

Impresión de resultado.

// Tratamiento de sentencias logicas

// Salida: false true false

main

{

boolean a, b, resultado;

a=true;

b=false;

resultado=(a && b);

printf resultado;

resultado=(a || b);

printf resultado;

resultado=(!a);

printf resultado;

}

Fichero: ej_logicas2.alf

Comentarios con el siguiente texto: Tratamiento

de sentencias logicas, comprobando la

precedencia de operandos. Salida: true false false

true

Declaración de 4 variables lógicas: a, b, c,

resultado.

Asignación de los siguientes valores: a <- true, b

<- false, c <- false.

Asignación: resultado <- a or b and c.

Impresión de resultado.

Asignación: resultado <- a and b or c.

Impresión de resultado.

Asignación: resultado <- not a and b.

Impresión de resultado.

Asignación: resultado <- not (a and b).

Impresión de resultado.

// Tratamiento de sentencias logicas,

comprobando

// la precedencia de operandos

// Salida: true false false true

main

{

boolean a, b, c, resultado;

a=true;

b=false;

c=false;

resultado=(a || b && c);

printf resultado;

resultado=(a && b || c);

printf resultado;

resultado=(!a && b);

printf resultado;

resultado=(!(a && b));

printf resultado;

}

Casos de prueba específicos

En las tablas adjunta se describen los 3 casos de prueba específicos para cada uno de los 5

compiladores distintos. Es muy importante respetar los nombres que aparecen en la tablas de los

ficheros que contienen los programas de prueba.

Casos de prueba específicos del compilador ALFA1

Fichero: alfa1_especifico1.alf

Implementar un programa que imprima por pantalla los números que sean menores o iguales que 64,

que sean múltiplos de 4 y que sean múltiplos de 7. Para ello se deberán utilizar tres variables de tipo

conjunto. En la primera se introducirán los múltiplos de 4. En la segunda se introducirán los múltiplos

de 7 y en la tercera variable se almacenará la intersección de las dos primeras. Para la elaboración de

este programa deberán utilizarse una función que determine cuando un número es múltiplo de otro. La

salida del programa deberá ser:

28

56

Fichero: alfa1_especifico2.alf

Implementar un programa que imprima por pantalla los números menores o iguales que 64 y que sean

primos o que pertenezcan a la sucesión de Fibonacci. Para ello se utilizarán tres variables de tipo

conjunto. La primera almacenará los números primos. La segunda almacenará los números de la

sucesión de Fibonacci. La tercera variable almacenará la unión de las dos anteriores. Para la

elaboración de este programa deberán utilizarse una función que determine cuando un número es

primo. Además los números de la sucesión de Fibonacci deberán de ser generados por el propio

programa. La salida será:

0

1

2

...

55

59

61 Fichero: alfa1_especifico3.alf Implementar un programa que lea diez números por la entrada estándar y luego imprima cuantos

números (sin repetición) han sido introducidos. Para elaborar dicho programa habrá que utilizar una

variable de tipo conjunto donde se irán almacenando los números. Una vez leídos los 10 números se

imprimirá el tamaño de la variable conjunto resultante. Por ejemplo, si se introducen los números 1, 2,

3, 4, 3, 6, 2, 1, 2 , 8, el programa imprimirá:

6

Casos de prueba específicos del compilador ALFA2

Fichero: alfa2_especifico1.alf

Implementar un programa que lea por la entrada estándar los elementos de una matriz cuadrada de

dimensión 3x3. Los elementos se introducirán en líneas distintas uno por uno y en el orden e11, e12,

e13, e21, e22, e23, e31, e32, e33 donde eij denota el elemento de la fila i y la columna j. El programa

pondrá la diagonal de dicha matriz a cero, multiplicará los elementos de la matriz por 2 y finalmente

imprimirá la fila y la columna de aquellos elementos que sean iguales a 7. Por ejemplo si e23 y e31

son los únicos elementos iguales a 7 tras la operación, el programa deberá imprimir:

2.000000

3.000000

3.000000

1.000000

Casos de prueba específicos del compilador ALFA2

Fichero: alfa2_especifico2.alf

Implementar un programa que lea por la entrada estándar las coordenadas de dos vectores de

dimensión 10 y luego calcule la distancia en el espacio euclídio de los dos puntos que representan

dichos vectores en el espacio 10-dimensional. Las coordenadas se introducirán de una en una en líneas

diferentes. Para calcular la raíz cuadrada de un número dado S se recomienda utilizar el método de

aproximación babilónico:

1 – Empezar con un valor positivo cualquiera x_0, por ejemplo 10.

2 – Fijar x_(n+1) al promedio de x_n y de S / x_n, es decir: x_(n+1) = 0.5 * (x_n + S / x_n).

3 – Repetir pasos 2,3 hasta que x_(n+1)^2 esté lo suficientemente cerca de S.

La salida del programa deberá ser una línea donde se imprima la distancia requerida.

Fichero: alfa2_especifico3.alf Implementar un programa que lea por la entrada estándar las coordenadas de 4 vectores v1, v2, v3, y

v4 de dimensión 3. El programa deberá de calcular en primer lugar dos vectores v5 y v6, donde v5 es

el producto vectorial de v1 y v2 y v6 es el producto vectorial de v3 y v4. Finalmente el programa

imprimirá el resultado de calcular el producto escalar entre v5 y v6.

Casos de prueba específicos del compilador ALFA3

Fichero: alfa3_especifico1.alf

Implementar un programa que lea por la entrada estándar 20 números enteros, los almacene en una

lista y los ordene de menor a mayor mediante el algoritmo insert sort. La salida del programa serán los

20 números introducidos y ordenados, cada uno en una línea diferente. Para la ordenación se

recomienda utilizar listas auxiliares.

Fichero: alfa3_especifico2.alf

Implementar un programa que lea por la entrada estándar 10 números enteros y los almacene en una

lista. El proceso de almacenamiento deberá ser como se describe a continuación. Si el número es par,

el número se introducirá al principio de la lista. Si el número es impar, se almacenará al final de la

lista. La salida del programa serán los elementos de dicha lista imprimidos en un orden determinado

por otros 10 números enteros que se procederán a leer por la entrada estándar. Si el primero de este

segundo bloque de 10 números es múltiplo de 3, el primer elemento a imprimir será el que se

encuentre al principio de la lista. Si dicho número no es múltiplo de 3, el primer elemento a imprimir

será el que se encuentre al final de la lista, y así sucesivamente teniendo en cuenta que cada vez que se

imprima un elemento de la lista, éste se eliminará de dicha lista. Para la entrada de números 1, 2, 3, 4,

5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 la salida seŕa la secuencia 9, 7, 10, 5, 3, 8, 1, 2, 6, 4, donde

los números se introducirán en líneas separadas y se imprimirán también en líneas separadas.

Fichero: alfa3_especifico3.alf Implementar un programa que lea 10 números por la entrada estándar, los almacene al final de una

lista y luego se proceda a imprimir los elementos de dicha lista, empezando por el último y

terminando por el primero.

Casos de prueba específicos del compilador ALFA4

Fichero: alfa4_especifico1.alf

Implementar un programa que lea por la entrada estándar 20 números enteros donde el número 0 será

el equivalente al símbolo de paréntesis izquierdo “(“ y el número 1 será el equivalente al símbolo de

paréntesis derecho “)”. Utilizando una pila, el programa deberá determinar si los símbolos de

paréntesis codificados por 0 y 1 se encuentran balanceados. La salida del programa será el número 1 si

los paréntesis están balanceados y el número 0 en caso contrario.

Casos de prueba específicos del compilador ALFA4

Fichero: alfa4_especifico2.alf

Implementar un programa que utilizando una estructura de tipo pila evalúe una serie de operaciones

aritméticas introducidas en formato postfijo. La entrada será una lista de 19 números que

representarán bien operadores (número 0 y 1) u operandos (resto de números). Los números 0 y 1

corresponderán a los operadores de suma y multiplicación respectivamente, así la cadena de números

3 4 1 5 0 representará la cadena en postfijo 3 4 * 5 +. Los 19 números de entrada se introducirán en

líneas diferentes y la salida será el número resultado de evaluar la operación que dichos números

codifican en formato postfijo. Deberá utilizarse una pila para la evaluación de dicha operación. Así si

la entrada es la secuencia de números 2, 2, 1, 4, 3, 0, 7, 1, 9, 10, 1, 1, 13, 14, 0, 16, 1, 0, 1, la salida del

programa será el número 19368.

Fichero: alfa4_especifico3.alf Implementar un programa que lea 20 números por la entrada estándar. Para cada número, se realizarán

las siguientes operaciones. Si el número es par, se introducirá el número 1 en la cima de una pila

inicialmente vacía. Si el número es impar se introducirá el número 0 en la cima de la pila. Una vez

procesados los 10 primeros números se volverán a leer otros diez números por la entrada estándar.

Para cada uno de las números pertenecientes a este segundo bloque de diez cifras se realizarán las

siguientes operaciones. Si el número es múltiplo de 5 y en la cima de la pila hay un 0 se eliminará

dicho 0 de la cima de la pila. Si por el contrario en la cima hay un 1 no se realizará ninguna operación.

Si el número no es múltiplo de 5 y en la cima de la pila hay un 0 o un 1 se eliminará de la pila el

contenido que este en la cima. Finalmente se imprimirá el contenido de la pila. Los números

proporcionados como entrada al programa requerido se introducirán de uno en uno en líneas

separadas. Para la entrada 2, 2, 1, 4, 3, 4, 7, 1, 9, 10, 1, 1, 13, 14, 3, 20, 1, 10, 1, 5 la salida del

programa será 1.

Casos de prueba específicos del compilador ALFA5

Fichero: alfa5_especifico1.alf

Implementar un programa que lea por la entrada estándar 20 números. Los almacene en una cola y

que cree una nueva cola cuyo contenido sea igual a la primera cola, pero con los elementos pares y los

impares intercambiados. Finalmente, se imprimirá el contenido de la segunda cola. Si la entrada al

programa es la secuencia de números 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,

la salida será la secuencia de números 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15, 18, 17, 20, 19.

Los números proporcionados como entrada al programa requerido se introducirán de uno en uno en

líneas separadas. La salida será también en una línea por cada número.

Fichero: alfa5_especifico2.alf

Implementar un programa que lea por la entrada estándar 20 números enteros, los almacene en una

cola y los ordene de menor a mayor mediante el algoritmo insert sort. La salida del programa serán los

20 números introducidos y ordenados, cada uno en una línea diferente. Para la ordenación se

recomienda utilizar colas auxiliares. Los números proporcionados como entrada al programa

requerido se introducirán de uno en uno en líneas separadas.

Fichero: alfa5_especifico3.alf Implementar un programa que lea por la entrada estándar 10 números. Y los almacene en una cola. A

continuación el programa volverá a leer otra serie de 10 números que representarán una permutación

sobre los primeros 10 números leídos. La salida del programa deberá de ser el resultado de aplicar

dicha permutación a la entrada original. Por ejemplo, si la entrada al programa es la cadena de

números 10, 1, 7, 9, 8, 3, 2, 4, 6, 5, 8, 5, 3, 1, 9, 6, 5, 7, 10, 2, 4. La salida deberá de ser la cadena de

números 4, 8, 7, 10, 6, 3, 8, 2, 5, 1, 9. Tanto la entrada como la salida se realizarán en lineas diferentes

para cada número.

ANALIZADOR MORFOLÓGICO Para completar el analizador morfológico de su compilador debe seguir las indicaciones que se

describen a continuación.

Estudio de la Gramática

• Inicialmente se tratará de identificar en la gramática completa del lenguaje el conjunto

de unidades sintácticas o tokens existentes.

Codificación de una Especificación para flex • El alumno deberá diseñar el conjunto de expresiones regulares que representa cada

unidad sintáctica.

• Observación muy importante: Recuerde que algunas tareas que el analizador léxico

puede y suele realizar son:

o Ignorar los espacios en blanco y tabuladores, que actúan como separadores

entre unidades sintácticas.

o Ignorar los comentarios, que no aportan código ejecutable al programa.

o Gestionar errores morfológicos.

• Se deberá escribir un fichero de nombre alfa.l que sea una especificación correcta para

la entrada de la herramienta flex.

• Se recomienda al alumno que se familiarice primero con flex mediante las explicaciones

que su profesor de prácticas realizará en su laboratorio y posteriormente diseñe el

conjunto final de expresiones regulares.

Codificación de un Programa de Prueba para el analizador morfológico • Se deberá escribir (en C) un programa de prueba del analizador léxico generado con

flex, con los siguientes requisitos:

o Nombre del programa fuente: prueba_lexico.c

o Al ejecutable correspondiente se le invocará de la siguiente manera:

prueba_lexico [<nombre_fichero_entrada> [<nombre_fichero_salida>]] o Es decir, el programa se puede ejecutar:

� Con 0 argumentos: se utilizan la entrada y la salida estándares.

� Con 1 argumento: se utiliza la salida estándar y el argumento como

nombre del fichero de entrada.

� Con 2 argumentos: el primer argumento se interpreta como el nombre

del fichero de entrada y el segundo como el nombre del fichero de

salida.

o La estructura de los ficheros de entrada/salida se explican a continuación.

Descripción del Fichero de Entrada • El fichero de entrada contiene un programa escrito en lenguaje ALFAi (no

necesariamente correcto).

Funcionalidad del Programa • El programa de prueba, haciendo uso del analizador léxico construido con flex, deberá

identificar en el fichero de entrada las siguientes unidades sintácticas:

o Palabras reservadas: cualquier palabra reservada ALFAi correcta.

o Símbolos: cualquier símbolo ALFAi correcto.

o Identificadores: que sigan la sintaxis descrita en su gramática para la unidad

sintáctica asociada con los identificadores de variables.

o Constantes: cualquier número o dato constante de los tipos permitidos en

ALFAi.

o Cualquier otra cosa, se considerará errónea.

• Por cada unidad sintáctica identificada en el fichero de entrada, el programa de prueba

debe generar una línea en el fichero de salida según se describe a continuación.

Descripción del Fichero de Salida • El fichero de salida se compone de un conjunto de líneas, una por cada unidad sintáctica

del fichero de entrada. La estructura de la línea es la siguiente:

o El primer elemento de la línea será, según corresponda

� TOK_PALABRA_RESERVADA: para las palabras reservadas.

� TOK_SIMBOLO: para los símbolos.

� TOK_IDENTIFICADOR: para los identificadores.

� TOK_CONSTANTE: para todas las constantes.

� TOK_ERROR: para los errores. Será suficiente controlar la aparición

de caracteres no permitidos por el lenguaje e identificadores de longitud

no válida.

o El segundo elemento será un número entero, que identificará la unidad

sintáctica (debe ser distinto para cada unidad sintáctica). Debe codificar un

fichero tokens.h para contener los valores numéricos de los tokens de la

gramática de ALFAi.

o El tercer elemento será el lexema (el fragmento del programa fuente) analizado

como la unidad sintáctica correspondiente.

o Muy importante: cada elemento de la línea estará separado por un tabulador y ningún otro carácter más.

Ejemplos A continuación se muestran algunos ejemplos para algunos fuentes escritos en ALFA. Los

números asociados con cada token son también un ejemplo de posible numeración.

• Ejemplo 1: Si el fichero de entrada es el siguiente:

// Programa que eleva un número entero al cuadrado

main {

int x, resultado;

scanf x;

resultado=x*x;

printf resultado;

}

El fichero de salida es el siguiente:

TOK_PALABRA_RESERVADA 200 main

TOK_SIMBOLO 300 {

TOK_PALABRA_RESERVADA 201 int

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 306 ,

TOK_IDENTIFICADOR 500 resultado

TOK_SIMBOLO 302 ;

TOK_PALABRA_RESERVADA 213 scanf

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 302 ;

TOK_IDENTIFICADOR 500 resultado

TOK_SIMBOLO 309 =

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 303 *

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 302 ;

TOK_PALABRA_RESERVADA 214 printf

TOK_IDENTIFICADOR 500 resultado

TOK_SIMBOLO 302 ;

TOK_SIMBOLO 301 }

• Ejemplo 2: Si el fichero de entrada es el siguiente:

// Programa que eleva un número x a la potencia y.

main {

int x, y;

int i, total;

scanf x;

scanf y;

i=1;

total=1;

while (i<=y) {

total=total*x;

i=i+1;

}

printf total;

}

El fichero de salida es el siguiente:

TOK_PALABRA_RESERVADA 200 main

TOK_SIMBOLO 300 {

TOK_PALABRA_RESERVADA 201 int

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 306 ,

TOK_IDENTIFICADOR 500 y

TOK_SIMBOLO 302 ;

TOK_PALABRA_RESERVADA 201 int

TOK_IDENTIFICADOR 500 i

TOK_SIMBOLO 306 ,

TOK_IDENTIFICADOR 500 total

TOK_SIMBOLO 302 ;

TOK_PALABRA_RESERVADA 213 scanf

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 302 ;

TOK_PALABRA_RESERVADA 213 scanf

TOK_IDENTIFICADOR 500 y

TOK_SIMBOLO 302 ;

TOK_IDENTIFICADOR 500 i

TOK_SIMBOLO 309 =

TOK_CONSTANTE 501 1

TOK_SIMBOLO 302 ;

TOK_IDENTIFICADOR 500 total

TOK_SIMBOLO 309 =

TOK_CONSTANTE 501 1

TOK_SIMBOLO 302 ;

TOK_PALABRA_RESERVADA 211 while

TOK_SIMBOLO 307 (

TOK_IDENTIFICADOR 500 i

TOK_SIMBOLO 404 <=

TOK_IDENTIFICADOR 500 y

TOK_SIMBOLO 308 )

TOK_SIMBOLO 300 {

TOK_IDENTIFICADOR 500 total

TOK_SIMBOLO 309 =

TOK_IDENTIFICADOR 500 total

TOK_SIMBOLO 303 *

TOK_IDENTIFICADOR 500 x

TOK_SIMBOLO 302 ;

TOK_IDENTIFICADOR 500 i

TOK_SIMBOLO 309 =

TOK_IDENTIFICADOR 500 i

TOK_SIMBOLO 312 +

TOK_CONSTANTE 501 1

TOK_SIMBOLO 302 ;

TOK_SIMBOLO 301 }

TOK_PALABRA_RESERVADA 214 printf

TOK_IDENTIFICADOR 500 total

TOK_SIMBOLO 302 ;

TOK_SIMBOLO 301 }

PARTE 3: ANÁLISIS SINTÁCTICO Esta parte tiene como primer objetivo la codificación de un analizador sintáctico mediante el

uso del lenguaje de programación C y la herramienta de ayuda a la generación de analizadores

sintácticos bison.

Este analizador será utilizado por el compilador del lenguaje ALFAi que va a desarrollarse

durante el curso.

Para ello debe seguir las indicaciones que se describen a continuación.

Codificación de una especificación para bison El alumno deberá escribir un fichero con nombre alfa.y que sea una especificación correcta para

la entrada de la herramienta bison. Se recomienda al alumno que se familiarice primero con

bison mediante las explicaciones que su profesor de prácticas realizará en su laboratorio.

Resolución de conflictos Cuando se compile el fichero alfa.y pueden aparecer mensajes de conflictos. Estos conflictos se

refieren a los que encuentra el autómata a pila generado por la herramienta bison. Para obtener

información acerca de ellos, se debe compilar el fichero alfa.y de la siguiente manera:

bison -d -y -v alfa.y con el flag -v se genera el fichero y.output que contiene la descripción completa del autómata y

de los conflictos (si existieran).

El alumno debe asegurarse de eliminar los conflictos siguiendo las indicaciones de su profesor

de prácticas.

Modificación de la especificación para flex

El alumno deberá modificar el fichero alfa.l de la primera parte para poder ser enlazado

con el fichero alfa.y. Para ello, utilizará como guía las explicaciones que su profesor de

prácticas realizará en su laboratorio.

Codificación de un programa de prueba El alumno deberá escribir (en C) un programa de prueba del analizador sintáctico generado con

bison, con los siguientes requisitos:

• Nombre del programa fuente: prueba_sintactico.c

• Al ejecutable correspondiente, se le invocará de la siguiente manera:

prueba_sintactico [<nombre fichero entrada> [<nombre fichero salida>]] • Es decir, el programa se puede ejecutar:

o Con 0 argumentos, entonces se utilizan la entrada y la salida estándares.

o Con 1 argumento, entonces se utiliza la salida estándar y el argumento como

nombre del fichero de entrada.

o 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.

• La estructura de los ficheros de entrada/salida se explica a continuación.

Descripción del fichero de entrada El fichero de entrada contiene un programa escrito en lenguaje ALFAi (no necesariamente

correcto).

Descripción del fichero de salida

El fichero de salida se compone de un conjunto de líneas de dos tipos. En concreto:

• Una línea por cada TOKEN deplazado (reconocido) por el analizador léxico.

• Una línea por cada PRODUCCIÓN reducida en el proceso de análisis sintáctico.

Cada línea correspondiente a un TOKEN desplazado debe contener la siguiente información y

formato:

;D: <token> donde

• ; debe escribirse literalmente para que le sea cómodo gestionar la impresión de estos

textos en el compilador completo (corresponde con el símbolo de inicio de los

comentarios de línea en NASM)

• <token> es el fragmento de entrada reconocido por el analizador léxico

• D: y <token> van separados por un tabulador.

Cada línea correspondiente a una regla reducida tendrá el formato siguiente:

;R<nº regla>: <regla> donde

• <nº regla> es el número que identifica la regla que se reduce en la gramática de ALFAi

diseñada en la primera parte por el alumno • <regla> es el texto de la regla reducida según aparece en la gramática. • R<nº regla> y <regla> van separados por un tabulador. • Los elementos que forman <regla> irán separados por espacios.

Gestión de errores Cuando se produzca un error sintáctico el analizador creado mediante bison deberá de imprimir

una línea por la salida estándar de error con el siguiente formato:

ERROR SINTACTICO:<nº linea>:<nº carácter> donde

• <nº linea> es la línea en el fichero de entrada donde aparece el último TOKEN

reconocido por el analizador léxico y • <nº carácter> es el carácter en la correspondiente línea donde empieza el último

TOKEN reconocido por el analizador léxico. Cuando se produzca un error léxico, el analizador léxico implementado en la práctica 1 deberá

imprimir la siguiente línea por la salida estándar de error:

ERROR LEXICO:<nº linea>:<nº carácter> donde

• <nº linea> es la línea en el fichero de entrada donde aparece donde aparece el TOKEN

erróneo y • <nº carácter> es el carácter en la correspondiente línea donde empieza el TOKEN

erróneo. En el caso de que se imprima un mensaje de error léxico, no deberá de imprimirse otro mensaje

de error sintáctico.

Ejemplo Suponga que el siguiente programa está escrito en uno de los lenguajes de programación ALFAi

main {

int x, resultado;

scanf x;

resultado = x * x + 1.5 * 2;

printf resultado;

}

Una posible salida para su programa es la que se muestra a continuación (se supone que los

números de regla, etc. corresponden a una gramática correcta)

;D: main

;D: {

;D: int

;R10: <tipo> ::= int

;D: x

;R9: <clase_escalar> ::= <tipo>

;R5: <clase> ::= <clase_escalar>

;R106: <identificador> ::= TOK_IDENTIFICADOR

;D: ,

;D: resultado

;R106: <identificador > ::= TOK_IDENTIFICADOR

;D: ;

;R18: <identificadores> ::= <identificador >

;R19: <identificadores> ::= <identificador> , <identificadores>

;R4: <declaracion> ::= <clase> <identificadores> ;

;D: scanf

;R2: <declaraciones> ::= <declaracion>

;R21: <funciones> ::=

;D: x

;R106: <identificador> ::= TOK_IDENTIFICADOR

;D: ;

;R54: <lectura> ::= scanf <identificador>

;R35: <sentencia_simple> ::= <lectura>

;R32: <sentencia> ::= <sentencia_simple> ;

;D: resultado

;R106: <identificador > ::= TOK_IDENTIFICADOR

;D: =

;D: x

;R106: <identificador > ::= TOK_IDENTIFICADOR

;D: *

;R80: <exp> ::= <identificador>

;D: x

;R106: <identificador> ::= TOK_IDENTIFICADOR

;D: +

;R80: <exp> ::= <identificador>

;R75: <exp> ::= <exp> * <exp>

;D: 1.5

;R105: <constante_real > ::= TOK_CONSTANTE_REAL

;R101: <constante> ::= <constante_real >

;R81: <exp> ::= <constante>

;D: *

;D: 2

;R104: <constante_entera > ::= TOK_CONSTANTE_ENTERA

;R100: <constante> ::= <constante_entera>

;R81: <exp> ::= <constante>

;D: ;

;R75: <exp> ::= <exp> * <exp>

;R72: <exp> ::= <exp> + <exp>

;R43: <asignacion> ::= <identificador > = <exp>

;R34: <sentencia_simple> ::= <asignacion>

;R32: <sentencia> ::= <sentencia_simple> ;

;D: printf

;D: resultado

;R106: <identificador > ::= TOK_IDENTIFICADOR

;D: ;

;R80: <exp> ::= <identificador >

;R56: <escritura> ::= printf <exp>

;R36: <sentencia_simple> ::= <escritura>

;R32: <sentencia> ::= <sentencia_simple> ;

;D: }

;R30: <sentencias> ::= <sentencia>

;R31: <sentencias> ::= <sentencia> <sentencias>

;R31: <sentencias> ::= <sentencia> <sentencias>

;R1: <programa> ::= main { <declaraciones> <funciones> <sentencias> }

PARTE 4: TABLA DE SÍMBOLOS Esta parte tiene como objetivo la implementación de la tabla de símbolos de su compilador.

El alumno debe escribir los ficheros y módulos C que considere necesarios para la definición e

implementación de la tabla de símbolos. Para todas sus decisiones de diseño utilizará como

referencia las indicaciones que conoce de la parte de teoría y las explicaciones que su profesor

de prácticas realizará en su laboratorio.

Observaciones

• Todos los lenguajes ALFAi tienen estructura de bloques

• Observe que en ninguno de ellos pueden definirse funciones (ni otro tipo de bloques sin

nombre) dentro de una función por lo que como mucho se necesitará

o La tabla de símbolos del ámbito principal.

o La tabla de símbolos de la función activa.

Codificación de un programa de prueba El alumno deberá escribir (en C) un programa de prueba del analizador sintáctico generado con

bison al que se incorpora la tabla de símbolos, con los siguientes requisitos:

• Nombre del programa fuente: prueba_tabla_simbolos.c

• Al ejecutable correspondiente, se le invocará de la siguiente manera:

prueba_tabla_simbolos [<nombre fichero entrada> [<nombre fichero salida>]] • Los argumentos tienen el mismo significado de la parte anterior.

• La estructura de los ficheros de entrada/salida se explica a continuación.

Descripción del fichero de entrada El fichero de entrada contiene un programa correcto escrito en lenguaje ALFAi.

Descripción del fichero de salida A la salida de la parte 3 puede añadir, justo al término del proceso de las partes declarativas del

programa considerado el código NASM correspondiente a la declaración de las variables

contenidas en la tabla de símbolos.

Si se está escribiendo la tabla de símbolos del ámbito principal, la primera línea debe ser

; TABLA SÍMBOLOS PRINCIAL Si se está escribiendo la tabla de símbolos de una función, la primera línea debe ser

; TABLA SÍMBOLOS FUNCIÓN

Debe asegurarse de comenzar cada una de las líneas con el símbolo “;” para que sean

comentarios NASM válidos. Esto le facilitará la construcción del compilador completo.

Debe seguir las indicaciones de su profesor de laboratorio respecto al formato de las

instrucciones NASM necesarias para esta tarea.

Ejemplo Para el mismo fuente, y en los mismos supuestos del ejemplo de la parte anterior. La tabla de

símbolos del ámbito principal aparecería en la parte resaltada. Observe que la mayoría de las

líneas del fichero de salida han sido omitidas por claridad.

;D: main

;D: {

·

·

·

;R2: <declaraciones> ::= <declaracion>

; TABLA SÍMBOLOS PRINCIPAL · · · ; ;D: scanf

·

·

·

;R1: <programa> ::= main { <declaraciones> <funciones> <sentencias> }

PARTE 5: ANALIZADOR SEMÁNTICO Y GENERADOR DE CÓDIGO El objetivo de esta práctica es finalizar la construcción del compilador para el lenguaje de

programación ALFAi. Para ello, se debe tomar como punto de partida el resultado de la parte 4.

El compilador final requerido deberá traducir programas escritos en lenguaje ALFAi a sus

equivalentes en ensamblador, es decir la entrada al compilador será texto que contenga un

programa ALFAi y la salida del compilador será texto que contenga instrucciones en lenguaje

ensamblador (NASM).

DESCRIPCIÓN DE LA SEMÁNTICA DE LOS LENGUAJES ALFAi En esta descripción sólo se mencionarán los aspectos en los que los lenguajes ALFAi puedan

diferir de otros lenguajes de programación de alto nivel. Se sobreentienden por tanto reglas

semánticas como que las variables deben ser definidas antes de ser utilizadas, o que deben ser

únicas dentro de su ámbito de aplicación.

A continuación se muestran las descripciones correspondientes a todas las versiones del

lenguaje ALFAi de este año. Cada alumno sabe qué parte de las siguientes descripciones debe

tener en cuenta para su lenguaje concreto.

Cualquier duda respecto a la resolución de algún aspecto de la semántica del lenguaje ALFAi,

será resuelta por el profesor de prácticas.

Expresiones lógicas Las restricciones semánticas relativas a las expresiones lógicas son las siguientes:

• En las expresiones lógicas sólo pueden aparecer datos de tipo lógico. Por lo tanto, todas

las subexpresiones, variables y constantes empleadas en una expresión lógica tienen que

ser de ese tipo.

• Debe incorporar los siguientes operadores:

o disyunción

o conjunción

o negación

Expresiones aritméticas

Las restricciones semánticas relativas a las expresiones aritméticas son las siguientes:

• En las expresiones aritméticas sólo pueden aparecer datos de tipo numérico del

permitido en ALFAi. Por lo tanto, todas las subexpresiones, variables y constantes

empleadas en una expresión aritmética tienen que ser de esos tipos.

• Los operadores binarios disponibles para operaciones aritméticas son los siguientes:

o suma,

o resta

o multiplicación

o división

• El operador monádico (unario) disponible para operaciones aritméticas es el cambio de

signo.

Expresiones de comparación Las expresiones de comparación están sujetas a las siguientes restricciones:

• Las comparaciones sólo pueden operar con datos de tipo numérico y el resultado de la

comparación es de tipo lógico.

• Debe incorporar los siguientes operadores

o igualdad

o desigualdad (distinto)

o el primer operando menor o igual que el segundo

o el primer operando mayor o igual que el segundo

o el primer operando menor que el segundo

o el primer operando mayor que el segundo

Asignaciones Las asignaciones válidas son aquellas en las que la parte izquierda y la derecha son del mismo

tipo, y no son tipos de datos estructurados (vectores, conjuntos, pilas, etc).

Semántica de los vectores Las variables de tipo vector tienen la semántica habitual de los lenguajes de programación con

las siguientes peculiaridades:

• Sólo pueden contener datos de tipo básico.

• Sólo son de una o dos dimensiones.

• El tamaño de los vectores de una dimensión no podrá exceder nunca el valor de 64. Esta

misma restricción se aplica a cada una de las dimensiones de los vectores de dos

dimensiones.

• Para acceder a los elementos de los vectores (para cada una de sus dimensiones) se

utilizará cualquier expresión de tipo entero. Esta expresión debe tener un valor entre 0 y

el tamaño definido para el vector menos 1 (ambos incluidos).

• Tras la declaración de una variable de tipo vector, ésta aparecerá siempre indexada, y se

utilizará de la misma manera que cualquier otro objeto que pueda ocupar su misma

posición.

Semántica de los conjuntos Un conjunto es una colección de elementos que tiene las siguientes propiedades:

• Todos los elementos son de tipo entero.

• Los elementos no mantienen una relación de orden.

• No hay elementos repetidos.

• Inicialmente un conjunto está vacío (tiene 0 elementos)

• El tamaño mínimo de un conjunto es 1, y el tamaño máximo es 64 elementos.

Se definen las siguientes operaciones sobre conjuntos:

• Unión

• Intersección

• Inserción

• Vaciado

• Tamaño

• Pertenencia

La unión y la intersección de conjuntos están sujetos a las siguientes restricciones:

• Estas operaciones deben especificar tres identificadores, uno almacenará el resultado de

la operación, y los otros dos son, los operandos.

• Los tres identificadores tienen que haber sido declarados como conjuntos.

• Respecto a las capacidades máximas de los tres conjuntos deben comprobarse las

siguientes restricciones semánticas:

o Para la unión, el conjunto resultado debe tener una capacidad máxima mayor o

igual que la suma de las capacidades máximas de los operandos.

o Para la intersección, el conjunto resultado debe tener una capacidad máxima

mayor o igual que el mínimo de las capacidades máximas de los operandos.

• El resto de la semántica de las operaciones es la de la unión e intersección de conjuntos

habitual en matemáticas.

La inserción de una expresión en un conjunto está sujeta a las siguientes restricciones:

• La expresión tiene que ser de tipo entero.

• El conjunto tiene que estar declarado.

• Si el conjunto no tiene espacio suficiente (está lleno antes de la inserción) debe

detectarse en tiempo de ejecución y salir del programa de manera controlada.

• Se insertará el valor de la expresión teniendo en cuenta la semántica de la operación de

conjuntos habitual en matemáticas: si la expresión ya está en el conjunto, tras la

inserción el conjunto realmente no cambia.

Vaciar un conjunto significa asignar 0 como el número de elementos que contiene.

• El tamaño de un conjunto se refiere al número de elementos que contenga (y no a la

capacidad máxima especificada en su declaración) y, por tanto, es de tipo entero.

La condición de pertenencia de una expresión a un conjunto está sujeta a las siguientes

restricciones:

• La expresión tiene que ser de tipo entero.

• El conjunto tiene que estar declarado.

• La condición de pertenencia de una expresión a un conjunto es de tipo lógico.

• El resto de la semántica de esta operación es la habitual en matemáticas.

Semántica de las listas, colas y pilas Estas estructuras se refieren a las habituales que ya conoce de otras asignaturas. La tabla de

descripción de los lenguajes ALFAi contiene la lista de operaciones y el tipo de dato que las

estructuras tienen que soportar.

Estas estructuras deben poder contener (sin mezclar) los tipos de datos que en la tabla aparecen

como básicos.

Semántica de las estructuras de control de flujo de programa iterativas y condicionales La tabla de descripción de los lenguajes ALFAi contiene las estructuras que deben ser

implementadas en cada caso. Todas ellas son las habituales en otros lenguajes de programación

de alto nivel.

Semántica de las operaciones de entrada/salida La operación de entrada lee datos escalares sobre elementos identificadores o elementos de

vectores.

Se distinguen dos tipos de operaciones de salida, las que operan sobre escalares, y las que

operan sobre colecciones. Se deben proporcionar dos operaciones distintas una para cada tipo de

salida

• La operación de escritura de datos de tipo escalar trabaja con expresiones de tipo lógico

o numérico.

• La escritura de un conjunto, lista, cola o pila, se realizará ubicando todos lo elementos

en la misma línea separados por un espacio en blanco. En el caso de las colas y las

listas, el primer elemento corresponderá al primer elemento de la estructura. Y en el

caso de las pilas, el primer elemento corresponderá a la cima de la estructura.

• La escritura de un vector depende de la dimensión del mismo. Los vectores de una

dimensión se escribirán en una línea separando los elementos por un espacio en blanco.

Los vectores de dos dimensiones se escribirán en forma de tabla, con cada fila en una

línea diferente con los elementos separados por un espacio en blanco.

Semántica de las funciones

Las funciones tienen las siguientes características:

• Sólo se permiten funciones con retorno de tipos básicos (lógico o numérico)

• Los parámetros de las funciones sólo pueden ser de tipos básicos (lógico o numérico)

• Las variables locales de las funciones sólo pueden ser de tipo básico (lógico o

numérico)

• En las sentencias de llamadas a funciones, sólo es necesario comprobar la corrección

del número de argumentos. No es necesario realizar ninguna comprobación de la

correspondencia de tipos.

• En las llamadas a funciones, los parámetros actuales no pueden ser llamadas a otras

funciones.

Gestión de errores semánticos

Los errores semánticos se informarán en la salida estándar de error con el siguiente formato:

ERROR SEMÁNTICO:<nº linea>:<nº carácter>:<descripción del error>

A continuación se presenta un programa de ejemplo cuyo error semántico no depende del

lenguaje concreto utilizado (variable sin declarar)

main

{

int x;

printf y;

}

En la línea 4 aparece una referencia a la variable “y”, que no está declarada en la sección

declarativa. El compilador debe informar de este error semántico con un mensaje de error

similar al siguiente:

ERROR SEMÁNTICO:4:10: Intento de acceso a una variable no declarada (y)

GENERACIÓN DE CÓDIGO El compilador debe traducir los programas válidos escritos en ALFAi a los correspondientes

programas en ensamblador NASM directamente, es decir, no se utilizará en la práctica ninguna

representación intermedia.

Esta generación de código se realizará mediante la asociación de acciones a la reducción de las

reglas de la gramática, descrita previamente en el analizador sintáctico.

En el laboratorio, se explicarán conceptos básicos de NASM para la realización de la práctica.

La gestión de la entrada y salida se realizará mediante la librería auxiliar (alfalib) disponible en

la página web de prácticas. El profesor de prácticas indicará el procedimiento a seguir para

utilizar dichas librerías.

INVOCACIÓN DEL COMPILADOR

El compilador deberá cumplir los siguientes requisitos:

• Nombre del programa fuente que contenga la rutina principal (main) del compilador:

alfa.c

• El ejecutable se invocará de la siguiente manera:

alfa [ <nombre fichero entrada> [<nombre fichero salida>] ]

• Es decir, el programa se puede llamar:

o Con 0 argumentos, entonces se utilizan la entrada y la salida estándares.

o Con 1 argumento, entonces se utiliza la salida estándar y el argumento como

nombre del fichero de entrada.

o 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.

• Descripción del fichero de entrada y de salida:

o El fichero de entrada contiene un programa escrito en lenguaje ALFA.

o El fichero de salida contiene un programa escrito en lenguaje ensamblador

NASM.

NORMAS DE ENTREGA

Debe entregar mediante la web de entregas de prácticas de la escuela un fichero

empaquetado (.zip) que deberá cumplir los siguientes requisitos:

• El fichero zip deberá contener todos los fuentes (ficheros .h y .c) necesarios para

resolver el problema.

• El fichero zip deberá contener las librerías auxiliares disponibles en la web de

prácticas.

• El fichero zip también deberá contener los casos de prueba descritos en la parte

2 de este enunciado. Para el fichero de cada caso utilice los nombres indicados

en esa parte.

• El fichero zip deberá contener un fichero Makefile compatible con la

herramienta make que para el objetivo all genere el ejecutable de nombre alfa.

• El nombre del fichero zip será alfa_gg_pp.zip, donde gg corresponde al grupo

de prácticas y pp al número de pareja. Por ejemplo, el fichero comprimido de la

pareja 5 del grupo Ma se llamará alfa_ma_05.zip

OBSERVACIÓN MUY IMPORTANTE:

Las prácticas que, tras eliminar cualquier fichero con extensión .o así como el propio

ejecutable alfa (en el caso de que dichos ficheros aparezcan en la entrega), no compilen

mediante el comando make all, no generen el ejecutable alfa tras la ejecución de dicho

comando o no cumplan los requisitos descritos en este enunciado se considerarán como

no entregadas.

TABLA DE DESCRIPCIÓN DE LOS LENGUAJES

ALFA1 ALFA2 ALFA3 ALFA4 ALFA5

Tipos básicos Lógico

Entero

Lógico

Entero

Real

Lógico

Entero

Lógico

Entero

Lógico

Entero

Identificadores Longitud menor o igual a 100 caracteres

Constantes Lógicas

Enteras

Lógicas

Reales

Lógicas

Enteras

Lógicas

Entera

Lógica

Enteras

Operaciones

aritméticas

Suma, resta, multiplicación y división

Menos unario

Operaciones

lógicas

Conjunción, disyunción y negación

Comparaciones Igual, distinto, mayor, menor, mayor o igual, menor o igual

Tipo

estructurado

Conjunto Vector 1D

Vector 2D

Lista Pila Cola

Operaciones

tipo

estructurado

• Inserción

• Unión

• Intersección

• Pertenencia

• Vaciado

• Tamaño

• Indexación • Inserción

principio

• Inserción

final

• Extracción

principio

• Extracción

final

• ¿Vacía?

• Vaciado

• Tamaño

• Apilar

• Desapilar

• Cima

• ¿Vacía?

• Vaciado

• Tamaño

• Insertar

• Extraer

• ¿Vacía?

• Vaciado

• Tamaño

Condicional Simple (if)

Bucle Repeat Repeat While While While

E/S Lógico (E/S)

Entero (E/S)

Conjunto (S)

Lógico (E/S)

Entero (E/S)

Real (E/S)

Vector 1D (S)

Vector 2D (S)

Lógico (E/S)

Entero (E/S)

Lista (S)

Lógico (E/S)

Entero (E/S)

Pial (S)

Lógico (E/S)

Entero (E/S)

Cola (S)

Funciones SI

Comentarios SI (de tipo C++ //)

EVALUACIÓN DE LA PRÁCTICA La descripción detallada de las normas de evaluación puede encontrarse en la web de

prácticas. Su profesor, en los laboratorios, completará, explicará y matizará cualquier

aspecto adicional.