Teoria de Compiladores

download Teoria de Compiladores

of 27

description

Compilador usando Jflex “Calculadora De Operaciones Basicas”

Transcript of Teoria de Compiladores

MONOGRAFA

Compilador usando Jflex Calculadora De Operaciones Basicas

Teora de Compiladores

Resumen

En un principio, En 1946 se desarroll el primer ordenador digital, estas mquinas ejecutaban instrucciones consistentes en cdigos numricos que sealan a los circuitos de la mquina los estados correspondientes a cada operacin. A esto se le llamo lenguaje maquina.

Pronto los primeros usuarios de estos ordenadores descubrieron la ventaja de escribir sus programas mediante claves ms fciles de recordar que esos cdigos numricos; al final, todas esas claves juntas se traducan manualmente a Lenguaje Mquina.

La tarea de realizar un compilador no fue fcil. El primer compilador de FORTRAN tard 18 aos-persona en realizarse y era muy sencillo.Como un ejemplo de ello tenemos el hecho de que los espacios en blanco fuesen ignorados, debido a que el perifrico que se utilizaba como entrada de programas (una lectora de tarjetas perforadas) contaba correctamente los espacios en blanco.

El lenguaje Java, establece que el compilador no genera cdigo para una mquina determinada sino para una virtual, la Java Virtual Machine (JVM), que posteriormente ser ejecutado por un intrprete, normalmente incluido en un navegador de Internet. El gran objetivo de esta exigencia es conseguir la mxima portabilidad de los programas escritos y compilados en Java, pues es nicamente la segunda fase del proceso la que depende de la mquina concreta en la que se ejecuta el intrprete.

INTRODUCCIONEn 1946 se desarroll el primer ordenador digital. Pronto los primeros usuarios de estos ordenadores descubrieron la ventaja de escribir sus programas mediante claves ms fciles de recordar que esos cdigos numricos; al final, todas esas claves juntas se traducan manualmente a Lenguaje Mquina. Estas claves constituyen los llamados lenguajes ensambladores, que se generalizaron en cuanto se dio el paso decisivo de hacer que las propias mquinas realizaran el proceso mecnico de la traduccin. A este trabajo se le llama ensamblar el programa.

En el caso particular de que el lenguaje a traducir es un lenguaje de alto nivel y el lenguaje traducido de bajo nivel, se emplea el trmino compilador.

La tarea de realizar un compilador no fue fcil. El primer compilador de FORTRAN tard 18 aos-persona en realizarse y era muy sencillo. Este desarrollo del FORTRAN estaba muy influenciado por la mquina objeto en la que iba a ser implementado. Como un ejemplo de ello tenemos el hecho de que los espacios en blanco fuesen ignorados, debido a que el perifrico que se utilizaba como entrada de programas (una lectora de tarjetas perforadas) no contaba correctamente los espacios en blanco.

Paralelamente al desarrollo de FORTRAN en Amrica, en Europa surgi una corriente ms universitaria, que pretenda que la definicin de un lenguaje fuese independiente de la mquina y en donde los algoritmos se pudieran expresar de forma ms simple.

En 1969, el lenguaje fue revisado y llev a una nueva versin que se llam ALGOL 60. Junto a este desarrollo en los lenguajes, tambin se iba avanzando en la tcnica de compilacin. En 1958, Strong y otros proponan una solucin al problema de que un compilador fuera utilizable por varias mquinas objeto.

En 1975, con la aparicin de LEX surge el concepto de un generador automtico de analizadores lxicos a partir de expresiones regulares, basado en el sistema operativo UNIX. A partir de los trabajos de Chomsky ya citados, se produce una sistematizacin de la sintaxis de los lenguajes de programacin, y con ello un desarrollo de diversos mtodos de anlisis sintctico.

A mitad de la dcada de los 60, Knuth define las gramticas LR y describe la construccin de una tabla cannica de parser LR. Por otra parte, el uso por primera vez de un parsing descendente recursivo tuvo lugar en el ao 1961. En el ao 1968 se estudian y definen las gramticas LL as como los parsers predictivos.

En los primeros lenguajes (FORTRAN y ALGOL 60) los tipos posibles de los datos eran muy simples, y la comprobacin de tipos era muy sencilla.

En la actualidad, el proceso de la compilacin ya est muy asentado. Un compilador es una herramienta bien conocida, dividida en diversas fases. Algunas de estas fases se pueden generar automticamente (analizador lxico y sintctico) y otras requieren una mayor atencin por parte del escritor de compiladores (las partes de traduccin y generacin de cdigo).

De todas formas, y en contra de lo que quiz pueda pensarse, todava se estn llevando a cabo varias vas de investigacin en este fascinante campo de la compilacin.

MARCO TEORICO

1. COMPILADORTambin llamado traductor, es cualquier programa que toma como entrada un texto escrito en un lenguaje, llamado fuente y da como salida otro texto en un lenguaje, denominado objeto.

En el caso de que el lenguaje fuente sea un lenguaje de programacin de alto nivel y el objeto sea un lenguaje de bajo nivel (ensamblador o cdigo de mquina), a dicho traductor se le denomina compilador.

La mejor informacin sobre los errores por parte del compilador as como una mayor velocidad de ejecucin del cdigo resultante hizo que poco a poco se impusieran los compiladores.

Hoy en da, y con el problema de la memoria prcticamente resuelto, se puede hablar de un gran predominio de los compiladores frente a los intrpretes, aunque intrpretes como los incluidos en los navegadores de Internet para interpretar el cdigo JVM de Java son la gran excepcin.

Un compilador no es un programa que funciona de manera aislada, sino que necesita de otros programas para conseguir su objetivo.1.1) Partes de un compilador La construccin de un compilador involucra la divisin del proceso en una serie de fases que variar con su complejidad. Generalmente estas fases se agrupan en dos tareas: el anlisis del programa fuente y la sntesis del programa objeto. Anlisis: Se trata de la comprobacin de la correccin del programa fuente, e incluye las fases correspondientes al Anlisis Lxico (que consiste en la descomposicin del programa fuente en componentes lxicos), Anlisis Sintctico (agrupacin de los componentes lxicos en frases gramaticales ) y Anlisis Semntico (comprobacin de la validez semntica de las sentencias aceptadas en la fase de Anlisis Sintctico). Sntesis: Su objetivo es la generacin de la salida expresada en el lenguaje objeto y suele estar formado por una o varias combinaciones de fases de Generacin de Cdigo (normalmente se trata de cdigo intermedio o de cdigo objeto) y de Optimizacin de Cdigo (en las que se busca obtener un cdigo lo ms eficiente posible).Alternativamente, las fases descritas para las tareas de anlisis y sntesis se pueden agrupar en Front-end y Back-end: Front-end: Es la parte que analiza el cdigo fuente, comprueba su validez, genera el rbol de derivacin y rellena los valores de la tabla de smbolos. Esta parte suele ser independiente de la plataforma o sistema para el cual se vaya a compilar, y est compuesta por las fases comprendidas entre el Anlisis Lxico y la Generacin de Cdigo Intermedio. Back-end: Es la parte que genera el cdigo mquina, especfico de una plataforma, a partir de los resultados de la fase de anlisis, realizada por el Front End.Esta divisin permite que el mismo Back End se utilice para generar el cdigo mquina de varios lenguajes de programacin distintos y que el mismo Front End que sirve para analizar el cdigo fuente de un lenguaje de programacin concreto sirva para generar cdigo mquina en varias plataformas distintas. Suele incluir la generacin y optimizacin del cdigo dependiente de la mquina.El cdigo que genera el Back End normalmente no se puede ejecutar directamente, sino que necesita ser enlazado por un programa enlazador (linker)2. INTERPRETES VS COMPILADORES

Inicialmente interpretes eran ms comunes. Hoy en da, los compiladores son ms comunes: Compila una vez, ejecuta muchas veces. Ejecucin programa objeto ms rpida. Compilador tiene una visin ms global del programa. Interprete sin embargo da mejor diagnostico de errores.

3. Tipos de compiladores

Ensamblador: lenguaje fuente = ensamblador Compilador con montador: compila modulo independientes y luego los enlaza Auto compilador: escrito en el mismo lenguaje que va a compilar Descompilador: realiza proceso inverso a la compilacin.

4. ESTRUCTURA DE UN COMPILADOR

5. ANALISIS LXICO

Lee caracteres uno a uno y forma grupos de caracteres con alguna relacin entre s (tokens).

Cada token es una secuencia de caracteres tratados como una unica entidad.

6. ANALISIS SINTCTICO

Recibe como entrada los tokens que le pasa el analizador lxico. Comprueba si los tokens llegan en order correcto (orden permitido por el lenguaje). La salida es un arbol sintctico (arbol de parse). Cuando el programa fuente es incorrecto (sintacticamente) el analizador sintactico es el responsable de producir un mensaje de error.

7. ANALISIS SEMNTICO Comprueba que lo que el significado de lo que se va leyendo es vlido.

8. GESTION DE ERRORES

Se utiliza en todas las fases, pero especialmente en las de anlisis sintctico y semntico.

Es una tarea difcil:

Un error puede ocultar otros. Un error puede provocar una avalancha de otros.

Importante tener un buen manejo de errores: Que detecte todos los errores. Que no deje de compilar al detectar el primer error.

9. FORMAS DE EXAMINAR UN COMPILADOR

9.1) FASE DE ANALISIS

En esta fase el programa es descompuesto en sus elementos fundamentales. Abarca el anlisis lxico, el anlisis sintctico y el anlisis semntico. Esta fase verifica si el programa en lenguaje fuente es correcto, y recoge la informacin necesaria en la tabla de smbolos para el mdulo de sntesis. Si detecta la existencia de errores, se notifican por medio del gestor de errores.

9.2) FASE DE SINTESISEsta fase se lleva a cabo una vez que el mdulo de anlisis ha verificado que el cdigo fuente es correcto. La informacin recogida en el mdulo de anlisis y almacenada en la tabla de smbolos se emplea en la fase de sntesis para la generacin del cdigo objeto. Abarca la generacin de cdigo intermedio, y en el caso de los compiladores, la generacin de cdigo y la optimizacin del mismo.

9.3) AGRUPAMIENTO DE FASES

Front-end: depende del lenguaje fuente, independiente del lenguaje objeto. Back-end: depende del lenguaje objeto y es independiente del lenguaje fuente.

10. TABLA DE SMBOLOS

Un compilador necesita guardar y usar la informacin de los objetos que va encontrando en el texto fuente. Esta informacin se almacena en una estructura de datos interna: tabla de smbolos, Accesos a la tabla deben ser rpidos.

11. Herramientas que muestran tipos de anlisis de programas fuente

11.1) Editores de estructuras11.2) Impresoras estticas: Una impresora esttica analiza un programa y lo imprime de forma que la estructura del programa resulte claramente visible.

11.3) Verificadores estticos: Un verificador esttico lee un programa, lo analiza e intenta descubrir errores potenciales sin ejecutar el programa

11.4) Intrpretes: En lugar de producir un programa objeto como resultado de una traduccin, un intrprete realiza las operaciones que implica el programa fuente.

12. JFLEXJFLEX es un generador de analizador lxico para java1 escrito en Java, fue desarrollado por Elliot Berk Universidad de Princeton. Generador de programas java diseado paraprocesamiento lxico, Parte de un conjunto de reglas lxicas. JFlex produce un programa llamado Yylex que reconoce las cadenas que cumplen dichas reglas.

12.1) OBJETIVOS DE DISEO

Los objetivos de diseo principales de JFLEX son:

Completo soporte Unicode Rpido generados escneres Generacin de escner rpido Sintaxis de especificacin de Conveniente Independencia de plataforma Compatibilidad con JLex

La velocidad suele ser proporcional a la cantidad de caracteres en la entrada. El nmero o la complejidad de la reglas slo influyen sobre el tamao del autmata.

12.2) OPCIONES Y DECLARACIONESOpciones del cdigo generado: %class nombre Especifica el nombre de la clase generada como salida de JFlex. %line y %column activan cuenta de lneas (yyline) y columnas (yycolumn) respectivamente. %standalone Genera programa que acepta un fichero de entrada en lnea de comando. %debug Durante la ejecucin muestra: n lnea de la especificacin, lexema reconocido y accin ejecutada.

12.3) REGLAS LEXICAS

Especificacin de las expresiones:

expresiones regulares: sean a y b expresiones vlidas a | b Unin a b Concatenacin a* Repeticin 0 o N veces a+ Repeticin 1 o N veces (= a a*) a? Opcionalidad !a Negacin ~a Cualquier cosa que termine

12.4) FUNCIONES DEL JFLEX yytext() Devuelve el lexema reconocido. yylength() Devuelve el la longitud del lexema. yycharat( int n ) Devuelve el ensimo carcter del lexema reconocido. yypushback( int n ) Considera los n ltimos caracteres del lexema reconocido como no procesados. Se volvern a leer, pero no se tendrn en cuenta para: yytext() e yylength().

13. PROYECTO CALCULADORA USANDO JFLEX

13.1) Calculadora

Calc.flex%%

%byaccj

%{ private Parser yyparser;

public Yylex(java.io.Reader r, Parser yyparser) { this(r); this.yyparser = yyparser; }%}

NUM = [0-9]+ ("." [0-9]+)?NL = \n | \r | \r\n

%%

/* operators */"+" | "-" | "*" | "/" | "^" | "(" | ")" { return (int) yycharat(0); }

/* newline */{NL} { return Parser.NL; }

/* float */{NUM} { yyparser.yylval = new ParserVal(Double.parseDouble(yytext())); return Parser.NUM; }

/* whitespace */[ \t]+ { }

\b { System.err.println("Sorry, backspace doesn't work"); }

/* error fallback */[^] { System.err.println("Error: unexpected character '"+yytext()+"'"); return -1; }

Calcy.y%{ import java.io.*; %} %token NL /* newline */%token NUM /* a number */

%type exp

%left '-' '+'%left '*' '/'%left NEG /* negation--unary minus */%right '^' /* exponentiation */ %%

input: /* empty string */ | input line ; line: NL { if (interactive) System.out.print("Ingrese su operacin: "); } | exp NL { x=$1 + ""; if(x.equals("Infinity"))System.out.println(" Indeterminado "); else System.out.println(" = " + x ); if (interactive) System.out.print("Ingrese su operacin: "); } ; exp: NUM { $$ = $1; } | exp '+' exp { $$ = $1 + $3; } | exp '-' exp { $$ = $1 - $3; } | exp '*' exp { $$ = $1 * $3; } | exp '/' exp { $$ = $1 / $3; } | '-' exp %prec NEG { $$ = -$2; } | exp '^' exp { $$ = Math.pow($1, $3); } | '(' exp ')' { $$ = $2; } ;

%%

private Yylex lexer; String x; private int yylex () { int yyl_return = -1; try { yylval = new ParserVal(0); yyl_return = lexer.yylex(); } catch (IOException e) { System.err.println("IO error :"+e); } return yyl_return; }

public void yyerror (String error) { System.err.println ("Error: " + error); } public void yyerrork (String error) throws Exception { System.err.println ("Error: " + error); throw new Exception("Error Exception"); }

public Parser(Reader r) { lexer = new Yylex(r, this); }

static boolean interactive;

public static void main(String args[]) throws IOException { System.out.println("BYACC/Java with JFlex Calculator Demo"); Parser yyparser; if ( args.length > 0 ) { // parse a file yyparser = new Parser(new FileReader(args[0])); } else { // interactive mode //System.out.println("[Quit with CTRL-D]"); System.out.print("Ingrese su operacn: "); interactive = true; yyparser = new Parser(new InputStreamReader(System.in)); }

yyparser.yyparse(); if (interactive) { System.out.println(); System.out.println("Ingrese una operacion!!!!!!"); } }

Calculadora.Java import java.io.*; public class Parser{

boolean yydebug; //do I want debug output?int yynerrs; //number of errors so farint yyerrflag; //was there an error?int yychar; //the current working character

void debug(String msg){ if (yydebug) System.out.println(msg);}

final static int YYSTACKSIZE = 500; //maximum stack sizeint statestk[] = new int[YYSTACKSIZE]; //state stackint stateptr;int stateptrmax; //highest index of stackptrint statemax; //state when highest index reached

final void state_push(int state){ try {stateptr++;statestk[stateptr]=state; } catch (ArrayIndexOutOfBoundsException e) { int oldsize = statestk.length; int newsize = oldsize * 2; int[] newstack = new int[newsize]; System.arraycopy(statestk,0,newstack,0,oldsize); statestk = newstack; statestk[stateptr]=state; }}final int state_pop(){ return statestk[stateptr--];}final void state_drop(int cnt){ stateptr -= cnt; }final int state_peek(int relative){ return statestk[stateptr-relative];}final boolean init_stacks(){ stateptr = -1; val_init(); return true;}

void dump_stacks(int count){int i; System.out.println("=index==state====value= s:"+stateptr+" v:"+valptr); for (i=0;i=YYSTACKSIZE) return; valstk[++valptr]=val;}ParserVal val_pop(){ if (valptr= 0 && yyn