Tema: INTÉRPRETE ENSAMPOCO/3

Anuncio
Compiladores. Guía 11
1
Facultad:
Ingeniería
Escuela:
Computación
Asignatura: Compiladores
Tema: INTÉRPRETE ENSAMPOCO/3
Contenido
En esta práctica se desarrollará un intérprete de lenguaje
ENSAMPOCO/3 para completar el desarrollo de un compilador.
Objetivos Específicos
Aplicar y
lenguaje.
definir
los
conceptos
de
intérprete
de
un
Material y Equipo
Guía de Laboratorio Nº 11.
Computadora con DevC++
Introducción Teórica
Intérpretes
Guía
3
Los
intérpretes
son programas que simplemente ejecutan las
instrucciones que encuentran en el texto fuente.
En
muchos
Guía
4 casos coexisten en memoria el programa fuente y el
programa intérprete. Nótese que en este caso todo se hace en
tiempo de ejecución.
fía
Algunos
de los lenguajes comúnmente interpretados son el
BASIC, LOGO, PROLOG, SMALLTALK, APL, PHP y LISP.
Funcionamiento de un intérprete
Evidentemente la ejecución de un programa compilado será más
rápida que la del mismo programa interpretado. Sin embargo
los intérpretes son más interactivos y facilitan la puesta a
punto de programas.
2
Compiladores. Guía 11
Algunos lenguajes de programación tan sólo pueden ser
interpretados debido a sus características, por ejemplo
algunos lenguajes funcionales y lenguajes orientados a
objeto. En estos casos existen intérpretes con compiladores
incrementales que pueden recompilar los módulos modificados
en tiempo de ejecución.
Los intérpretes se pueden clasificar desde el punto de vista
de su estructura en varios tipos: intérpretes puros,
intérpretes
avanzados
o
normales,
e
intérpretes
incrementales.
Intérpretes puros
Los intérpretes puros son los que analizan una sentencia y la
ejecutan, y así sucesivamente todo el programa fuente. Fueron
los intérpretes desarrollados en la primera generación de
ordenadores, pues permitían la ejecución de largos programas
con ordenadores de memoria muy reducida, ya que sólo debían
contener en memoria el intérprete y la sentencia a analizar y
ejecutar. El principal problema de este tipo de intérpretes
es que si a mitad del programa fuente se producen errores, se
debe de volver a comenzar el proceso.
En la figura se representa el esquema general de un
intérprete puro, donde se puede observar que el lenguaje
fuente se traduce a una representación interna (texto o
binaria) que puede ser almacenada en memoria o en disco. Esta
representación
interna
tiene
todas
las
instrucciones
numeradas o colocadas consecutivamente en estructuras de
tamaño fijo (por ejemplo un array o posiciones consecutivas
de memoria, o un fichero binario de estructuras de tamaño
fijo).
Mientras se realiza este paso se puede construir la tabla de
etiquetas, que es una tablas que contiene una estructura
donde están todas las etiquetas y su posición en el programa
fuente (las etiquetas se utilizan tanto en las instrucciones
de salto como en las llamadas a procedimientos y funciones).
Una vez que este proceso ha finalizado, comienza la ejecución
por la primera instrucción del código, que se envía al
evaluador de instrucciones, éste la ejecuta (recibiendo datos
si es necesario o enviando un mensaje de error). El evaluador
de instrucciones también determina la instrucción siguiente a
ejecutar, en algunos casos previa consulta a la tabla de
etiquetas. En el caso de que no haya saltos (GOTO) o llamadas
a procedimientos o funciones se ejecuta la siguiente
instrucción a la instrucción en curso.
Compiladores. Guía 11 3
El evaluador de instrucciones puede utilizar dos métodos de
evaluación. El método clásico es la evaluación voraz o
ansiosa, donde se evalúan las expresiones completamente. Otro
método es la evaluación perezosa, evaluándose sólo la parte
necesaria de la expresión (el resto no se evalúa).
Esquema general de un intérprete puro
Intérpretes avanzados
Los intérpretes avanzados o normales incorporan un paso
previo de análisis de todo el programa fuente. Generando
posteriormente un lenguaje intermedio que es ejecutado por
ellos mismos. De esta forma en caso de errores sintácticos no
pasan de la fase de análisis.
Un ejemplo de intérprete avanzado es el que utiliza el
lenguaje Java [JAVAi]. Así un programa en lenguaje java (con
la extensión .java) se compila y produce uno o varios
ficheros con la extensión .class, estos ficheros están en un
formato
binario
denominado
bytecode
independiente
de
plataforma, que se interpreta posteriormente. Esto permite
que el bytecode se ejecute en cualquier sistema operativo que
disponga de un intérprete de bytecode. Dado que la mayor
parte de los navegadores de Internet llevan inmerso un
intérprete de bytecode, esto ha permitido al lenguaje Java
ser uno de los más utilizados en aplicaciones que usen
Internet.
4
Compiladores. Guía 11
Esquema general de un intérprete avanzado
Las aplicaciones de los intérpretes avanzados son:
• Emulación de arquitecturas de ordenadores.
• Método para facilitar la portabilidad de aplicaciones entre
distintas arquitecturas de ordenadores.
• Fase de prueba de lenguajes y arquitecturas de máquinas
abstractas, antes de construir los traductores a código
objeto de una arquitectura determinada.
Intérpretes incrementales
Algunos lenguajes no se pueden compilar, debido a que entre
sus características pueden manejar objetos o funciones que no
son conocidos en tiempo de compilación, ya que son creados en
ejecución.
Para
este
tipo
de
lenguajes
existen
los
intérpretes incrementales, que permiten compilar los módulos
completamente definidos, y recompilar en tiempo de ejecución
los nuevos módulos. Están a medio camino entre los
intérpretes puros y los intérpretes avanzados o normales.
Los intérpretes incrementales tienen gran interés en los
lenguajes que permiten no definir los problemas completamente
en tiempo de compilación. En estos casos se utilizan
evaluadores parciales (partial evaluators) que toman como
entrada el programa fuente junto con algunos datos (pero no
todos), realizándose los cálculos que se pueden hacer con
dicho subconjunto de datos, y produciendo una salida que
contiene
un
residuo
del
programa
fuente
que
se
ha
introducido.
Compiladores. Guía 11 5
Algunos fabricantes de software denominan a los intérpretes
incrementales como compiladores incrementales, debido a que
la palabra intérprete está desprestigiada, y prefieren
acogerse a la parte del intérprete avanzado.
Procedimiento
Considerando la clase “Interprete”, desarrolle un proyecto en
C++ que solicite el nombre del archivo en ENSAMPOCO/3 y a
Guía 3
continuación
ejecute el interprete del archivo.
InterpreteEnsampoco.h
Guía 4
#ifndef INTERPRETE_H
#define INTERPRETE_H
fía
#include
<stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define TAM_MAX_INS 20
using namespace std;
struct pila {
char valor;
struct pila *sucesor;
};
typedef struct pila ELEMENTO;
typedef ELEMENTO *PUNTERO;
class Interprete{
FILE *entrada; //Descriptor del fichero de entrada
bool esCodigo;
int memoria[26];
PUNTERO cabezaPila;
char instruccion[TAM_MAX_INS];
char parametro;
void analizarInstruccion();
void interpretarInstruccion();
void interpretarInstruccionDeCaracter();
void interpretarInstruccionDeFlotante();
void interpretarInstruccionDeInt();
void iabs();
void add();
void code();
void data();
void div();
void end();
6
Compiladores. Guía 11
void iexp();
void i2tof();
void itof();
void load();
void mod();
void mul();
void neg();
void output();
void input();
void pusha();
void pushc();
void isin();
void store();
void itan();
int pop();
void push(int valor);
void error(int num);
public:
Interprete (char *unNombreFicheroEntrada);
~Interprete (void);
};
Interprete::Interprete (char *unNombreFicheroEntrada){
int i;
if ((entrada = fopen(unNombreFicheroEntrada,"r")) == NULL )
error(0);
for(i= 0; i<26; i++) memoria[i] = 0;//inicialización a cero
while (!feof(entrada)){
analizarInstruccion();
if (instruccion[0] != '\0')
interpretarInstruccion();
else{
cout<<"FIN\n";
return;
}
}
}
/**********************************************************/
Interprete::~Interprete (void){
fclose(entrada);
}
/**********************************************************/
void Interprete::analizarInstruccion(){
int n;
if ((instruccion[0] = fgetc(entrada)) != EOF){
n = 1;
while (((instruccion[n] = fgetc(entrada)) != ' ') &&
(instruccion[n] != '\n'))
Compiladores. Guía 11 7
n++;
if (instruccion[n] != '\n'){
while (((parametro = fgetc(entrada)) == ' ') &&
(parametro != '\n'))
;
instruccion[n] = '\0';
if (parametro != '\n'){
while ((n = fgetc(entrada)) != '\n');
}
}
else{
instruccion[n] = '\0';
}
}
else instruccion[0]='\0';
}
void Interprete::interpretarInstruccion() {
switch (instruccion[0]) {
case 'C': interpretarInstruccionDeCaracter();
break;
case '.': if (strcmp (instruccion,".DATA") == 0) data();
else if (strcmp (instruccion,".CODE") == 0)
code();
else error(1);
break;
case 'E': if (strcmp (instruccion,"END") == 0) end();
else error(1);
break;
case 'F': interpretarInstruccionDeFlotante();
break;
case 'I':if (strcmp(instruccion,"ITOF") == 0) itof();
else
if
(strcmp(instruccion,"I2TOF")
==
0)
i2tof();
else interpretarInstruccionDeInt();
break;
default : error(1); break;
}
return;
}
void Interprete::interpretarInstruccionDeCaracter() {
if(!esCodigo)
return;
switch(instruccion[1]){
case 'I':
if (strcmp(instruccion,"CINPUT") == 0) input();
8
Compiladores. Guía 11
else error(1);
break;
case 'L':
if (strcmp(instruccion,"CLOAD") == 0) load();
else error(1);
break;
case 'O':
if (strcmp(instruccion,"COUTPUT") == 0) output();
else error(1);
break;
case 'P':
if (strcmp(instruccion,"CPUSHA") == 0) pusha();
else error(1);
break;
case 'S':
if (strcmp(instruccion,"CSTORE") == 0) store();
else error(1);
break;
default:
error(1);
break;
}
}
void Interprete::interpretarInstruccionDeFlotante(){
if(!esCodigo)
return;
switch(instruccion[1]){
case 'A':
if(strcmp(instruccion,"FABS")==0) iabs();
else if (strcmp(instruccion,"FADD") == 0) add();
else error(1);
break;
case 'D':
if (strcmp(instruccion,"FDIV") == 0) div();
else error(1);
break;
case 'E':
if (strcmp(instruccion,"FEXP") == 0) iexp();
else error(1);
break;
case 'I':
if (strcmp(instruccion,"FINPUT") == 0) input();
else error(1);
break;
case 'L':
if (strcmp(instruccion,"FLOAD") == 0) load();
else error(1);
Compiladores. Guía 11 9
break;
case 'M':
if (strcmp(instruccion,"FMUL") == 0) mul();
else if (strcmp(instruccion,"FMOD") == 0) mod();
else error(1);
break;
case 'N':
if (strcmp(instruccion,"FNEG") == 0) neg();
else error(1);
break;
case 'O':
if (strcmp(instruccion,"FOUTPUT") == 0) output();
else error(1);
break;
case 'P':
if (strcmp(instruccion,"FPUSHA") == 0) pusha();
else error(1);
break;
case 'S':
if (strcmp(instruccion,"FSIN") == 0) isin();
else if (strcmp(instruccion,"FSTORE") == 0) store();
else error(1);
break;
case 'T':
if (strcmp(instruccion,"FTAN") == 0) itan();
else error(1);
break;
default:
error(1);
break;
}
}
void Interprete::interpretarInstruccionDeInt() {
if(!esCodigo)
return;
switch(instruccion[1]){
case 'A':
if (strcmp(instruccion,"IABS") == 0) iabs();
else if(strcmp(instruccion,"IADD")==0) add();
else error(1);
break;
case 'D':
if (strcmp(instruccion,"IDIV") == 0) div();
else error(1);
break;
case 'E':
if (strcmp(instruccion,"IEXP") == 0) iexp();
10 Compiladores. Guía 11
else error(1);
break;
case 'I':
if (strcmp(instruccion,"IINPUT") == 0) input();
else error(1);
break;
case 'L':
if (strcmp(instruccion,"ILOAD") == 0) load();
else error(1);
break;
case 'M':
if (strcmp(instruccion,"IMUL") == 0) mul();
else if (strcmp(instruccion,"IMOD") == 0) mod();
else error(1);
break;
case 'N':
if (strcmp(instruccion,"INEG") == 0) neg();
else error(1);
break;
case 'O':
if (strcmp(instruccion,"IOUTPUT") == 0) output();
else error(1);
break;
case
'P':if
(strcmp(instruccion,"IPUSHC")
==
0)
pushc();
else if (strcmp(instruccion,"IPUSHA") == 0) pusha();
else error(1);
break;
case 'S':
if (strcmp(instruccion,"ISIN")==0) isin();
else if (strcmp(instruccion,"ISTORE") == 0) store();
else error(1);
break;
case 'T':
if(strcmp(instruccion,"ITAN")==0) itan();
else error(1);
break;
default:
error(1);
break;
}
}
//**** INSTRUCCIONES DE ENSAMPOCO *****
void Interprete::iabs(){
push(abs(pop()));
}
void Interprete::add() {
Compiladores. Guía 11 11
PUNTERO p;
p = cabezaPila;
cabezaPila = cabezaPila->sucesor;
cabezaPila->valor = cabezaPila->valor+p->valor;
free((PUNTERO)p);
}
void Interprete::code() {
esCodigo=true;
}
void Interprete::data(){
esCodigo=false;
}
void Interprete::div() {
PUNTERO p;
p = cabezaPila;
cabezaPila = cabezaPila->sucesor;
cabezaPila->valor = (int) (cabezaPila->valor / p->valor);
free((PUNTERO)p);
}
void Interprete::end() {
return;
}
void Interprete::iexp() {
double a = pop();
double b = pop();
//System.out.println(b+" ^ "+a+"= "+ Math.pow(b, a));
push((int)pow(b, a));
}
void Interprete::i2tof() {
//de momento nada la conversion de entero a float es
//automatica en c++
}
void Interprete::input() {
int valor;
cout<<"Entrada "<<parametro<<" > ";
cin>>valor;
memoria[parametro - 'a'] = valor;
}
void Interprete::itof(){
//de momento nada la conversion de entero a float es
//automatica en c++
}
void Interprete::load() {
cabezaPila->valor = memoria[cabezaPila->valor-'a'];
}
void Interprete::mod() {
12 Compiladores. Guía 11
PUNTERO p;
p = cabezaPila;
cabezaPila = cabezaPila->sucesor;
cabezaPila->valor = (( (int)cabezaPila->valor) % ( (int)
p->valor) );
free((PUNTERO)p);
}
void Interprete::mul() {
PUNTERO p;
p = cabezaPila;
cabezaPila = cabezaPila->sucesor;
cabezaPila->valor = cabezaPila->valor*p->valor;
free((PUNTERO)p);
}
void Interprete::neg() {
cabezaPila->valor = -cabezaPila->valor;
}
void Interprete::output() {
cout<<"Salida "<<parametro<<" > "<< memoria[parametro'a']<<endl;
system("pause");
}
void Interprete::pusha() {
PUNTERO p;
p = (PUNTERO) malloc (sizeof(ELEMENTO));
p->valor = parametro;
p->sucesor = cabezaPila;
cabezaPila = p;
}
void Interprete::pushc() {
PUNTERO p;
p = (PUNTERO) malloc (sizeof(ELEMENTO));
p->valor = parametro-'0';
p->sucesor = cabezaPila;
cabezaPila = p;
}
void Interprete::isin(){
push((int)sin(pop()));
}
void Interprete::store() {
PUNTERO p,q;
p = cabezaPila;
q = cabezaPila->sucesor;
if (q->sucesor!=NULL) cabezaPila = q->sucesor;
else cabezaPila=NULL;
memoria[(q->valor)-'a'] = p->valor;
free((PUNTERO)p);
Compiladores. Guía 11 13
free((PUNTERO)q);
}
void Interprete::itan(){
push((int)tan(pop()));
}
//********* FIN DE LAS INSTRUCCIONES DE ENSAMPOCO *******
int Interprete::pop() {
int valor = cabezaPila->valor;
cabezaPila = cabezaPila->sucesor;
return valor;
}
void Interprete::push(int valor) {
PUNTERO nuevo;// = new PUNTERO();
nuevo->valor = valor;
nuevo->sucesor = cabezaPila;
cabezaPila = nuevo;
}
void Interprete::error(int num){
// Manejo de errores
cout<<"Error "<<num;
switch (num){
case
0:
cout<<":
No
encuentra
el
fichero
fuente"<<endl; break;
case
1:
cout<<":
Instrucción
desconocida"<<endl;break;
case 2: cout<<": PUSHA sin variable"<<endl;break;
case 3: cout<<": PUSHC sin constante"<<endl;break;
case 4: cout<<": INPUT sin variable"<<endl;break;
case 5: cout<<": OUTPUT sin vaariable"<<endl;break;
default:
cout<<": No documentado"<<endl; break;
}
}
#endif
Análisis de resultados
Teniendo
en
cuenta
el
siguiente
código
en
lenguaje
ensampoco/3 ejecute el intérprete implementado anteriormente
y describa su funcionamiento.
Prueba.poc
.DATA
INT a
INT b
FLOAT c
FLOAT d
14 Compiladores. Guía 11
.CODE
IINPUT a
IINPUT b
FPUSHA c
IPUSHA a
ILOAD
IPUSHA b
ILOAD
IADD
ITOF
FSTORE
FPUSHA d
IPUSHA a
ILOAD
IPUSHA b
ILOAD
INEG
IADD
ITOF
FSTORE
FOUTPUT c
FOUTPUT d
END
Responda las siguientes cuestiones:
Describa el algoritmo de la clase intérprete.
Clasifique y distinga, ¿qué tipo de intérprete es el
implementado para ENSAMPOCO/3?
Explique, en el caso de ENSAMPOCO/0 que no acepta tipos,
¿cuáles cambios consideraría usted que deberían ser
hechos a este intérprete, para interpretar ENSAMPOCO/0?
Investigación complementaria
Investigue que es un traductor, documente las partes que lo
componen y la actividad principal. Además haga un cuadro
comparativo entre compiladores, traductores e intérpretes.
Bibliografía
Cueva, J.
lenguaje.
(1998). Conceptos
Universidad
básicos
de
de procesadores de
Oviedo,
España.
Compiladores. Guía 11 15
Hoja de cotejo:
Guía 11: Intérprete de Ensampoco/3
Docente:
Tema: Presentación del programa
11
1
Máquina No:
Máquina No:
Alumno:
Máquina No:
GL:
Alumno:
Docente:
GL:
Docente:
GL:
Fecha:
a
EVALUACION
%
CONOCIMIENTO
Del 20
al 30%
APLICACIÓN
DEL
CONOCIMIENTO
Del 40%
al 60%
1-4
5-7
8-10
Conocimie
nto
deficient
e de los
fundament
os
teóricos
Conocimiento
y explicación
incompleta de
los
fundamentos
teóricos
Conocimiento
completo y
explicación
clara de los
fundamentos
teóricos
No tiene
actitud
proactiva
.
Actitud
propositiva y
con
propuestas no
aplicables al
contenido de
la guía.
Tiene actitud
proactiva y sus
propuestas son
concretas.
ACTITUD
Del 15%
al 30%
TOTAL
100%
Nota
Descargar