grapes compiler

43
GRAPES COMPILER. ©Grapes Compiler ® Friends Company. Marca registrada.

Upload: ro-berto

Post on 05-Sep-2015

269 views

Category:

Documents


3 download

DESCRIPTION

Compilador

TRANSCRIPT

Grapes Compiler.

Grapes Compiler.

Grapes Compiler Friends Company. Marca registrada.

QU ES UN COMPILADOR?

El compilador es un programa que se encarga de traducir los programas escritos por el programador en lenguaje de alto nivel (entendible por el ser humano) a un lenguaje de bajo nivel que es el comprensible por la mquina y que, de esta manera, permite que pueda ser ejecutado por la computadora. Sera la transformacin del cdigo fuente a un lenguaje mquina o cdigo objeto.

Para poder entender mejor cmo realiza su tarea, es conveniente conocer las diversas fases que cumple un compilador para lograr la traduccin.

Las primeras tres fases son de anlisis: anlisis lxico, sintctico y semntico, fases en las que se leen los caracteres del cdigo fuente, se analizan, se comprueban si son vlidos y se van reagrupando en secuencias lgicas y frases gramaticales.

Grapes Compiler es un compilador creado por la empresa Friends Company que presenta estas caractersticas y las cuales se muestran en este manual, el cual muestra su respectivo cdigo de programacin.

ANALIZADOR LXICO.

Analizador lxico (scanner): lee la secuencia de caracteres del programa fuente, carcter a caracter, y los agrupa para formar unidades con significado propio, los componentes lxicos (tokens en ingles). Estos componentes lxicos representan:palabras reservadas.identificadores: asociados a variables, nombres de funciones, tipos definidos por el usuario, etiquetas.operadores.smbolos especiales.constantes numricas: literales que representan valores enteros, en coma flotante, etc.constantes de caracteres: literales que representan cadenas concretas de caracteres.

Los componentes lxicos se suelen definir como un tipo enumerado. Se codifican como enteros. Tambin se suele almacenar la cadena de caracteres que se acaba de reconocer (el lexema), que se usara posteriormente para el anlisis semntico. Los componentes lxicos se representan mediante una estructura registro con tipo de Token y lexema.

MATRIZ DE TRANSICION DEL AUTOMATA

ANLISIS SINTCTICO.

La sintaxis es un conjunto de reglas formales que especifican la composicin de los programas a base de letras, dgitos y otros caracteres. La principal tarea del analizador sintctico no es comprobar que la sintaxis del programa fuente sea correcta, sino construir una representacin interna de ese programa y en el caso en que sea un programa incorrecto, dar un mensaje de error.El analizador sintctico (A. S.) comprueba que el orden en que el analizador lxico le va entregando los tokens es vlido. Si esto es as significar que la sucesin de smbolos que representan dichos tokens puede ser generada por la gramtica correspondiente al lenguaje del cdigo fuente.

Tipos de Anlisis Sintcticos

Desde el punto de vista de la teora de Anlisis Sintctico, hay dos estrategias para construir el rbol sintctico: Anlisis descendente: partimos de la raz del rbol (donde estar situado el axioma o smbolo inicial de la gramtica) y se van aplicando reglas por la izquierda de forma que se obtiene una derivacin por la izquierda de la cadena de entrada. Para decidir qu regla aplicar, se lee un token de la entrada. Recorriendo el rbol de anlisis sintctico resultante, en profundidad de izquierda a derecha, encontraremos en las hojas del rbol los tokens que nos devuelve el Analizador Lxico (A.L.) en ese mismo orden. Anlisis ascendente: partiendo de la cadena de entrada, se construye el rbol de anlisis sintctico empezando por las hojas (donde estn los tokens) y se van creando nodos intermedios hasta llegar a la raz (hasta el smbolo inicial), construyendo as el rbol de abajo a arriba. El recorrido del rbol se har desde las hojas hasta la raz. El orden en el que se van encontrando las producciones corresponde a la inversa de una derivacin por la derecha.Las dos estrategias recorren la cadena de entrada de izquierda a derecha una sola vez, y necesitan (para que el anlisis sea eficiente) que la gramtica no sea ambigua.Ejemplo:Entrada: num*num+numGramtica:E ::= E + T | TT ::= T * F | FF ::= num(E: expresin, T: trmino, F: factor)

Las dos estrategias recorren la cadena de entrada de izquierda a derecha una sola vez, y necesitan (para que el anlisis sea eficiente) que la gramtica no sea ambigua.Ejemplo:Entrada: num*num+numGramtica:E ::= E + T | TT ::= T * F | FF ::= num(E: expresin, T: trmino, F: factor)

ANLISIS SEMNTICO.

Despus de pasar exitosamente por la fase sintctica es posible entender el significado de la frase a travs del anlisis semntico. Intuitivamente realizamos el anlisis semntico y entonces darle sentido a las frases. Lo importante es determinar la coherencia entre lo dicho por medio del lenguaje y los elementos del mundo a los que se est haciendo referencia. Para un compilador dicho mundo es la computadora, sus registros, sus celdas de memoria, etc.El anlisis semntico realizado por un compilador es averiguar, por ejemplo, si una expresin dentro de un programa significa algo vlido. Una frase analizada a fondo, al terminar su validez lexicogrfica, sintctica y semntica, llega el momento de ser traducida. En algunos compiladores suelen incluirse las funciones de generacin de cdigo (lenguaje mquina o al menos lenguaje ensamblador).

CODIGO DEL COMPILADORpublic class Main extends JFrame { private JTextField jTextField = null; private JLabel jLabel = null; private JButton jButton = null; //static Lexico lex; static LexicoGui lex; static SintacticoGui sin; //static Sintactico sin; static SemanticoGui sem; //static Semantico sem; static int banderaBuffer = 0; static int banderaLeidos = 0; static int banderaPrimeraMitad = 0; static int banderaSegundaMitad = 0; static boolean esFinArchivo; static int posOp = 0; static int token = -1; static String lexema; static int estado = 0; static boolean banderaErrorF = false; static FileReader archivo; static char buffer[]; static int tam = 28, apuntadorLec = 0, mitadBuffer, cantidadLec; static int arregloApuntadores[]; static char tOperadores[] = {' ', '\t', '\r', '\n', '+', '-', '*', '/', ';', '=', '(', ')', ','}; static String tSimbolos[][]; static int tTransiciones[][] = {{0, 0, 0, 0, 100, 101, 102, 3, 104, 105, 106, 107, 1, 2, 200, 110}, {108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 1, 1, 108, 108}, {109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 2, 109, 109}, {103, 103, 103, 103, 103, 103, 4, 103, 103, 103, 103, 103, 103, 103, 103, 103}, {4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 201, 4, 4, 4, 4, 4, 4, 4, 4}}; static CType Tipo, Lista, ListaP; static JLabel jLabel1 = null; static JLabel jLabel2 = null; private JButton browse; JFileChooser fc; /** * This is the default constructor */ public Main() { super(); initialize(); } /** * * @param args */ public static void main(String[] args) { Main a = new Main(); a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } /** * This method initializes this * * @return void */ private void initialize() { fc = new JFileChooser(); jLabel1 = new JLabel(); jLabel1.setBounds(new java.awt.Rectangle(77, 41, 130, 34)); jLabel1.setText("...C O M P I L A D O R..."); jLabel = new JLabel(); jLabel.setBounds(new java.awt.Rectangle(22, 87, 47, 30)); jLabel.setText("Archivo"); browse = new JButton("..."); browse.setBounds(new java.awt.Rectangle(205, 120, 56, 28)); browse.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { int returnVal = fc.showOpenDialog(Main.this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); getJTextField().setText(file.getPath()); } else { } } });

this.setLayout(null); this.setSize(281, 200); this.setTitle("Compiler Grapes"); this.setVisible(true); this.add(getJTextField(), null); this.add(jLabel, null); this.add(getJButton(), null); this.add(jLabel1, null); this.add(getJLabel2(), null); this.add(browse, null); this.setSize(280, 200); } /** * This method initializes jTextField * * @return javax.swing.JTextField */ private JTextField getJTextField() { if (jTextField == null) { jTextField = new JTextField(); jTextField.setBounds(new java.awt.Rectangle(70, 87, 113, 32)); } return jTextField; }

/** * This method initializes jButton * * @return javax.swing.JButton */ private JButton getJButton() { if (jButton == null) { jButton = new JButton(); jButton.setText("OK"); jButton.setBounds(new java.awt.Rectangle(205, 87, 56, 28)); jButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { System.out.println("actionPerformed()"); // TODO Auto-generated Event stub actionPerformed() { String nombreArchivo; arregloApuntadores = new int[2]; buffer = new char[tam]; arregloApuntadores[0] = -1; arregloApuntadores[1] = 0; mitadBuffer = tam / 2; cantidadLec = mitadBuffer;

tSimbolos = new String[25][2]; tSimbolos[0][0] = "inicio"; tSimbolos[1][0] = "fin"; tSimbolos[2][0] = "int"; tSimbolos[3][0] = "float"; tSimbolos[4][0] = "char"; tSimbolos[5][0] = "String"; String name = jTextField.getText(); nombreArchivo = name; try { archivo = new FileReader(new File(nombreArchivo)); } catch (FileNotFoundException f) { jLabel2.setText("El Archivo no existe."); return; } cargarBuffer(); lex = new LexicoGui(); lex.setLocation(0, 200); sin = new SintacticoGui(); sin.setLocation(420, 200); sem = new SemanticoGui(); sem.setLocation(840, 200);

sem.imprime("... Reglas Gramaticales ...\n"); do { token = scanner(); if (token != -1) { P(); } } while (esFinArchivo == false); sem.imprime("\n...TABLA DE SIMBOLOS...\n"); String temp = ""; for (int i = 0; i < tSimbolos.length; i++) { for (int j = 0; j < tSimbolos[0].length; j++) { if (tSimbolos[i][j] != null) { if (j == 1) { sem.imprime(tSimbolos[i][0] + "\t" + tSimbolos[i][j] + "\n"); } else if (tSimbolos[i][1] == null) { sem.imprime(tSimbolos[i][j] + "\n"); } } } sem.imprime(""); } } } }); }

return jButton; } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica P */ public static void P() { if (token == 1) { sem.imprime("P->inicio Declaracion C fin\n"); token = scanner(); Declaracion(); C(); } else if (token != 2) { sem.imprime("Error: se esperaba fin\n"); } } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica C */ public static void C() { if (token > 100) { sin.imprime("C->id=E;C\n"); token = scanner(); if (token == 22) { token = scanner(); E(); if (token == 21) { token = scanner(); C(); } else { sin.imprime("Error: se esperaba ;\n"); //C (archivo, buffer, cantidadLec, arregloApuntadores, estado, tOperadores, tSimbolos, tTransiciones); } } else { sin.imprime("Error: se esperaba =\n"); } } else { sin.imprime("C->vacio\n"); } } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica E esto significa * que se trata de una Expresion */ public static void E() { sin.imprime("E->TE'\n"); T(); if (banderaErrorF == false) { EPrima(); } } * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica T esto significa * que se trata de un Termino */ public static void T() { sin.imprime("T->FT'\n"); F(); if (banderaErrorF == false) { TPrima(); } } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica F esto significa * que se trata de un Factor */ public static void F() { if (token > 100) { banderaErrorF = false; sin.imprime("F->id\n"); token = scanner(); } else if (token == 31) { banderaErrorF = false; sin.imprime("F->(E)\n"); token = scanner(); E(); if (token == 32) { token = scanner(); } else { sin.imprime("Error: se esperaba )\n"); } } else if (token == 7) { banderaErrorF = false; sin.imprime("F->num"); token = scanner(); } else { sin.imprime("Error: se esperaba id,num o (\n"); char a; do { a = dameCar(); } while (a != ';'); retraer(); omitir(); banderaErrorF = true; token = scanner(); } } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica T' esto significa * que se trata de un Termino */ public static void TPrima() { if (token == 13) { sin.imprime("T'->*FT'\n"); token = scanner(); F(); TPrima(); } else if (token == 14) { sin.imprime("T'->/FT'\n"); token = scanner(); F(); TPrima(); } else { sin.imprime("T'->vacio\n"); } } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica E' esto significa * que se trata de una Expresion */ public static void EPrima() { if (token == 11) { sin.imprime("E'->+TE'\n"); token = scanner(); T(); EPrima(); } else if (token == 12) { sin.imprime("E'->-TE'\n"); token = scanner(); T(); EPrima(); } else { sin.imprime("E'->vacio\n"); } }/** * Agrega una linea en el analizador semntico que indica una declaracion */ public static void Declaracion() { if (token == 30 || token == 41 || token == 51 || token == 61) { sem.imprime("Declaracion->Tipo Lista; Declaracion\n"); Tipo(); Lista(); if (token == 21) { token = scanner(); Declaracion(); } else { sem.imprime("Error: se esperaba ;\n"); } } else { sem.imprime("Declaracion->vacio\n"); } } /**

* Agrega una linea que indica el tipo de dato al que pertenece * cierto lexema en caso de tratarse de una declaracion */ public static void Tipo() { if (token == 30) { sem.imprime("Tipo->int\n"); token = scanner(); Tipo = new CType(); Tipo.setType("int", "2"); //Tipo_Clase = "int"; } else if (token == 41) { sem.imprime("Tipo->float\n"); token = scanner(); Tipo = new CType(); Tipo.setType("float", "3"); //Tipo_Clase = "float"; } else if (token == 51) { sem.imprime("Tipo->char\n"); token = scanner(); Tipo = new CType(); Tipo.setType("char", "4"); //Tipo_Clase = "char"; } else if (token == 61) { sem.imprime("Tipo->String\n"); token = scanner(); ListaPrima(); } else { sem.imprime("Error: se esperaba id\n"); } } /** * Agrega una linea que indica que el lexema se comporta * como se indica en la Gramatica L' esto significa * que se trata de una Lista que sigue de una coma "," */ public static void ListaPrima() { if (token == 33) { sem.imprime("Lista'->,id Lista'\n"); token = scanner(); ListaP = new CType(); ListaP.setType(Lista.getType(), Tipo.getPos()); //ListaP_Clase = Lista_Clase; if (token > 100) { //id_Clase = Lista_Clase; tSimbolos[token - 100][1] = Lista.getPos(); token = scanner(); ListaPrima(); } else { sem.imprime("Error: se esperaba id\n"); } } else { sem.imprime("Lista'->vacio\n"); } } /** * Lee una secuencia de caracteres del programa fuente, * carcter a caracter, y los agrupa para formar unidades con significado * propio. * @return El identificador del lexema */ public static int scanner() { estado = 0; boolean esPalReservada = false; int posPalRes = -1; int posId = -1; int posCNum = -1; int ret = -1; char car; while (estado < 100) { car = dameCar(); if (car != '$') { estado = revisarTransicion(estado, car, tOperadores, tTransiciones); } else { break; } }switch (estado) { case 100: { aceptar(); lex.imprime(" (1,1) operador\n"); ret = 11; break; } case 101: { aceptar(); lex.imprime(" (1,2) operador\n"); ret = 12; break; } case 102: { aceptar(); lex.imprime(" (1,3) operador\n"); ret = 13; break; } case 103: { retraer(); aceptar(); lex.imprime(" (1,4) operador\n"); ret = 14; break; }

case 104: { aceptar(); lex.imprime(" (2,1) operador\n"); ret = 21; break; } case 105: { aceptar(); lex.imprime(" (2,2) operador\n"); ret = 22; break; } case 106: { aceptar(); lex.imprime(" (3,1) operador\n"); ret = 31; break; } case 107: { aceptar(); lex.imprime(" (3,2) operador\n"); ret = 32; break; } case 108: { retraer(); aceptar(); for (int i = 0; i < 6; i++) { if (lexema.equals(tSimbolos[i][0])) { esPalReservada = true; posPalRes = i; break; } else { esPalReservada = false; } } if (esPalReservada == true) { lex.imprime(" (palabraReservada," + (posPalRes + 1) + ")\n"); if (tSimbolos[posPalRes][0].equals("inicio")) { ret = 1; } else if (tSimbolos[posPalRes][0].equals("fin")) { ret = 2; } else if (tSimbolos[posPalRes][0].equals("int")) { ret = 30; } else if (tSimbolos[posPalRes][0].equals("float")) { ret = 41; } else if (tSimbolos[posPalRes][0].equals("char")) { ret = 51; } else if (tSimbolos[posPalRes][0].equals("String")) { ret = 61; }else { for (int j = 6; j < tSimbolos.length; j++) { if (tSimbolos[j][0] != null && lexema.equals(tSimbolos[j][0])) { posId = j; break; } else if (tSimbolos[j][0] == null) { tSimbolos[j][0] = lexema; posId = j; break; } } lex.imprime(" (Identificador," + (posId + 1) + ")\n"); ret = posId + 100; } break; }case 109: { retraer(); aceptar(); for (int j = 2; j < tSimbolos.length; j++) { if (tSimbolos[j][0] != null && lexema.equals(tSimbolos[j][0])) { posCNum = j; break; } else if (tSimbolos[j][0] == null) { tSimbolos[j][0] = lexema; posCNum = j; break; } } lex.imprime(" (Constante numerica," + (posCNum + 1) + ")\n"); ret = 7; break; } case 110: { aceptar(); lex.imprime(" (4,1) operador\n"); ret = 33; break; }case 200: { char ci[]; ci = lexema.toCharArray(); if (102 == (byte) ci[0] && 105 == (byte) ci[1] && 110 == (byte) ci[2]) { break; } else { aceptar(); lex.imprime("Error Lexico: " + token); break; } } case 201: { omitir(); token = scanner(); ret = token; break; } } return ret; } /** * Devuelve el estado al que ha cambiado dependiendo el caracter analizado * @param estado Estado Actual * @param car Caracter a analizar * @param tOperadores tabla de Operadores * @param tTransiciones tabla de Transiciones * @return estado actualizado */

public static int revisarTransicion(int estado, char car, char[] tOperadores, int[][] tTransiciones) { boolean esLetra = false; boolean esDigito = false; boolean esOperador = false; esLetra = Character.isLetter(car); esDigito = Character.isDigit(car); for (int i = 0; i < tOperadores.length; i++) { if (car == tOperadores[i]) { esOperador = true; posOp = i; break; } else { esOperador = false; } }if (esLetra == true) { estado = tTransiciones[estado][12]; } else if (esDigito == true) { estado = tTransiciones[estado][13]; } else if (esOperador == true && car != ',') { estado = tTransiciones[estado][posOp]; } else if (esOperador == true && car == ',') { estado = tTransiciones[estado][15]; } else { estado = tTransiciones[estado][14]; } return estado; } /**Carga a la memoria un buffer para ser analizado */ public static void cargarBuffer() { int leidos = 0; int apuntadorLec = 0; int mod;mod = banderaBuffer % 2; if (mod == 0 && banderaPrimeraMitad == 0) { apuntadorLec = 0; banderaPrimeraMitad = 1; banderaSegundaMitad = 0; } else if (mod == 1 && banderaSegundaMitad == 0) { apuntadorLec = 14; banderaPrimeraMitad = 0; banderaSegundaMitad = 1; } try { leidos = archivo.read(buffer, apuntadorLec, cantidadLec); banderaBuffer = banderaBuffer + 1; banderaLeidos = leidos; if (leidos == cantidadLec) { //System.out.print ("\nSe cargaron " + leidos + " caracteres"); } else if (banderaLeidos < cantidadLec && banderaLeidos != -1) { buffer[apuntadorLec + banderaLeidos] = '$'; } else if (leidos == -1) { System.out.print("\nNo se cargaron caracteres"); } } catch (IOException e) { System.out.print("\n\t\t\tError de lectura"); } }

/** * Obtiene un caracter * @return un caracter del buffer */ public static char dameCar() { if (banderaLeidos == 14) { if (arregloApuntadores[0] == 13 && banderaSegundaMitad == 0) { cargarBuffer(); } else if (arregloApuntadores[0] == 27 && banderaPrimeraMitad == 0) { cargarBuffer(); arregloApuntadores[0] = -1; } if (arregloApuntadores[0] < buffer.length - 1) { arregloApuntadores[0] = arregloApuntadores[0] + 1; } else { arregloApuntadores[0] = 0; } int apBusqueda = arregloApuntadores[0]; return buffer[apBusqueda]; } else if (banderaLeidos < 14) { if (arregloApuntadores[0] == 13 && banderaSegundaMitad == 0) { cargarBuffer(); } else if (arregloApuntadores[0] == 27 && banderaPrimeraMitad == 0) { cargarBuffer(); arregloApuntadores[0] = -1; arregloApuntadores[1] = 0; } if (arregloApuntadores[0] < buffer.length - 1) { arregloApuntadores[0] = arregloApuntadores[0] + 1; } else { arregloApuntadores[0] = 0; } int apBusqueda = arregloApuntadores[0]; if (buffer[apBusqueda] == '$') { esFinArchivo = true; return '$'; } else { return buffer[apBusqueda]; } } else { return '&'; } }/** * Regresa el apuntador al inicio para una nueva lectura */ public static void retraer() { if (arregloApuntadores[0] == 0) { arregloApuntadores[0] = buffer.length - 1; } else { arregloApuntadores[0] = arregloApuntadores[0] - 1; } } /** * En caso de haber un error ser notificado en Consola */ public static void fallo() { arregloApuntadores[0] = arregloApuntadores[1] - 1; System.out.print("Falla "); } /** * Si la cadena es aceptada el Analizador Lexico le procesara */ public static void aceptar() { StringBuffer cadena = new StringBuffer(); cadena = new StringBuffer(); int apBusqueda = arregloApuntadores[0]; int apActual = arregloApuntadores[1]; //System.out.print ("Aceptar: "); if (apBusqueda >= apActual) { while (apActual apBusqueda && apBusqueda != -1) { while (apActual < buffer.length) { if (buffer[apActual] != ' ' && buffer[apActual] != '\t' && buffer[apActual] != '\n' && buffer[apActual] != '\r') { lex.imprime("" + buffer[apActual]); cadena = cadena.append(buffer[apActual++]); } else { apActual++; } }apActual = 0; while (apActual = apActual) { while (apActual apBusqueda && apBusqueda != -1) { while (apActual < buffer.length) { if (buffer[apActual] != ' ' && buffer[apActual] != '\t' && buffer[apActual] != '\n' && buffer[apActual] != '\r') { cadena = cadena.append(buffer[apActual++]); } else { apActual++; } }apActual = 0; while (apActual