CI-1322
Autómatas y compiladores
Funcionamiento
de la calculadora con yylex() obtenido en FLEX
Realizado por
:
Sharon Amador Vargas A10218
Roberto Hernández Montoya A11727
Formato del archivo de entrada
Datos de prueba del programa..
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.
Modificar
la su solución de la cuarta tarea
para que use un analizador léxico obtenido con Lex/Flex.
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.
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.
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.
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
|
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.
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.
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;
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
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().
Visual
C++ 6.0 Microsoft Compiler.
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.
Los datos de prueba
del programa fueron
R
(2+4)
R
(6*8)
R
((2+4)*(6+8))
R
(2+4)
R
(6*8)
R
((2+4)*(6+8))
Aho, A. et al. Compiladores: principios,
técnicas y herramientas. Addison Wesley.1990