Академический Документы
Профессиональный Документы
Культура Документы
Proyecto de Compiladores.
Tema:
Implementación de la Generación de Código.
Autores:
Diego Eduardo Murquincho Puma.
Jessica Cecibel Correa Campoverde.
Docente:
Ing. Willman Chamba.
LOJA – ECUADOR.
ÍNDICE.
1. Objetivos…………………………………………………………………………….. 2
1.1 Objetivo General……………………………………………………………….. 2
1.2 Objetivos Específicos…………………………………………………………. 2
2. Marco Teórico…………………………………………………………………..…… 2
2.1 Análisis Semántico……………………………………………………………… 2
2.1.1. Atributos y acciones semánticas……………………………………….. 2
2.1.2 Ejecución de una acción semántica…………………………………. 2, 3
2.2 Generación de Código…………………………………………………………. 4
2.2.1. Código de tercetos……………………………………….………….. 5, 6, 7
2.3 Tabla de símbolos…………………………………………………………...…. 8
3. Desarrollo..…………………………………………………………………… 8, 9, 10
4. Conclusiones..………………………………………………………………………. 11
5. Recomendaciones…………………………………………………………………. 12
6. Bibliografía………………………………………………………………………….. 13
ÍNDICE DE FIGURAS
FIGURA 1……………………………………………………………………………….. 3
FIGURA 2………………………………………………………………….……………. 4
FIGURA 3………………………………………………………………….……………. 5
ya le en
1
1. Objetivos.
1.1 Objetivo General.
Implementar la Generación de Código para la Gramática y Tokens definidas
de las expresiones aritméticas utilizadas en el analizador sintáctico.
2. Marco Teórico
2
Se supone que en una primera fase se construye el árbol sintáctico completo
y, posteriormente, se ejecutan las acciones semánticas en una secuencia tal
que permita el cálculo de todos los atributos de los nodos del árbol.
En el caso del análisis ascendente la cosa puede no estar tan clara de primera hora
y resulta conveniente exponer claramente cuáles son estas reglas sobre la
utilización de atributos en acciones semánticas de un esquema LR:
- Un atributo solo puede ser usado (en una acción) detrás del símbolo al que
pertenece.
- En una acción intermedia sólo se puede hacer uso de los atributos de los
símbolos que la preceden.
[4]
3
2.2 Generación de Código.
En el modelo de análisis y síntesis de un compilador, la etapa inicial traduce un
programa fuente a una representación intermedia a partir de la cual la etapa final
genera el código objeto. [5]
4
Los detalles del lenguaje objeto se confinan en la etapa final, si esto es posible.
Aunque un programa fuente se puede traducir directamente al lenguaje objeto,
algunas ventajas de utilizar una forma intermedia independiente de la máquina son:
[9]
1. Se facilita la re-destinación; se puede crear un compilador para una
máquina distinta uniendo una etapa final para la nueva máquina a una etapa
inicial ya existente.
2. Se puede aplicar a la representación intermedia un optimizador de código
independiente de la máquina.
Hay lenguajes que son pseudo interpretados que utilizan un código intermedio
llamado código-P que utiliza lo que se denomina bytecodes (sentencias de un µP
hipotético). Por ejemplo Java utiliza los ficheros .class, éstos tienen unos bytecodes
que se someten a una Java Virtual Machine, para que interprete esas sentencias.
[10]
5
● Operando 1º (dirección de memoria donde se encuentra el primer operando).
● Operando 2º (dirección de memoria donde se encuentra el segundo
operando).
● Operador (código de operación)
● Resultado (dirección de memoria donde albergar el resultado, o a la que
saltar en caso de que se trate de una operación de salto).
Ejemplo:
Para ilustrar cómo se utiliza el código de tercetos en una gramática vamos a
suponer que nuestra calculadora en lugar de ser una calculadora interpretada es
una calculadora compilada, es decir, en vez de interpretar las expresiones vamos a
generar código intermedio equivalente. [12]
- Pasos de construcción
Antes de comenzar a codificar los analizadores léxico y sintáctico es necesario
plantear exactamente qué se desea hacer y con qué gramática. Para ello se debe
proponer un ejemplo preliminar de lo que debe hacer la calculadora para, a
continuación, crear la gramática que reconozca el lenguaje, asignar los atributos
necesarios y, una vez claro el cometido de las acciones semánticas, comenzar la
codificación. [13]
6
a := 5 * b;
c := b := d := a * (4+v);
c := c := c;
la salida debería ser:
tmp1 = 5 * b
a = tmp1
tmp2 = 4 + v
tmp3 = a * tmp2
d = tmp3
b=d
c=b
c=c
c=c
- Gramática
La gramática de partida basada en reglas de producción es:
7
| ID
| NUMERO
;
Como puede observarse, no se permite el programa vacío, lo que hace que sea
necesario introducir una nueva regla de error que gestione la posibilidad de que se
produzca algún fallo en la primera asignación. Nótese que si se produce un error en
esta primera asignación, la pila del análisis sintáctico aún no tiene el no terminal
prog a su izquierda, por lo que no es posible reducir por la regla prog : prog error
‘;’, pero sí por la regla prog : error ‘;’.
Por otro lado, la finalización de cada sentencia se hace con un punto y coma ‘;’, en
lugar de con retorno de carro, lo que resulta más cercano al tratamiento real de los
lenguajes de programación actuales. [14]
3. Desarrollo
8
escribir.write("public class texto{" + "\n");
escribir.write("}");
escribir.append('\n');
escribir.write("}");
escribir.append('\n');
//Cerramos la conexion
escribir.close();
} catch (IOException e) {
System.out.println("Error al escribrir");
}
}
} catch (Exception e) {
System.out.println("Error AbrirArchivo: " + e);
}
return sb.toString();
9
}
Método del Análisis Semántico.
if(codigo.trim().matches("[+-/*]\\s\\d+\\s\\d+") ||
codigo.trim().matches("[+-/*]\\s[+-/*]\\s\\d+\\s\\d+\\s[+-/*]\\s\\d+\\s\\d+")) {
Expresion expresion = new Expresion(codigo.trim());
System.out.println(expresion.resultado);
resultadoAnalisisSemantico.setText(String.valueOf(expresion.resultado));
}
@Override
public void actionPerformed(ActionEvent arg0) {
String nombreDeArchivo =
AnalizadorSemantico.rutaDeArchivo.getText().trim();
try {
AnalizadorSemantico.resultadoAnalisisLexico.setText(AnalizadorSemantico.analizar(Analiza
dorSemantico.leerArchivo(nombreDeArchivo)));
} catch (IOException e) {
System.out.println(e.getMessage());
}
AnalizadorSemantico.resultadoAnalisisSintactico.setText(AnalizadorSemantico.errores.toStri
ng());
}
10
4. Conclusiones
En conclusión:
11
5. Recomendaciones.
Se recomienda que:
12
6. Bibliografía
[2], [3], [4], [5], [7], [8], [11], [12], [13], [14] Gálvez, S., & Mora, M. Á. (2005). Java
a tope: Traductores y Compiladores con Lex/Yacc, JFlex/Cup y JavaCC.
Universidad de Málaga. Retrieved from
http://www.lcc.uma.es/~galvez/ftp/libros/Compiladores.pdf
13