Professional Documents
Culture Documents
Requisitos: Haberse ledo la introduccin a Flex y Bison que est en la pgina Web de la asignatura (aunque no es necesario mirar la parte de condiciones de arranque de Flex ni la parte de semntica, precedencia de operadores ni la seccin sobre la coleccin de tipos de valores de la parte de Bison). Tambin es conveniente mirar algo de documentacin sobre Make. En la web de la asignatura tenis enlaces a un tutorial y a la documentacin.
Uso de Make
A continuacin se muestra un fichero Make, muy bsico, para compilar un fichero de Flex que se llame p0.l
p0: lex.yy.c gcc lex.yy.c lfl L/opt/flex/lib -o p0 lex.yy.c: p0.l flex p0.l
Si llamamos a este Makefile p0_Makefile, por ejemplo, la siguiente lnea de comandos generar el fichero ejecutable p0:
$make f p0_Makefile
En las prcticas de Compiladores I es necesario entregar un Makefile correcto con cada prctica. Tenis un ejemplo ms completo de Makefile en
/users2/COMPI/salidas/ejemploMake
Teora (concatenacin de e.r., aunque generalmente no ponemos nada) | (unin de e.r.) * (cerradura de Kleene) + (cerradura positiva) ( ) (parntesis) {a,b,c,d,0,1,2} (conjunto formado por los smbolos a,b,c,d,0,1 y 2) |a
Flex No hay smbolo. Las e.r. a concatenar se escriben pegadas como en la notacin de teora. | * + () [abcd012] o tambin [a-d0-2] a? El smbolo a, cero o una veces. No hay equivalente directo en Flex. Para usarlo como parte de una expresin, se usan los smbolos * ? que permiten repetir algo cero veces (ver lnea anterior).
Salida:
Este es un texto<EOL> con varios blancos<EOF>
Donde los patrones son expresiones regulares en formato Flex y las acciones son el cdigo C que se ejecuta cuando Flex encuentra concordancia entre algn patrn y el texto que se le presente. El siguiente fichero Flex resolver el ejercicio. Creadlo y llamadlo ej1.l
%% [\t ]+$ ; /* Blancos a final de linea */ [\t ]+ { printf(" "); /* Grupos de blancos*/ }
ej1: lex.yy.c gcc lex.yy.c lfl L/opt/flex/lib -o ej1 lex.yy.c: ej1.l flex ej1.l
Notad que el Makefile indica que hay que invocar a Flex para convertir ej1.l en un fichero C (lex.yy.c) y luego llamar al compilador gcc para generar el ejecutable ej1. La siguiente lnea genera el ejecutable:
$make f p0_ej1_Makefile
El cursor parpadea esperando que escribis el texto de entrada. Si escribs por ejemplo ___a____b_____ (sustituyendo los guiones por espacios) y pulsis <Entrar>:
$./ej1 a b a b
El programa sustituye los grupos de espacios por uno solo y elimina los de final de lnea (esto ltimo no se ve; podis modificar el fuente para que en lugar de espacios busque y sustituya guiones para poder comprobarlo mejor). Esta forma de trabajar no es muy cmoda, porque hay que escribir el texto de entrada lnea a lnea. Una solucin es crear un fichero de texto con la entrada y pasrselo al ejecutable. Si por ejemplo hemos creado un fichero llamado entrada.txt, esta lnea de comandos lo procesar completo y escribir la salida por pantalla:
$./ej1 < entrada.txt
Ejercicio 2 - Flex
Elaborar un programa en Flex que copie el archivo de entrada en uno de salida, sustituyendo todo numero entero positivo que sea mltiplo de 7 por el carcter *. Para ello se sugiere construir una e.r. que lea nmeros en decimal, y despus en la accin asociada en Flex comprobar si stos son mltiplos de 7.
Ejercicio 3 - Flex
Elaborar un programa en Flex que cuente el nmero de palabras del texto de entrada que contengan alguna vez la letra w. Cmo sera la e.r.? Y como sera si nos piden las palabras que contengan slo una w?
Ejercicio 4 - Flex
Elaborar un programa en Flex que dada una secuencia de entrada, realice lo siguiente para cada uno de los casos:
Informar del nmero de caracteres, de palabras y de lneas de texto. Reconocer todos los nmeros enteros y calcular e informar de la media de los mismos. Reconocer todos los nmeros reales e informar cuntos de ellos estn comprendidos en el rango entre cero y uno. La principal dificultad de este ejercicio, est en notar que los nmeros son tambin palabras, y adems estn compuestos por caracteres, sin embargo un carcter del fichero de entrada en Flex slo se puede emparejar con, como mucho, un patrn (una e.r.).
Ejercicio 5 - Flex
Elaborar un programa con Flex que dado un fichero de texto, verifique que siempre que se abre un parntesis, se cierra. Si detecta algn error, informar de la lnea donde se produce dicho error. Este ejercicio tiene una dificultad: Es el lenguaje de las palabras sobre el alfabeto {(,)} que son pares de parntesis correctamente anidados regular? Podis demostrarlo? Si no es regular, podemos hacer algo?
Supongamos que queremos reconocer las palabras del lenguaje formado por las expresiones enteras con parntesis que utilizan + y * (por ejemplo 4, 4 + 2,(4 + 3) * 5 etc.) : Para ello podramos crear una gramtica libre de contexto muy sencilla: ST|T+T|T*T T ENTERO | ( S ) Que traducida a un fuente bsico de Bison sera:
%token PARIZ PARD MAS POR INTEGER %start S %% S: T | T MAS T | T POR T ; T: INTEGER | PARIZ S PARD ;
Pero adems, necesitaramos un fichero fuente de Flex (fuente.l) que lea la entrada estndar y reconozca las ocurrencias de los diferentes tokens de nuestra gramtica, es decir:
%{ #include "y.tab.h" /* GENERADO AUTOMTICAMENTE POR BISON */ %} %% [\-]?[0-9]+ return(INTEGER); \+ \* \( \) \n [ \t] return(MAS); return(POR); return(PARIZ); return(PARD); return(0); {/* ignorar blancos y tabuladores */}
Aadimos algunas definiciones de funciones necesarias al fuente de Bison (fuente.y) , que quedara como sigue:
%token PARIZ PARD MAS POR INTEGER %start S %% S: T | T MAS T | T POR T ; T: INTEGER | PARIZ S PARD ;
ej6 contiene ahora un ejecutable que reconoce todas las expresiones enteras bien escritas. Este ejecutable puedes utilizarlo desde teclado como desde un fichero (redirigiendo la entrada, igual que se hace con Flex cuando est solo). Si la entrada es una palabra del lenguaje, no da ninguna salida. Si la entrada no est en el lenguaje, el resultado ser parse error. El siguiente fichero Makefile nos facilitar la compilacin:
LEX=flex YACC=bison CC=gcc ej6: y.tab.o lex.yy.o $(CC) -o ej6 y.tab.o lex.yy.o -ly -lfl -L/opt/flex/lib lex.yy.o: lex.yy.c y.tab.h $(CC) -c lex.yy.c y.tab.o: y.tab.c $(CC) -c y.tab.c y.tab.c y.tab.h: ej6.y $(YACC) -yd ej6.y lex.yy.c: ej6.l y.tab.h $(LEX) ej6.l
Ejercicio 7 Flex/Bison
Utilizad Bison para generar ejecutables que reconozcan los siguientes lenguajes. Esto quiere decir que para las palabras del lenguaje la salida debe ser vaca y para las que no pertenecen al lenguaje parse error. 1) L = { ai bj cj di | i,j 1 }
7
2) L = { 0m 1n | m > n 0 } Nota: cuidado con el nombre que le dais a los tokens en Bison. Si los llamis a, b, c etc., se producen colisiones con algunas variables internas de Flex. Es mejor que los llamis de forma algo ms complicada como t_a, t_b etc.
Puede haber etiquetas que aparezcan sin etiqueta de cierre, pero es obligatorio que stas lleven una barra (/) al final (se les llama elementos vacos):
<ETIQUETA/>
Los elementos pueden tener atributos en sus etiquetas de apertura (o en su nica etiqueta si son elementos vacos). Los atributos tienen valores que deben ir entre comillas, ya sean dobles o simples. Si hay varios atributos, tienen que ir separados por al menos un espacio (o tabulador, fin de lnea...).
<ETIQUETA ATRIBUTO = "Valor" ATRIBUTO2 = Valor2>
Los documentos XML deberan empezar con una declaracin de XML que especifique la versin del estndar que cumple el documento (esta declaracin puede llevar otros atributos, pero son opcionales):
<?xml version="1.0"?>
El documento debe tener un elemento raz (y slo uno) que englobe a todos los dems entre una etiqueta de apertura y una de cierre. Los elementos englobados por otro se llaman sub-elementos de ste, o sus hijos. Todas las etiquetas de apertura deben tener su correspondiente etiqueta de cierra para los elementos que contengan a otros, o que contengan datos. Si aparece una etiqueta sola, debe tener una barra (/) al final de su texto (se llama elemento vaco). Entre dos etiquetas puede haber nada, espacios, texto y/o otras etiquetas. No pueden aparecer dentro del texto de un elemento (entre otros):
< (en su lugar poner < )
Los elementos deben anidarse correctamente. Es decir, la etiqueta de cierre de un elemento hijo de otro, debe aparecer antes que la etiqueta de cierre de su elemento padre. Si aparecen atributos en algn elemento tienen que tener un valor, y ste debe ir entre comillas (dobles o simples).
XML vlido
Un documento XML vlido es aquel que adems de bien formado, es conforme a cierta estructura previamente establecida. Esta estructura se especifica en forma de definicin de tipo de documento (DTD) o mediante un esquema (Schema) que es el mtodo ms reciente y ms potente. Un DTD o un esquema son fundamentalmente, una gramtica que especifica qu elementos pueden/deben aparecer en un documento XML y como deben estar estructurados (los esquemas son ms potentes y permiten definir con mucha precisin tipos de datos vlidos en los elementos y atributos, cardinalidades complejas etc.). En esta prctica no entraremos para nada en la validez de documentos XML.
Notas: Esta no es, ni mucho menos, la nica o la mejor manera de analizar la entrada. Slo es una que funciona razonablemente, es bastante completa y no es muy compleja. Los identificadores de etiqueta son parecidos a los de un lenguaje de programacin tpico, pero admiten expresamente cosas como dos puntos (:). Si una etiqueta admite atributos y lleva varios, deben estar separados por espacios. Ignoramos comentarios y espacios, salvo los que van entre los atributos que los trataremos dentro de la e.r. de la etiqueta que sea, dado que en general podemos organizar las etiquetas en un documento con margen para usar tabulaciones, espacios y fines de lnea para indentarlo, y los comentarios los podemos poner ms o menos donde queramos. La e.r. CDATA se emparejarn con el texto libre que podemos escribir entre etiquetas. Se admite casi cualquier carcter (incluyendo espacios, saltos de lnea,
10
Tratamos de forma distinta espacios y CDATA (que puede llevarlos), porque CDATA debe aparecer en nuestra gramtica, hay sitios donde es aceptable y sitios donde no, y los espacios, en general y salvo entre atributos, podremos ignorarlos y no devolvrselos a Bison, lo que facilita bastante la tarea. Devolvemos especficamente un token cuando encontremos un carcter que no se ha emparejado antes, porque casi con seguridad ser un error del fichero XML y de esta forma es ms sencillo que Bison lo detecte (aunque el token no aparecer en ningn sitio en la gramtica de Bison).
Pruebas
En el directorio /users2/LGA/salidas/pract4 tenis varios ficheros XML que podis usar para hacer pruebas: bueno1.xml hasta bueno4.xml son ficheros de tamao y complejidad creciente que vuestro analizador deber considerar como correctos (y que efectivamente son ficheros XML bien formados, el ltimo de ellos un ejemplo real, mnimamente simplificado, de la descripcin de un servicio web). fallo1.xml hasta fallo6.xlm son ficheros con distintos errores (slo un error en cada fichero) que vuestro analizador deber considerar como incorrectos (y que
11
problema1.xml ilustra el principal problema que tiene el analizador, y es que el fichero es incorrecto (la etiqueta de apertura y de cierre son distintas) pero el analizador lo considerar correcto al no poder tener en cuenta cual es el nombre de las etiquetas.
12