1. CIS-IXB-001
UNIVERSIDAD
NACIONAL
DE LOJA
´Area de la Energ´ıa las Industrias y los Recursos Naturales No Renovables
Carrera de Ingenier´ıa en Sistemas
C¸ OMPILADOR DIVISOR DE
CANTIDADES”
MODULO IX B
Autores:
SORAYA ISAMAR LARA TAPIA
Docente:
ING. HENRY PAZ
Fecha:
13 FEBRERO 2014
Loja-Ecuador
Septiembre 2014 - Julio 2015
1
3. 1. Problema:
Un compilador que permita dividir en partes iguales el total de una cantidad de dinero
para un numero determinado de personas las cuales tienen que ser diferentes de cero.
1.1. Ejemplo
35 / 5 igual 7
2. Aut´omata
a continuaci´on presentamos la representaci´on del aut´omata el cual representa la es-
tructura del compilador Figura 1.
Figura 1: Aut´omata del compilador
3. Desarrollo
Para el desarrollo del compilador se esa utilizando la librer´ıa JFLEX y CUP.
4. JFlex
Es una herramienta desarrollada en Java, la cual genera un programa en Java a partir
de una especificaci´on en el que se indican los tokens permitidos por nuestro lenguaje.
Un archivo de especificaci´on para JFLex esta organizado en tres secciones, separadas
por: “ % % ”.
3
4. 4.1. C´odigo de usuario.
En esta secci´on se crean las clases necesarias para nuestro analizador l´exico, las cuales
ser´an copiadas directamente al inicio del archivo de salida. Se importan los paquetes
necesarios.
Primero se declara el nombre del paquete en el cual esta contenido. Figura 2.
Figura 2: C´odigo de usuario
4.2. Directivas JFLex.
En esta secci´on se incluyen algunas reglas propias de JFLex. Tambi´en se pueden definir
macros, que resuman ciertas expresiones regulares que nos ser´an ´utiles al momento de
identificar tokens en la siguiente secci´on, y estados. Figura 3.
Figura 3: Directivas de Jflex
4
5. Cambiamos el nombre de la clase del analizador a Lexer. % class AnalizadorLexico
Realizamos la activaci´on del contador de lineas, variable yyline y el contador de co-
lumna, variable yycolumn.
%line
%column
luego hay que activar la compatibilidad con Java CUP para analizadores sintacticos.
% cup
Generamos un java cup.Symbol para guardar el tipo de token encontrado.
private Symbol symbol(int type) {
return new Symbol(type, yyline, yycolumn);
}
Tambi´en generamos un Symbol para el tipo de token encontrado junto con su valor.
private Symbol symbol(int type, Object value) {
return new Symbol(type, yyline, yycolumn, value);
}
Las Macro declaraciones Figura 4.
Figura 4: Las Macro declaraciones
Un salto de linea es un n, r.
Salto = r|n|rn
Espacio es un espacio en blanco, tabulador t, salto de linea o avance de pagina f,
normalmente son ignorados.
Espacio = {Salto} | [ tf]
para que reconozca n´umeros enteros:
Entero = 0 | [1-9][0-9]*
5
6. 4.3. Secci´on de reglas l´exicas
Esta secci´on contiene expresiones regulares y acciones. Las acciones son c´odigo en
Java Figura 5. que se ejecutara cuando se encuentre una entrada valida para la expresi´on
regular correspondiente.
Figura 5: Reglas l´exicas
YYINITIAL es el estado inicial del analizador lexico al escanear. Las expresiones
regulares solo ser´an comparadas si se encuentra en ese estado inicial. Es decir, cada vez
que se encuentra una coincidencia el scanner vuelve al estado inicial.
<YYINITIAL> {
/* Regresa que el token FINLINEA declarado en la clase sym fue encontrado.*/
";" { System.out.print(yytext()+" FinLinea "+" ["+yyline+","
+yycolumn+"] n");
return symbol(sym.FINLINEA);}
/*Regresa que el token OP_DIVISION declarado en la clase sym fue encontrado.*/
"/" { System.out.print( yytext()+" dividido "+" ["+yyline+","
+yycolumn+"] n");
return symbol(sym.OP_DIVISION);}
/* Regresa que el token OP_CERO declarado en la clase sym fue encontrado.*/
"0" { System.out.print( yytext()+" cero "+" ["+yyline+","
+yycolumn+"] n");
return symbol(sym.OP_CERO);}
/* Si se encuentra un n´umero, se imprime, se regresa un token numero
que representa un entero y el valor que se obtuvo de la cadena yytext
al convertirla a double. yytext es el token encontrado. */
6
7. {Entero} { System.out.print(yytext()+" numero "+" ["+yyline+","
+yycolumn+"] n");
return symbol(sym.ENTERO, new Double(yytext())); }
/* Se ignora si se encuentra el espacio en blanco */
{Espacio} { /* Ignora el espacio */ }
}
/* Si el car´acter ingresado no coincide con ninguna regla
Entonces se marca un token ilegal */
[ˆ] { System.err.println("El caracter ingresado es
invaido <"+yytext()+">"+"posicion"+"("+yyline+" "+yycolumn+")"); }
5. CUP
Para construir un compilador el segundo paso que debemos dar es el de desarrollar el
analizador sint´actico de nuestro lenguaje.
CUP desarrollada en Java para crear analizadores sint´acticos. Genera dos clases en
Java, por default sym y parser, a partir de una especificaci´on en la que se indica una
gram´atica formal as´ı como tambi´en se asocian una serie de acciones a los s´ımbolos apareci-
dos en cada regla gramatical. Tambi´en define un interfaz para acoplarse a los analizadores
l´exicos construidos con JFLex.
La clase sym esta constituida por los s´ımbolos terminales declarados en la gram´atica,la
cual es utilizada para hacer referencia a los mismos.
Un archivo de entrada para CUP consta de las siguientes secciones:
5.1. Definici´on de paquete e importaci´on de paquetes necesa-
rios.
En este secci´on se incluyen las construcciones para indicar que las clases Java genera-
das a partir de este archivo pertenecen a un determinado paquete y/o tambi´en importar
las clases Java necesarias. figura 6.
package ejemplocup;
import java_cup.runtime.*;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
7
8. Figura 6: Paquetes e importaciones
5.2. C´odigo de usuario.
En esta secci´on se puede incluir c´odigo Java del analizador sint´actico que se va a obte-
ner con CUP. En la primera parte tenemos el c´odigo para reportar los errores generados
al realizar un dato err´oneo figura 7.
Figura 7: M´etodo report error
Luego tenemos el m´etodo Main y Divisor que es que realiza la operaci´on de dividir
8
9. cantidades figura 8.
Figura 8: Metodo Main y divisi´on
/* C´odigo del parser, se copia ´ıntegramente a la clase final.
Agregamos el manejo de errores, el m´etodo de divisor y el main*/
parser code {:
/* Reporte de error encontrado. */
/* Creamos el meto report_error el cual recibe un mensaje y un objeto */
public void report_error(String message, Object info) {
/* Declaramos un StringBufer el cual contendr´a el mensaje*/
StringBuilder m = new StringBuilder("Error");
/*Agregamos un if el cual se analiza el objeto recibido instanceof
Sirve para conocer si un objeto de un tipo java_cup.runtime.Symbol*/
if (info instanceof java_cup.runtime.Symbol) {
//imprimimos objeto info para conocer su identificador
System.out.println("INFO ="+info);
/* Declaramos la variable s de tipo java_cup.runtime.Symbol
Donde se almacena el castin del info*/
java_cup.runtime.Symbol s = ((java_cup.runtime.Symbol) info);
/*if nos va a obtener la l´ınea y columna donde se encuentra el symbol*/
if (s.left >= 0) {
//agregamos al mensaje la l´ınea
m.append(" linea "+(s.left+1));
if (s.right >= 0)
//agregamos al mensaje la columna
m.append(", columna "+((s.right+1)-1));
9
10. }
/*Este if verifica el identificador es igual a 2 entonces
se trata del fin de l´ınea*/
if(s.sym==2){ message="est´a mal o no existe el fin de l´ınea"; }
/*Este if verifica el identificador es igual a 3
entonces se trata del OP_DIVISION*/
if(s.sym==3){message="tiene q existir numerador";}
/*Este if verifica el identificador es igual a 5
entonces se trata del ENTERO*/
if(s.sym==5){message="no puede existir dos numeros
continuos sin el operador";}
/*Este if verifica el identificador es igual a 4
entonces se trata del OP_CERO*/
if(s.sym==4){message="El numero para el cual se
divide debe ser mayor a cero ";}
}
//al mensaje le agregamos (:) para una comprensi´on mejor
m.append(" : "+message);
//imprimimos el error
System.err.println(m);
}
/* M´etodo main para garantizar la ejecuci´on del analizador l´exico y
sint´actico, Adem´as que se pase como par´ametro la tabla de s´ımbolos
correspondiente. */
public static void main(String[] args){
try {
AnalizadorSintactico asin = new AnalizadorSintactico(
new AnalizadorLexico( new FileReader(args[0])));
Object result = asin.parse().value;
} catch (Exception ex) {
// Imprimimos que existe un error al realizar la ejecuci´on
System.err.println("ERROR EN EL INGRESO DE DATOS");
}
}
/*Realizamos el m´etodo divisor que nos devuelve un double al
realizar la Operaci´on y recibe como para metro dos n´umeros */
public Double division(Double num1, Double mun2) {
// Variable para almacenar el resultado
Double todo;
//ejecuci´on de la operaci´on
todo= num1/mun2;
// Retornamos el valor de la operaci´on
return todo;
}
:};
10
11. 5.3. Declaraci´on de s´ımbolos terminales y no terminales.
En esta secci´on se declaran los s´ımbolos terminales y no terminales figura 9. de la
gram´atica que define el analizador sint´actico que deseamos producir. Tanto los s´ımbolos
no terminales como los s´ımbolos terminales pueden, tener asociado un objeto Java de una
cierta clase.
Figura 9: Declaraci´on de terminales y no terminales
/* ---Declaraci´on de s´ımbolos terminales y no terminales--- */
/* Terminales (tokens obtenidos por el analizador lexico).*/
terminal FINLINEA, OP_DIVISION, OP_CERO;
terminal Double ENTERO;
/* No terminales usados en la secci´on gramatical.e lista los no terminales que tien
un valor Object queNo tienen tipo, pudiendo ser entero o String. */
non terminal Object expr1, expr2;
non terminal Object sentencia;
5.4. Definici´on del s´ımbolo inicial de la gram´atica y las reglas
de producci´on
Las reglas de producci´on tienen esta sintaxis:
expresion ::= expresion < sımboloterminal > expresion{: codigo :};
Se pueden definir todas las reglas de producci´on que tengan a un mismo s´ımbolo no
terminal figure 10. como antecedente separandolas por el s´ımbolo |.
/* ------------------- Seccion de la gramatica ------------------------ */
/* La | sirve para indicar que es una producci´on u otra. Debemos pasar de s´ımbolos
terminales a s´ımbolos terminales. Una gram´atica que no Termina en s´ımbolos terminal
11
12. Figura 10: Secci´on Gramatical
se dice que no reduce, y por lo tanto nunca se finaliza Su procesado.*/
expr1 ::= expr1 expr2
|
expr2
;
/* En esta expresi´on se llama a la expresi´on sentencia para poder imprimir
el Resultado de en c´odigo java
*/
expr2 ::= sentencia:e
{:
System.out.println(" igual "+e);
:}
;
/*Puede ser una expresi´on que inicia por numero op_divido, de esa forma
se realiza Una divisi´on. En RESULT se almacena el valor de las acciones y
se pasa al siguiente nivel de la gram´atica.
*/
sentencia ::=
12
13. //sentencia incorrecta de la operaci´on
ENTERO:n OP_DIVISION ENTERO:m
{:
// C´odigo para obtener el objeto info del fin de l´ınea
CUP$AnalizadorSintactico$result = parser.getSymbolFactory().
newSymbol("sentencia",2,((java_cup.runtime.Symbol)
CUP$AnalizadorSintactico$stack.elementAt(CUP$
AnalizadorSintactico$top-2))((java_cup.runtime.Symbol)
CUP$AnalizadorSintactico$stack.peek()), RESULT);
// Llamamos al m´etodo report_error y enviamos el
//mensaje y el objeto tipo info
parser.report_error("Falta fin", CUP$AnalizadorSintactico$result);
:}
// o podemos tener la sentencia correcta
|
ENTERO:n OP_DIVISION ENTERO:m FINLINEA
{:
//El RESULT almacena el resultado de haber llamado el m´etodo divisi´on
RESULT=parser.division(n.doubleValue(), m.doubleValue());
:}
;
6. Sym
En esta clase java se generan los Tokens declarados y utilizados en la secci´on l´exica y
sint´actica figura 11.
Figura 11: Codigo java de la clase sym
13
14. package ejemplocup;
/** CUP generated class containing symbol constants. */
public class sym {
/* terminals */
public static final int OP_CERO = 4;
public static final int FINLINEA = 2;
public static final int error = 1;
public static final int OP_DIVISION = 3;
public static final int EOF = 0;
public static final int ENTERO = 5;
}
7. Control de errores
En la secci´on de errores podemos observar que el control se realiza en la parte de el
analizador sint´actico en el m´etodo de report error figura 12.
Figura 12: Errores sint´acticos
14
15. Y la parte de control de caracteres se realiza en la secci´on l´exica Figura 13.
Figura 13: Errores l´exicos
8. Funcionamiento del compilador
Lo que primero hacemos es escoger la opci´on 1 Figura 14. Generar del men´u en la cual
se generan la clase sym, AnalizadorLexico y AnalizadorSintactico.
Figura 14: Genraci´on de clase sym, AnalizadorLexico y AnalizadorSintactico
Luego realizamos el ingreso de caracteres validos. Ingresamos: 43/9; Figura 15.
15
16. Figura 15: Ejecuci´on correcta
Ahora vamos a presentar el control de algunos errores al ingresar mal los datos de
entrada
1. Cuando falta fin de linea ”43/9”. Figura 16.
Figura 16: Falta Fin de linea
2. Cuando se ingresa dos cantidades seguidas sin operador ”4 3 / 9;”. Figura 17.
Figura 17: Sin operador
16
17. 3. Cuando dividimos para cero ”43 /0;”Figura 18.
Figura 18: Denominador cero
4. Cuando no existe denominar el error interpreta como fin de linia al simbolo del
divisor ”43 /;”Figura 19.
Figura 19: Sin denominador
17
18. 5. Cuando no existe numerador /9;”Figura 20.
Figura 20: Sin numerador
6. Cuando se ingresa mal un car´acter ”43/hola;”Figura 21.
Figura 21: Caracteres inv´alidos
La c´odigo de este compilador se lo puede encontrar en:
https://code.google.com/p/compiladoresdivisor/source/browse/#svn%2Ftrunk
18
19. 9. BIBLIOGRAFIA
Referencias
[1] Antonio De Miguel Vicenti.2007 C¸ompilador de Pascal”. Disponible en:
http%3A%2F%2Fplg07082.googlecode.com%2Fsvn%2Ftrunk%2FDocumentaci%
25C3%25B3n%2FDOCUMENTACION%2520ENTREGA%2520FINAL%2FDOCUMENTACION%
2FANALISIS%2520LEXICO%2FDocumentacion%2520Analizador%2520Lexico.
pdf&ei=0gOOVNemE43asASVqYL4Bw&usg=AFQjCNEAOrPRo7wH_L7KLJ4bvbjCwvKzlQ
[2] Carlos III de Madrid, Departamento de ingenier´ıa telematoca, ” Fundamentos de
Ordenadores I: Breve Introducci´on a CUP” Disponible en: http://www.it.uc3m.
es/luis/fo1/p/CUP.html
[3] Compiladores: principios, t´ecnicas y herramientas. A.V. Aho, R. Sethi, J.D. Ull-
man. Addison-Wesley Iberoamerica. 1990. Disponible en: http://loscompiladores.
wordpress.com/category/analizador-sintactico/
[4] Enrique Arangurenn. .A
nalizador Sint´actico”, 2011. Disponible en: http://
loscompiladores.wordpress.com/category/analizador-sintactico/
[5] Open(fecks();). .Estructura Archivo JFLex”. Disponible en: http://openfecks.
wordpress.com/jFlex-y-cup/plantilla-archivo-jFlex/
[6] Salvador Sanchez, Daniel Rodrıguez, Departamento de Ciencias de Universidad
de Alcala, ”Procesadores de Lenguaje” Disponible en:http://www.cc.uah.es/ie/
docencia/ProcesadoresDeLenguaje/CUP.pdf
[7] Soraya Lara, Universidad Nacional de Loja, ” Divisor de cantidades C´odigo fuen-
te ”Disponible en:https://code.google.com/p/compiladoresdivisor/source/
browse/#svn%2Ftrunk
19