CI-1322 Autómatas y compiladores

Tarea #5

Funcionamiento de la calculadora con yylex() obtenido en FLEX

Realizado por :           

Sharon Amador Vargas            A10218  
 Roberto Hernández Montoya    A11727

 

 

Tabla de Contenidos

 

 

Introducción   2

Descripción del problema   2

Problema. 2

Solución. 2

Objetivos. 3

Requerimientos  3

Herramientas usadas  3

Formato del archivo de entrada  3

Formato del archivo de salida  5

Abstracción   5

Clases creadas  5

Implementación   6

Cambios realizados  6

Compilador Usado  6

Cómo compilar el programa  6

Guía de uso del programa   7

Datos de prueba del programa.. 7

Código fuente   9

Bibliografía   36

 

 


 

 

Introducción

 

            El analizador léxico es la primera fase del compilador. Se encarga de leer los caracteres de entrada y elaborar con ellos una salida de componentes léxicos, que utiliza el analizador sintáctico. El análisis léxico permite simplificar la compilación de un programa, mejora la eficiencia y la transportabilidad del compilador.

Se han desarrollado algunas herramientas para construir analizadores léxicos, en esta tarea se utiliza FLEX, para el cual la especificación de su entrada está en lenguaje LEX. Con el uso de Flex, se pretrende mostrar cómo, utilizando expresiones regulares, se puede combinar la especificación de patrones con acciones, cuya ejecución se pueda pedir a un analizador léxico.

En esta tarea se ejemplifica el uso de un analizador léxico, aplicado en la tarea anterior.

 


 

 

Descripción del problema

Problema  

Modificar la su solución de la cuarta tarea para que use un analizador léxico obtenido con Lex/Flex.

 

Solución

            El problema se soluciona creando un analizador léxico con el programa Flex, al cual le corresponde el archivo lex.yy.c . Luego este archivo se incorpora al proyecto de la tarea anterior y se modifica el funcionamiento de la calculadora para que use el nuevo analizador léxico, invocando al método yylex(). Se elimina la clase Astring y se sustituye su uso por punteros a char. También se elimina la clase Token, la cual funcionaba como analizador léxico.

 

Objetivos

R      Crear un analizador léxico con la herramienta Flex.

R      Modificar la calculadora de la tarea anterior para que use el método yylex, definido en el analizador léxico.

 

Requerimientos

R      La tarea anterior no debe tener errores.

R      Se debe conocer el funcionamiento de la tarea anterior para poder modificarla sin dañar el funcionamiento.

 


 

 

Herramientas usadas

 

            La principal herramienta que se usó fue el generador de analizadores léxicos Flex.

Como se puede observar en la figura 1,  Flex recibe en el archivo de entrada las definiciones en lenguaje LEX y produce como salida un archivo en C, que define la rutina yylex().

 

 

 

 

 

 

 

lex.yy.c

 

lex.yy.obj

 
 

 

 

Fig. 1. Creación de un analizado léxico con FLEX

 
 

 


Formato del archivo de entrada

El programa en LEX consta de tres partes:

declaraciones

%%

reglas de traducción

%%

procedimientos auxiliares

 

 

 

Para el caso de la calculadora el archivo de entrada fue:

%{

/*definición de constantes*/

 #define OP_SUM 321

 #define OP_MUL 322

 #define NUM 323

 #define P_ABRE 324

 #define P_CIERRA 325

 #define ERROR 666

 #define FIN 999

 

%}

/*definiciones regulares*/

delim  [ \n\t]

eb     {delim}+

digito [0-9]

numero {digito}+(\.{digito}+)?

 

%%

{eb}      {/*espacio en blanco, no hace nada*/}

{numero}  {return(NUM);}

"*" {return(OP_MUL)}

"/" {return(OP_MUL)}

"-" {return(OP_SUM)}

"+" {return(OP_SUM)}

"(" { return(P_ABRE); }

")" { return(P_CIERRA); }

%%

 

void main () {

    yylex();  

}     

 

En la primera parte se definen las constantes que se van a usar en el programa.

En las definiciones regulares, se especifica un delimitador como un espacio en blanco, una tabulación o un cambio de línea, luego un espacio en blanco consiste en cero o más delimitadores. También se especifican los dígitos, y los números como secuencias de dígitos con una parte decimal opcional.

Finalmente se presentan las reglas de traducción para cada expresión regular.        

 

¿Cómo funciona LEX?

 

Cuando el analizador léxico se está ejecutando, analiza la entrada buscando cadenas de caracteres que concuerden con uno de sus patrones definidos. Una vez que lo ha encontrado, lo hace disponible a través de la variable global yytext, que es un puntero a caracter. Su longitud se encuentra en el entero global yyleng. Luego se ejecuta la acción correspondiente.

Formato del archivo de salida

            Flex genera el archivo de salida lex.yy.c, el cual contiene la rutina yylex(), un número de tablas usadas para encontrar los tokens, y ciertas rutinas auxiliares y macros. Cada vez que se hace un llamado a yylex, éste revisa los tokens del archivo de entrada hasta que ejecute alguna acción o sea fin de archivo.

 

 


 

 

Abstracción

Clases creadas

            Clase nodo

h       Especificación de la clase:

Especifica los nodos que va a contener la lista

h       Métodos y variables:

public:

·        nodo()= Constructor

·        nodo(double num)= inicializa un nodo con un número double

·        nodo(char oper)= inicializa un nodo con un operador algebraico

·        int esoperador() = devuelve verdadero si el nodo contiene un operador

·        int esnumero()= devuelve verdadero si el nodo contiene un número

·        nodo * sig;

·        double numero;   

·        char operador;

Clase posfiex

h       Especificación de la clase:

 Lista en que se guarda la cadena en posfijo para evaluarla

h       Métodos y variables:

public:

·        posfiex()//inicializa la lista con el primero en nulo

·        void insertarnu(char * numero)= inserta un número en un nodo al final de la lista

·        void insertarop(char * operad) = inserta un operador en un nodo al final de la lista

·        nodo * prim() = devuelve un puntero al nodo primero        

private:

·        nodo * primero = el primero de la lista

 


 

 

Implementación

Cambios realizados

1.      Se eliminan la clase Token y la clase Astring, y todas las instancias de estas clases se cambian a punteros a char.

2.      Agregamos dos nuevas variables : int tokenact que mantiene el token actual (del lexema que está en preanálisis) y posfiex lista que es la lista en que se guarda la cadena en posfijo para evaluarla.

3.      Nuevos métodos:

h       void Calculadora::inicio() = inicializa todas las variables y estructuras y llama a Calculadora::Trabaje()

4.      En lugar de la función aparea() se hace una asignación a tokenact con el resultado de yylex().

Compilador Usado

Visual C++ 6.0 Microsoft Compiler.

Cómo compilar el programa

               Se proveen tres archivos necesarios para la compilación del programa: CLC5.cpp, lex.yy.c y LIBFLEX.lib.

Para compilar el programa se debe crear un nuevo proyecto de consola en Visual C++ y luego agregar al proyecto los dos primeros archivos. Luego se debe agregar la librería de la siguiente forma:

Se elige del menú principal Project, luego Settings.

 

 

 

 

 

 

 

 

 

Fig. 2. Opción del menú

 
 


En la opción de Link se debe agregar la librería en la parte de Object/Library modules, como se muestra en la figura 3.

 

 

Por último se compila el proyecto.

Fig. 3. Agregar la librería.

 
 

 



 

 

Guía de uso del programa

 

  1. El programa solicita introducir la expresión

 

  1. Se despliega la expresión en infijo, en posfijo y finalmente el resultado.

 

 

 


 

 

Datos de prueba del programa

 

Los datos de prueba del programa fueron

R      (2+4)

R      (6*8)

R      ((2+4)*(6+8))

 

Salidas del programa

R      (2+4)

R      (6*8)

 

R      ((2+4)*(6+8))

 

 

 

 


 

Bibliografía

 

 

 

 

Aho, A. et al. Compiladores: principios, técnicas y herramientas. Addison Wesley.1990