compilador convertidor de divisas

16
CIS-IXB-003 UNIVERSIDAD NACIONAL DE LOJA ´ Area de la Energ´ ıa las Industrias y los Recursos Naturales No Renovables Carrera de Ingenier ´ ıa en Sistemas Compiladores Convertidor de Divisas Tarea- Extra Clase Noveno B Autor: Henry David Quishpe Docente: Ing. Henry-Paz, Loja-Ecuador 2015 1

Upload: universidad-nacional-de-loja

Post on 30-Jul-2015

73 views

Category:

Software


6 download

TRANSCRIPT

Page 1: Compilador Convertidor de Divisas

CIS-IXB-003

UNIVERSIDADNACIONALDE LOJA

Area de la Energıa las Industrias y los Recursos Naturales No Renovables

Carrera de Ingenierıa en Sistemas

Compiladores

Convertidor de Divisas

Tarea- Extra ClaseNoveno B

Autor:

• Henry David Quishpe

Docente: Ing. Henry-Paz,

Loja-Ecuador2015

1

Page 2: Compilador Convertidor de Divisas

ContentsA Problema 3

B Automata del Compilador 31 Analisis Lexico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1 .1 Codigo de Usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 .2 Opciones y Declaraciones . . . . . . . . . . . . . . . . . . . . . . . . 41 .3 Reglas Lexicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Analisis Sintactico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 .1 Importaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 .2 Componentes de Codigo de Usuario . . . . . . . . . . . . . . . . . . 72 .3 Declaracion de la lista de Sımbolos de la Gramatica . . . . . . . . . 112 .4 Predencia y Asociacion de los Terminales . . . . . . . . . . . . . . . 112 .5 Gramatica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

C Resultados 13

D BIBLIOGRAFIA 16

Page 3: Compilador Convertidor de Divisas

A ProblemaPara poder realizar el compilador hay que basarse en un lenguaje, para ello he creıdo con-veniente crear mi propio lenguaje a partir de un alfabeto con el objetivo de crear palabrasclaves, identificadores, caracteres($, E, P y S) y numeros. Se hara uso de la librerıa JFlex,ya que esta nos facilita la construccion del analizador lexico, para la programacion delanalizador sintactico se utiliza la librerıa Cup, se hara una integracion de las dos librerıaspara la creacion del compilador.

El compilador que se realizo es un convertidor de divisas, lo que se pretende es sabera que valor equivale una divisa conocida a otra desconocida, para ello este compiladortiene una entrada en donde se debe especificar el valor y las 2 divisas respectivamente parafinalizar una lınea se tendra que poner un ; hay que recalcar que las divisas aceptadas sonDolar ($), Peso Mexicano (P), Sol Peruano (S) y Euro (E). A futuro se puede adicionardivisas mas conocidas para tener un compilador mas completo.

El compilador se lo realizo en 2 etapas las cuales son:

1) Analisis Lexico

2) Analisis Sintactico

B Automata del CompiladorPara la creacion del automata se hara uso de la herramienta JFlap, la misma que cuentacon una interfaz de facil uso para la creacion de automatas y para hacer pruebas defuncionamiento y otras funciones mas de importante uso.

Figure 1: Automata del Compilador Conversor de Divisas

3

Page 4: Compilador Convertidor de Divisas

1 Analisis LexicoEl Analizador lexico lee una secuencia de caracteres de izquierda a derecha del programafuente y agrupa las secuencias de caracteres en unidades con significado propio (compo-nentes lexicos). Las palabras claves, identificadores, operadores, constantes numericas,signos de puntuacion como separadores de sentencias, llaves, parentesis, etc.El analizador lexico de este compilador se encuentra divido en 3 secciones:

1 .1 Codigo de Usuario

En la primera seccion se realiza lo que es el codigo de usuario, aquı es donde se especificael paquete al cual va a pertenecer el archivo java e importaciones de algunas librerıas quese van a necesitar.

A continuacion se explica cada linea de codigo del archivo .flex: En la siguiente linease especifica el paquete al cual la clase va a pertenecer.

/*** Especificacion del paquete*/

package analizador;

Se importa toda la librerıa cup de la clase runtime.

/*** Libreria Cup*/

import java_cup.runtime.*;

Para separar cada seccion del archivo lexico o para indicar el inicio se lo hara con elsımbolo %%.

1 .2 Opciones y Declaraciones

En la siguiente lınea se especifica el nombre de la clase java que se crea cuando se ejecuteel archivo .flex.

/*** nombre de la clase*/

%class AnalizadorLexico

A continuacion se activa el contador de linea y columnas con los comandos %line y %col-umn respectivamente.

// activar el contador de lineas, variable yyline%line// activar el contador de columnas, variable yycolumn%column

4

Page 5: Compilador Convertidor de Divisas

Con el comando %cup se activa la compatibilidad con java cup para los analizadoressintacticos (parser).

// activar la compatibilidad con java cup%cup

Se crea un metodo de tipo Symbol para guardar el tipo de token encontrado, para locual recibe como parametros un entero, este metodo nos retorna un Symbol con el tipo,la linea y la columna.

private Symbol symbol(int type){return new Symbol(type, yyline, yycolumn);

}

Se crea un metodo de tipo Symbol para guardar el tipo de token encontrado junto con suvalor, para lo cual recibe como parametros un entero y Objeto el cual va a ser el valor, estemetodo nos retorna un Symbol con el tipo, la linea, la columna y el valor correspondiente.

private Symbol symbol(int type, Object value){return new Symbol(type, yyline, yycolumn, value);

}

En esta parte se realizan las declaraciones de las expresiones regulares, las mismas queseran utilizadas en las reglas lexicas. En la siguiente lınea de codigo declaramos la variableSalto a la cual le asignamos un retorno de carro o un salto de lınea o ambos a la vez.

// un salto de linea es un \n, \r o \r\nSalto = \r|\n|\r\n

Creamos la variable Espacio a la cual le asignamos la variable Salto declarada anterior-mente o le asignamos un espacio en blanco, tabulador o avance de pagina.

// Espacio en blanco, tabulador \t avance de pagina \fEspacio = {Salto}| [ \t\f]

Declaramos la variable Entero a la cual le asignamos uno o varios numeros de del 0 al 9seguido de un punto y repetimos la primera parte, lo cual nos genera en si un numerodecimal como por ejemplo 10.23.

// numero decimalEntero = [0-9]+ \. [0-9]+

1 .3 Reglas Lexicas

Esta seccion contiene expresiones regulares y acciones, las acciones son codigo en java quese ejecuta cuando se encuentre una entrada valida para la expresion regular correspondi-ente. YYINITIAL es el estado inicial del analizador lexico al escanear. Las expresionesregulares solo seran comparadas si se encuentra en ese estado inicial. Es decir, cada vezque se encuentra una coincidencia el scanner vuelve al estado inicial. Por lo cual se ignoranestados intermedios.

5

Page 6: Compilador Convertidor de Divisas

// Estado inicial del analizador lexico<YYINITIAL> {}

El codigo siguiente debe estar dentro de YYINITIAL para que una vez encontradauna entrada valida se vuelva analizar desde el inicio, es decir ignorando las siguientesexpresiones regulares.Cuando se encuentra el ; en la entrada se regresa el token FINLINEA el cual esta declaradoen la clase sym.

// Regresa el token FINLINEA declarado en la clase sym";" {return symbol(sym.FINLINEA);}

Al igual cuando se encuentre el sımbolo de Dolar $ en la cadena de entrada se retornarael token DOLAR.

// Regresa el token $ DOLAR declarado en la clase sym"$" {return symbol(sym.DOLAR);}

Cuando se encuentra la E nos retorna el token Euro.

// Regresa el token EURO declarado en la clase sym"E" {return symbol(sym.EURO);}

Tambien si se encuentra la P nos retorna el token Peso.

// Regresa el token PESO declarado en la clase sym"P" {return symbol(sym.PESO);}

Y ası mismo con S se retorna el token Sol.

// Regresa el token SOL declarado en la clase sym"S" {return symbol(sym.SOL);}

La siguiente expresion indica que cuando se encuentre un numero Decimal, se retorna eltoken VALOR y el valor.

// Regresa el token VALOR declarado en la clase sym{Entero}+ { return symbol(sym.VALOR, new Double(yytext()));}

La siguiente expresion regular es para ignorar la variable Espacio, la misma que estacompuesta por un tabulador, salto de pagina, retorno de carro, avance de pagina o unespacio en blanco.

{Espacio} {/* ignora el espacio */ }

Dentro del mismo metodo YYINITIAL especificamos una lınea para que nos imprima unerror con el valor, la lınea y columna, este error se presenta cuando se encuentre en laentrada un caracter que no este declarado en el metodo YYINITIAL.

. {System.out.println("Caracter Ilegal <" + yytext()+ ">, En la linea: "+ (yyline+1) + " Y en la columna: "+ (yycolumn+1)) ;}

6

Page 7: Compilador Convertidor de Divisas

2 Analisis SintacticoEl Analisis sintactico determina si la secuencia de componentes lexicos sigue la sintaxisdel lenguaje y obtiene la estructura jerarquica del programa en forma de arbol.El archivo .cup esta compuesto por 5 secciones las cuales se explican a continuacion:

2 .1 Importaciones

En la primera seccion se realiza lo que son las declaraciones de package donde se especificael paquete al cual va a pertenecer el archivo java e importaciones de algunas librerıas quese van a necesitar.En la siguiente linea se especifica el paquete al cual la clase va a pertenecer.

/*** Especificacion del paquete*/

package analizador;

Se importa toda la librerıa cup de la clase runtime.

/*** Libreria Cup*/

import java_cup.runtime.*;

Tambien se importa la librerıa Reader, esta se utiliza para poder leer un archivo .txt elcual sera nuestra entrada.

/*** Libreria Filereader*/

import java.io.FileReader;

2 .2 Componentes de Codigo de Usuario

Creamos un metodo para reportar los errores el mismo que recibe dos parametros unmensaje de tipo String y una informacion (Symbol) de tipo Object.

public void report_error(String message, Object info) {}

En la siguiente lınea creamos una variable m de tipo StringBuffer a la cual le asignamosla cadena Error, esta variable es la que se le va adicionar la lınea y columna en donde seencuentra el error.

StringBuffer m = new StringBuffer("Error");

Mediante un if comprobamos que la informacion que recibimos sea un instancia de la claseSymbol.

7

Page 8: Compilador Convertidor de Divisas

if(info instanceof java_cup.runtime.Symbol) {}

Creamos el objeto s al cual le asignamos la informacion recibida, aquı se guardara el valorentero asignado en la clase sym.

java_cup.runtime.Symbol s=((java_cup.runtime.Symbol)info);

A continuacion con el if comprobamos que la lınea sea mayor o igual a cero.

if(s.left >= 0) {}

Si la condicion anterior se cumple a la variable m declarada anteriormente le asignamosla cadena “En la linea ” mas el numero de linea aumentado en 1, ya que se empieza acontar desde cero.

m.append(" En la linea....."+(s.left+1));

Utilizamos otro if dentro del if anterior pero en este caso para comprobar que la columnasea mayor o igual a cero.

if (s.right >= 0){}

Si la condicion llegase a cumplirse le anadimos a la variable m la cadena “y en la columna”mas el numero de columna aumenta en uno por la misma razon del conteo de lıneas.

m.append(", y en la columna...... "+(s.right+1));

En este compilador le hemos anadido algo adicional, esto es el control de errores, es deciridentificar porque se ha producido el error e informar al usuario. Para esto utilizamos lavariable s que es de tipo Symbol declarada anteriormente, para obtener el valor entero deltoken utilizamos el sym, el cual nos regresa el valor un valor entero, con esto comprobamoscon los valores de cada uno de los valores de los tokens de la clase sym. Entonces medianteun if comprobamos la igualdad, cuando el valor entero sea igual a cero le asignamos a lavariable mensaje que recibimos como parametro la cadena “Falta un ;”.

if (s.sym == 0){message = "Falta ; o la expresion esta inncompleta";

}

En caso de no cumplirse la condicion anterior comprobamos si existe una igualdad entre5, 3, 6, o 4.

if (s.sym == 5 || s.sym == 3 || s.sym == 6 || s.sym == 4){}

Para saber si el error es de un ; comprobamos si la columna es igual a cero y la lıneaes igual o mayor a 1, esto es porque en el compilador se ignora el salto de lınea. Encaso de que se cumpla la condicion a la variable mensaje le asignamos “Falta un ; en laexpresion”.

8

Page 9: Compilador Convertidor de Divisas

if(s.right == 0 && s.left >= 1){message = "Falta un ; en la expresion";

}

Si no se cumple entonces le asignamos a mensaje “El valor de la divisa es incorrecto”.

else {message = "El valor de la divisa es incorrecto ";

}

En caso de no cumplirse la condicion que comprobamos con 5, 3, 6 o 4 pasamos a compro-bar si el valor entero es igual a 2 o igual 7. En caso de cumplirse le asignamos a mensajela cadena “Usted debe ingresar una divisa puede ser ($, P, S o E)”.

else if(s.sym == 2 || s.sym ==7){message = "Usted dede ingresar una divisa";

}

Para terminar con el metodo para reportar los errores a la variable m le asignamos lacadena “:” mas el mensaje recibido como parametro y modificado en caso que haya entradoen alguna condicion anteriormente.

m.append(" : "+message);

Y por ultimo imprimimos los errores que se llegasen a encontrar.

System.err.println(m);

Para poder hacer la conversion de divisas creamos un metodo el cual recibe tres parametrosla primera divisa de tipo String, la segunda divisa la cual es a la que se va a convertirigual de tipo String y por ultimo el valor de tipo double.

public void conversion(String a, String b, double n){}

Dentro del metodo creamos una variable de tipo double en la cual se va almacenar laequivalencia de cada moneda con respecto a la otra.

double equivalencia=0;

Mediante un if comprobamos la primera divisa. En caso de que sea igual a $ se compruebala segunda divisa.Si la segunda divisa es igual a $ a la variable equivalencia le asignamos 1.00 Si no secumple comprobamos si es igual a P (Pesos) y a la variable equivalencia le asignamos14.66, si no se cumple comprobamos si es igual E (Euros) y a la variable equivalencia leasignamos 0.846645, si no se cumple comprobamos si es igual a S (Soles) y a la variableequivalencia le asignamos 2.98170.Continuamos con el primer if pero en esta ocasion comprobamos la primera divisa con E(Euros).Si la primera divisa es igual a E comprobamos la si la segunda divisa es igual a $ Dolar) y

9

Page 10: Compilador Convertidor de Divisas

a la variable equivalencia le asignamos 1.18113, si no se cumple comprobamos si es iguala P (Peso) y a la variable equivalencia le asignamos 17.20, si no se cumple comprobamossi es igual a E (Euro) y a la variable equivalencia le asignamos 1.00, si no se cumplecomprobamos si es igual a S (Soles) y a la variable equivalencia le asignamos 3.52.En caso de que la primera divisa no sea igual E comprobamos con P.Si la primera divisa es igual a P entonces comprobamos si la segunda divisa es igual a $y a la variable equivalencia le asignamos 0.068, si no se cumple comprobamos si es iguala P (Peso) y a la variable equivalencia le asignamos 1.00, si no se cumple comprobamossi es igual a E (Euro) y a la variable equivalencia le asignamos 0.5813, si no se cumplecomprobamos si es igual a S (Sol) y a la variable equivalencia le asignamos 0.20332.Y por ultimo si la primera divisa no es igual a P comprobamos con S (Soles) En caso deque la primera divisa sea igual a S, empezamos a comprobar si la segunda divisa es iguala $ y si lo es le asignamos a la variable equivalencia 0.34, si no se cumple comprobamossi es igual a P (Peso) y a la variable equivalencia le asignamos 4.92 Si no se cumplecomprobamos si es igual a E (Euro) y a la variable equivalencia le asignamos 0.285, sino se cumple comprobamos si es igual a S (Sol) y a la variable equivalencia le asignamos1.00.

if (a=="$"){System.out.print("Dolares");if (b=="$"){equivalencia=1.00;}else if (b=="P"){equivalencia=14.66;}else if (b=="E"){equivalencia=0.846645;}else if (b=="S"){equivalencia= 2.98170;} }

else if (a=="E"){System.out.print("Euros");if (b=="$"){equivalencia=1.18113;}else if (b=="P"){equivalencia=17.20;}else if (b=="E"){equivalencia=1.00;}else if (b=="S"){equivalencia=3.52;}

}else if (a=="P"){

System.out.print("Pesos");if (b=="$"){equivalencia=0.068;}else if (b=="P"){equivalencia=1.00;}else if (b=="E"){equivalencia=0.05813;}else if (b=="S"){equivalencia=0.20332;}

}else if (a=="S"){

System.out.print("Soles");if (b=="\$"){equivalencia=0.34 ;}else if (b=="P"){equivalencia=4.92;}else if (b=="E"){equivalencia=0.285;}else if (b=="S"){equivalencia=1.00;}

}

10

Page 11: Compilador Convertidor de Divisas

Al final del metodo convertir se imprime los resultados.

System.out.print(" Son ======> "+ n*equivalencia + " ");

Para la ejecucion del compilador creamos el metodo main en el cual debemos crear unobjeto de la misma clase y creamos un variable resultado a la cual le asignamos el metodoparse al cual se puede llamar con el objeto creado anteriormente.

public static void main(String[] argumento){try {

AnalizadorSintactico asin = new AnalizadorSintactico(new AnalizadorLexico(new FileReader(argumento[0])));Object resultado = asin.parse().value;

} catch (Exception ex){ex.printStackTrace();

}}

2 .3 Declaracion de la lista de Sımbolos de la Gramatica

A continuacion declaramos los sımbolos terminales y no terminales. Los terminales sonlos tokens obtenidos por el analizador lexico. Primero se declaran los terminales que notienen un valor.

terminal FINLINEA, DOLAR, PESO, SOL, EURO;

Luego se declaran los terminales los cuales tienen un valor en este caso entero.

terminal Double VALOR;

Tambien se declaran los no terminales los cuales van a ser usados en la seccion de lagramatica.En nuestro caso declaramos no terminales de tipo Object, ya que este nos indica que notienen tipo, es decir pueden ser entero o String.

non terminal Object programa, linea, divisa;

2 .4 Predencia y Asociacion de los Terminales

La precedencia de los no terminales, no sirve con sımbolos terminales es por eso que nola usamos. Ademas indica si se asocia a izquierda o derecha.

2 .5 Gramatica

Por ultimo realizamos la gramatica de nuestro analizador la cual puede contener tanto unterminal con un no terminal. La expresion programa es la raız de la gramatica esta puedeser una expresion programa seguida de una expresion lınea o puede ser una lınea.

programa ::= programa linea | linea;

11

Page 12: Compilador Convertidor de Divisas

La expresion lınea se compone de una expresion medida seguida del terminal VALORotra vez la expresion medida por ultimo el terminal FINLINEA, de esa forma se realizala conversion de la divisas para ello llamamos al metodo convertir usando el parser y leenviamos las 2 divisas y el valor.Tambien utilizamos el token error de la clase sym para llamar al metodo de reporte deerrores.

linea ::= error {:parser.report_error("Revise la sintaxis",null);:}|divisa:m1 VALOR:n divisa:m2 FINLINEA {parser.conversion(m1.toString(),m2.toString(),n);System.out.println(m2); :};

La expresion medida esta compuesta por el terminal DOLAR en RESULT se almacena elvalor de las acciones. O puede estar compuesta por el terminal PESO de igual manera enRESULT se almacena el valor de la acciones, tambien puede estar compuesta por EUROo SOL.

divisa ::= DOLAR {: RESULT="$"; :} | PESO {: RESULT="P"; :} |SOL {: RESULT="S"; :} | EURO {: RESULT="E"; :};

12

Page 13: Compilador Convertidor de Divisas

C ResultadosA continuacion se ilustra los resultados obtenidos del compilador, para ello ejecutamos laclase Ejecutor.java, esta clase necesita un archivo txt el cual es nuestra entrada.

Figure 2: Valores de Entrada

Si nuestros valores de entrada son los de la figura 2 al compilar la clase Ejecutor obten-dremos los siguientes resultados:

Figure 3: Resultado del Compilador

Si ingresamos un caracter que no este declarado en las reglas lexicas del archivo analizadorlexico como por ejemplo:

Figure 4: Entrada con caracter erroneo

13

Page 14: Compilador Convertidor de Divisas

Con la entrada de la figura 4 el compilador nos indica el error junto conl caracter, lalinea y columna en la que se encuentra, el compilador ignora este caracter para seguircompilando, como lo podemos ver en la figura 5.

Figure 5: Resultado de Error Lexico

Ademas se controlan los errores sintacticos, se indica de porque el error y en donde seencuentra.

Figure 6: Entrada con errores sintacticos

Cuando se tenga la entrada de la figura 6 el compilador nos informara que existe un errorel mismo que se especifica el porque del error junto con la lınea y columna.

Figure 7: Errores de Sintaxis

14

Page 15: Compilador Convertidor de Divisas

Cuando no se ingrese el ; que en nuestro compilador es el fin de lınea el compiladornos informa del error inmediatamente.

Figure 8: Entrada Sin Fin de Linea de Sintaxis

Si no se ha ingresado el ; y al ejecutar nuestro compilador este nos devolvera lo siguiente:

Figure 9: Error de Sintaxis ;

15

Page 16: Compilador Convertidor de Divisas

D BIBLIOGRAFIA

References[1] L.C. Kenneth. Construccion de Compiladores. Principios y practica. Mexico: Thom-

son editores, 2004. pp. 31.

[2] A.V. Aho, R. Sethi y J.D. Ullman. Compiladores: Principios, tecnicas y herramientas.Wilmington, Delaware: Addison- Wesley Iberoamericana S. A., 1990. pp. 1 - 5.

[3] Gloria Ines Alvarez V. Compiladores: Analisis Sintactico, 2008 En lınea. Disponibleen: http://cic.javerianacali.edu.co/wiki/lib/exe/fetch.php?media=materias

[4] Enlace para descargar el codigo del compilador. Disponible en: https://code.google.com/p/compiladores-h/

16