Você está na página 1de 11

ESCUELA UNIVERSITARIA DE INGENIERA TCNICA INFORMTICA DE OVIEDO CURSO ACADMICO: 2005-2006

TEORA DE AUTMATAS

Prctica 3: Analizador Sintctico

PRELIMINARES

Al igual que en la prctica anterior vamos a trabajar en Petra bajo el sistema operativo Linux. La herramienta que vamos a conocer es CUP, que se encuentra instalada. Por tanto, es necesario que se conecte a Petra, donde ya tiene abierta una cuenta por ser alumno de la EUITIO. Para conectarse desde Windows puede usar el programa putty y en el cuadro de texto Host Name, escribir petra.euitio.uniovi.es Para comenzar a trabajar, en primer lugar crearemos un directorio llamado practica3 y ser ah donde realizaremos la prctica. Para crear el directorio, puede hacerlo con la siguiente orden mkdir practica3. Para situarse en el directorio recin creado, puede ejecutar cd practica3. A partir de este momento trabajaremos siempre en este directorio. En primer lugar, copiaremos en l los ficheros de trabajo con la siguiente orden (3 palabras): cp /var/www/asignaturas/teo.aut/practicas/Practica3/* . Para ver los ficheros que tiene en el directorio, puede utilizar la orden dir o la orden ls al. Cuando necesite editar y/o modificar un fichero, puede utilizar cualquiera de los editores de texto que estn instalados en Petra (vi, emacs, ...). Quiz el que resulte ms sencillo si nunca ha trabajado en un entorno Linux es joe. Para abrir un fichero que se llame "fichero.txt" basta con ejecutar joe fichero.txt (si fichero.txt no existe, lo crea) y ya puede escribir en l. Para grabar los cambios y salir del programa basta con pulsar "Ctrl+k" y luego "x". Puede acceder a la ayuda pulsando "Ctrl+k" y luego "h" Por ltimo, si nota un comportamiento raro en el editor (la pantalla no se desplaza bien, parece que desaparecen caracteres,...) es posible que tenga que indicar el tipo de terminal que estamos usando escribiendo: export TERM=vt100 Para terminar la sesin en petra, no olvide: exit

CUP: GENERADOR DE ANALIZADORES SINTCTICOS

2.1 CUP
CUP es una utilidad disponible para LINUX que es capaz de generar analizadores sintcticos, es decir, construye, de forma rpida y sencilla programas que analicen las cadenas que aparecen en un fichero de texto y compruebe que son sintcticamente correctas con respecto a una determinada gramtica. El analizador sintctico que generemos utilizando CUP podr, adems del anlisis, realizar diversas acciones segn se vallan reconociendo las cadenas. Realmente este tipo de herramientas estn pensadas para construir compiladores y por tanto son de gran potencia y flexibilidad. CUP sigue una forma de funcionamiento similar a la del JLex: toma como entrada un fichero de especificacin en el que se incluye una gramtica y genera un analizador sintctico escrito en java que, lgicamente, podremos compilar y ejecutar. Grficamente el esquema de funcionamiento para trabajar con Cup es el siguiente:
CUP

Fichero de especificacin Asintactico.cup (la gramtica)

Analizador sintctico (cdigo Java) Asintactico.java

javac

Fichero de Texto a analizar ENTRADA.TXT

Analizador sintctico (cdigo ejecutable)

Resultado del anlisis

El analizador sintctico construido procesar el fichero de texto que queramos analizar (entrada.txt) comprobando que su contenido es sintcticamente correcto con respecto a la gramtica que habremos especificado en el fichero de entrada para CUP.

2.2 CONSTRUCCIN DEL ANALIZADOR SINTNTICO


Veamos cmo se realiza este proceso de construccin de un analizador sintctico mediante el uso de Cup. Los pasos son los siguientes: 1. Se edita un fichero de texto que se suele denominar fichero de especificacin (A_sintactico.cup) para CUP, en el que se especifica, fundamentalmente, una gramtica (VT, VN, S, P). Para ello diremos cules son los smbolos terminales (VT), los no-terminales (VN), el axioma o smbolo inicial de la gramtica (S) y por ltimo el conjunto de reglas de produccin o gramaticales. Adems podremos incluir cdigo java que podr ser ejecutado posteriormente en el proceso de anlisis.

2. Se ejecuta CUP dndole como entrada el anterior fichero de especificacin. En caso de no encontrar errores CUP genera un programa escrito en java que contiene el analizador sintctico que pretendemos construir. java java_cup.Main a_sintactico.cup Genera dos ficheros java que implementan el analizador sintctico: parser.java y sym.java. 3. Como ya comentamos anteriormente los analizadores sintcticos se complementan con los analizadores lxicos. La idea es que al analizar sintcticamente un texto (un posible programa) el analizador sintctico le pide al lxico que vaya leyendo el texto y que le diga qu es lo que va encontrando, por ejemplo: un nmero real (3.4e7), un entero (123), un identificador (resul), un operador de menor o igual (<=), etc. De esta forma el analizador sintctico se despreocupa de esta labor de ir identificando dichos smbolos y lo que va recibiendo del lxico son directamente los smbolos terminales de la gramtica (llamados tokens) y que suelen estar formados por varios caracteres. Por este motivo a la hora de construir en analizador sintctico le tenemos que proporcionar un analizador lxico con el que deber coordinarse. JLex como CUP estn pensados para trabajar conjuntamente, por tanto tendremos que generar el analizador lxico con Jlex y despus compilarlo con el sintctico. Sin entrar en detalles internos vamos a ver cmo realizar este proceso. Primero escribiremos el fichero de especificacin para JLex: a_lexico.lex y lo compilamos con el JLex con la orden java JLex.Main a_lexico.lex con esto obtenemos el fichero a_lexico.lex.java que renombraremos a Yylex.java con la orden mv a_lexico.lex.java Yylex.java ahora ya tenemos los ficheros necesarios para construir nuestro analizador definitivo. 4. Se compilan los ficheros anteriores para obtener nuestro analizador sintctico en cdigo ejecutable con la orden javac -d . parser.java sym.java Yylex.java

2.3 UTILIZACIN DEL ANALIZADOR CONSEGUIDO


Para probar el analizador sintctico que hemos construido slo tendremos que ejecutar la siguiente orden y darle por teclado el texto a analizar. java parser

Tambin podremos editar un fichero (mifichero.txt) con el texto a analizar y pedirle a nuestro parser (nombre ingls para designar a los analizadores sintcticos) que nos lo analice mediante la orden java parser < mifichero.txt

FICHERO DE ESPECIFICACIN PARA CUP


El formato de un fichero de especificacin para CUP contiene cinco secciones: Sentencias import y package Cdigo de usuario Lista de smbolos terminales y no terminales Declaraciones de precedencia Gramtica

Nosotros vamos a centrarnos en las tres ltimas.

3.1 LISTA DE SMBOLOS TERMINALES Y NO TERMINALES


Cada terminal y no terminal se representa en tiempo de ejecucin con un objeto de tipo Symbol. En el caso de los terminales, son generados por el analizador lxico que podra poner el valor del terminal en el campo variable, pero para no entrar en demasiadas complicaciones esto lo veremos ms claramente con el ejemplo que incluimos (movelan.lex y movelan.cup). La declaracin de smbolos terminales y no terminales tiene la forma: terminal NombreClase nombre1, nombre2, ; non terminal NombreClase nombre1, nombre2, ; terminal nombre1, nombre2, ; non terminal nombre1, nombre2, ; NombreClase representa la clase del valor asociado al terminal o no terminal. Por ejemplo si queremos definir un no-terminal llamado NUM_INT y que tenga asociado un entero, deberamos incluir en nuestro fichero: terminal Integer NUM_INT; Sin embargo para el terminal O_REP no necesita tener asociado un tipo de dato concreto, por lo que podremos sencillamente: terminal O_REP; Tambin podemos asociar un tipo de dato a un smbolo no-terminal. Si quisiramos que un smbolo no-terminal ORDEN tenga asociado un tipo de dato entero (por ejemplo, la coordenada x de la posicin actual), entonces lo especificaremos de la forma: non terminal Integer ORDEN; Supongamos que definimos la orden de giro con la regla de produccin 6

ORDEN O_GIRO NUM_FLOAT U_GIRO y definimos en nuestro analizador lxico las expresiones regulares asociadas a la orden de giro, a los nmeros flotantes y a las unidades de giro (grados y radianes). Ahora cuando analicemos una cadena como Rot 34 gra, el analizador lxico le comunicar al analizador sintctico que Rot, "34" y "gra" son smbolos terminales de tipo "O_GIRO", "NUM_FLOAT" y "U_GIRO respectivamente; el analizador sintctico descubrir que la cadena introducida responde a la regla ORDEN O_GIRO NUM_FLOAT U_GIRO.

3.2 DECLARACIONES DE PRECEDENCIA Y ASOCIATIVIDAD DE TERMINALES


Aunque en esta primera prctica de CUP no utilizaremos la capacidad de definir la precedencia de los operadores y la asociatividad, vamos a explicar un poco para qu se usa esta seccin. Esta seccin es til en el caso de gramticas ambigas. Por ejemplo, si la entrada fuese repetir 3 + 4 * 8, el analizador no sabra si realizar antes la suma o la multiplicacin. Por el momento diremos que hay tres tipos de declaraciones de asociatividad/precedencia: precedente left precedente right precedente nonassoc terminal, terminal,; terminal, terminal,; terminal, terminal,;

El orden de precedencia de menor a mayor es de arriba abajo. As, precedence left ADD, SUB; precedence left DIV, MUL; indica que la divisin tiene una precedencia mayor que la suma. Por tanto, en 3+4*8 se resolvera antes la multiplicacin y luego la suma. Aquellos smbolos para los que no se indique precedencia, tienen la ms baja. En el caso de conflictos que no se pueden resolver con la precedencia: 3*4/8, es conveniente indicar la asociatividad (right, left o nonassoc de los terminales). En el caso de asociatividad a la izquierda (left) se comienza a resolver de izquierda a derecha. Y a la inversa para la asociatividad a la derecha. Si se declara nonassoc, entonces, dos ocurrencias consecutivas de smbolos con igual precedencia generan un error.

3.3 LA GRAMTICA
Esta seccin comienza, opcionalmente, con: 7

start with no-terminal; Si no se explicita un smbolo de arranque, se usa el smbolo en la parte izquierda de la primera regla. A continuacin, se escriben las reglas. Cada produccin en la gramtica tiene una parte izquierda (smbolo no terminal), seguida del smbolo ::=, seguido de cero o ms acciones, smbolos terminales, no terminales, y terminado en ;. Cada smbolo que se utilice en el lado derecho puede, opcionalmente, estar etiquetado con un nombre (smbolo:etiqueta). Los nombres de las etiquetas deben ser nicos en la produccin y representan el valor del smbolo. As, por ejemplo: NUM_INT:e (smbolo NUM_INT, valor del smbolo e). Estas etiquetas pueden utilizarse en el cdigo. La parte izquierda de cada produccin es siempre etiquetada de forma implcita con la etiqueta RESULT. Si hay varias producciones para un smbolo no terminal, deben declararse juntas y se separan con barra vertical | . Las acciones que aparecen en la parte derecha de una regla son cdigo Java entre los delimitadores {: y :}. Este cdigo es ejecutado por el parser cuando se aplica la regla asociada. Las etiquetas no vamos a utilizarlas en esta prctica, pero las necesitaremos en la siguiente prctica para poder evaluar expresiones. Como ejemplo vamos a ver cmo se introducen la regla que nos define que una instruccin se forma como una orden y el smbolo de fin de instruccin. Para ello necesitaremos los smbolos no-terminales orden e instruccion y el terminal FIN_SENT: instruccion ::= orden FIN_SENT;

EJEMPLO DE EJECUCIN CON CUP

Antes de ver el primer ejemplo debemos haber copiado los ficheros que vamos a utilizar desde el directorio de la asignatura tal y como se dijo en el primer apartado. La especificacin del analizador lxico est almacenada en el fichero movelan.lex y la especificacin del analizador sintctico est en el fichero movelan.cup, entonces deberemos escribir en la lnea de comandos java JLex.Main movelan.lex mv movelan.lex.java Yylex.java java java_cup.Main movelan.cup javac -d . parser.java sym.java Yylex.java java parser < programa1.entrada (donde programa1.entrada debe ser un fichero de prueba escrito en el lenguaje definido) o java parser (esta ltima opcin espera la entrada por teclado)

EJERCICIOS

5.1 EJERCICIO 1
Lo primero que debe hacer es probar las rdenes que hemos puesto en el captulo anterior y explicar qu ocurre cuando ejecuta con el fichero de prueba PruebaMovelan

5.2 EJERCICIO 2
Ahora vamos a aadir a nuestra gramtica la orden de repetir. La sintaxis de la orden es repetir <una_orden> un_numero_entero_de_veces Para ello utilizaremos los ficheros anteriores (previamente haremos una copia de seguridad cp movelan.lex movelan2.lex cp movelan.cup movelan2.cup) En el fichero movelan2.lex aada el smbolo O_REP y sustituya la salida por pantalla por las acciones necesarias para enviar el smbolo anterior al analizador sinttico. En el fichero movelan2.cup es donde debe declara el nuevo smbolo terminal e incluir las reglas correspondientes a la operacin de repetir. Explique qu es lo que pasa si ejecuta java parser < PruebaMovelan2

5.3 EJERCICIO 3
Las modificaciones del ejercicio 3 vamos a realizarlas sobre los ltimos ficheros conseguidos aunque, antes de nada, haremos una copia de seguridad: cp movelan2.lex movelan3.lex cp movelan2.cup movelan3.cup Estas modificaciones estn destinadas a incluir en nuestra gramtica los parntesis. As, a partir de ahora, una orden tambin es vlida si va entre parntesis. Por ejemplo (AVA 34 cm); Para ello debe definir en su fichero de especificacin de JLex dos nuevos smbolos terminales (ABREPARENT y CIERRAPARENT) asociados lgicamente a los caracteres ( y ) y sustituir las acciones de impresin por pantalla por las necesarias para transmitir esos smbolos al analizador sintctico.

Por otro lado tiene que modificar el fichero de especificacin cup. Edtelo y modifquelo para incluir la informacin de los nuevos smbolos terminales y la regla gramatical correspondiente. Por ltimo explique qu pasa cuando ejecuta java parser < PruebaMovelan3

5.4 EJERCICIO 4
Las modificaciones del ejercicio 4 vamos a realizarlas sobre los ltimos ficheros conseguidos aunque, antes de nada, haremos una copia de seguridad: cp movelan3.lex movelan4.lex cp movelan3.cup movelan4.cup Estas modificaciones estn destinadas a incluir en nuestra gramtica la posibilidad de crear rdenes compuestas con el operador Y. As, a partir de ahora, una orden tambin es vlida si est formada por la concatenacin mediante el operador anterior de dos o ms rdenes simples. Por claridad, se sugiere que las rdenes a concatenar las ponga entre parntesis. Por ejemplo (AVA 34 cm) Y (RET 24 m); Para ello debe aadir en su fichero de especificacin de JLex un nuevo smbolo terminal (AND) asociado lgicamente al carcter Y o y. Luego, aada la regla necesaria para enviar el smbolo al analizador sintctico cuando aparezca en el fichero de entrada. Por otro lado tiene que modificar el fichero de especificacin cup. Edtelo y modifquelo para incluir la informacin de los nuevos smbolos terminales y la regla gramatical correspondiente. Por ltimo explique qu pasa cuando ejecuta java parser < PruebaMovelan4

Você também pode gostar