#include<iostream>
#include<conio.h>
using namespace std;
int main (){
int opcion,opcion2,opcion3,i;
int total,cantidad,tot2,pago, cam,num,num2, tol;
do{
do{
cout<<"***Tienda***"<<endl;
cout<<"Menu"<<endl;
cout<<"1.Ver Productos"<<endl;
cout<<"2.Cotizar Productos"<<endl;
cout<<"3.Comprar Productos"<<endl;
cout<<"4.Salir"<<endl;
cout<<"Escoge una opcion: "<<endl;
cin>>opcion;
if(opcion==4){
opcion2=4;
}
switch(opcion){
case 1: {
cout<<"dame un valor que deseas contar"<<endl;
cin>>num;
cout<<"de cuanto deseas que sea el salto"<<endl;
cin>>num2;
for(i=0;i<=num;i=i+num2)
cout<<i<<endl;
do{
cout<<"*** Elige a el departamento *** "<<endl;
cout<<"1.- Electronica "<<endl;
cout<<"2.- Muebles "<<endl;
cout<<"3.- Regresar al menu "<<endl;
cin>>opcion2;
if(opcion2==3){
opcion3=6;
}
switch(opcion2){
case 1:{
cout<<"*** Electronica ***"<<endl;
cout<<"Smartphone $6,500"<<endl;
cout<<"Pantalla $5,000"<<endl;
cout<<"Dvd $1,500"<<endl;
cout<<"Consola Xbox One $7,600"<<endl;
cout<<"Presione 1 para regresar"<<endl;
cin>>opcion3;
break;
}
case 2:{
cout<<"*** Muebles ***"<<endl;
cout<<"Sala $9,000 "<<endl;
cout<<" Comedor $3,500 "<<endl;
cout<<"Cocina $8,000"<<endl;
cout<<"Cama Matrimonial $6,600"<<endl;
cout<<"Presione 1 para regresar"<<endl;
cin>>opcion3;
break;
}
}
}while(opcion3<6);
break;
}
case 2:{
do{
cout<<"*** Elige a el departamento *** "<<endl;
cout<<"1.- Electronica "<<endl;
cout<<"2.- Muebles "<<endl;
cout<<"3.- Regresar al menu "<<endl;
cin>>opcion2;
if(opcion2==3){
opcion3=6;
}
switch(opcion2){
case 1:{
cout<<"***Cotizacion del departamento de Electronica***"<<endl;
cout<<"Presiona el numero del producto que deseas cotizar: "<<endl;
cout<<"1.- Smartphone $6,500"<<endl;
cout<<"2.- Pantalla $5,000"<<endl;
cout<<"3.- Dvd $1,500 "<<endl;
cout<<"4.- Consola Xbox One $7,600"<<endl;
cout<<"Presione 1 para regresar"<<endl;
cin>>opcion3;
if(opcion3==1){
cout<<"¿Cuantos Smartphone deseas? "<<endl;
cin>>cantidad;
total=cantidad*6500;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}else{
if(opcion3==2){
cout<<"¿Cuantas pantallas deseas? "<<endl;
cin>>cantidad;
total=cantidad*5000;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}else{
if(opcion3==3){
cout<<"¿Cuantos Dvd deseas? "<<endl;
cin>>cantidad;
total=cantidad*1500;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}else{
if(opcion3==4){
cout<<"¿Cuantos Xbox One deseas? "<<endl;
cin>>cantidad;
total=cantidad*7600;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}
}
}
}
break;
}
case 2: {
cout<<"***Cotizacion del departamento de Muebles***"<<endl;
cout<<"Presiona el numero del producto que deseas cotizar: "<<endl;
cout<<"1.- Sala $9,000"<<endl;
cout<<"2.- _Comedor $3,500"<<endl;
cout<<"3.- Cocina $8,000"<<endl;
cout<<"4.- Cama matrimonial $6,000"<<endl;
cout<<"Presione 1 para regresar"<<endl;
cin>>opcion3;
if(opcion3==1){
cout<<"¿Cuantas salas deseas? "<<endl;
cin>>cantidad;
total=cantidad*9000;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}else{
if(opcion3==2){
cout<<"¿Cuantos comedores deseas? "<<endl;
cin>>cantidad;
total=cantidad*3500;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}else{
if(opcion3==3){
cout<<"¿Cuantas cocinas deseas? "<<endl;
cin>>cantidad;
total=cantidad*8000;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}else{
if(opcion3==4){
cout<<"¿Cuantas camas matrimoniales deseas? "<<endl;
cin>>cantidad;
total=cantidad*6000;
cout<<"Tu cantidad a pagar seria de: "<<total<<endl;
}
}
}
}
break;
}
}
}while(opcion3<6);
break;
}
case 3:{
do{
cout<<"*** Elige a el departamento *** "<<endl;
cout<<"1.- Electronica "<<endl;
cout<<"2.- Muebles "<<endl;
cout<<"3.- Regresar al menu "<<endl;
cin>>opcion2;
if(opcion2==3){
opcion3=6;
}
switch(opcion2){
case 1:{
cout<<"***Realizar la compra del departamento de Electronica***"<<endl;
cout<<"1.- Smartphone $6,500"<<endl;
cout<<"2.- Pantalla $5,000"<<endl;
cout<<"3.- Dvd $1,500 "<<endl;
cout<<"4.- Consola Xbox One $7,600"<<endl;
cout<<"Elige el producto "<<endl;
cout<<"Presione 1 para regresar"<<endl;
cin>>opcion3;
if(opcion3==1){
cout<<"¿Cuantos Smartphone deseas adquirir? "<<endl;
cin>>cantidad;
total=cantidad*6500;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}else{
if(opcion3==2){
cout<<"¿Cuantas pantallas deseas? "<<endl;
cin>>cantidad;
total=cantidad*5000;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}else{
if(opcion3==3){
cout<<"¿Cuantos Dvd deseas ? "<<endl;
cin>>cantidad;
total=cantidad*1500;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}else{
if(opcion3==4){
cout<<"¿ Cuantos Xbox One deseas? "<<endl;
cin>>cantidad;
total=cantidad*7600;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}
}
}
}
break;
}
case 2: {
cout<<"***Realizar compra del departamento Muebles ***"<<endl;
cout<<"1.- Sala $9,000"<<endl;
cout<<"2.- _Comedor $3,500"<<endl;
cout<<"3.- Cocina $8,000"<<endl;
cout<<"4.- Cama matrimonial $6,000"<<endl;
cout<<"Elige un producto"<<endl;
cout<<"Presione 1 para regresar"<<endl;
cin>>opcion3;
if(opcion3==1){
cout<<"¿Cuantas salas deseas? "<<endl;
cin>>cantidad;
total=cantidad*9000;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}else{
if(opcion3==2){
cout<<"¿Cuantos comedores deseas? "<<endl;
cin>>cantidad;
total=cantidad*3500;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}else{
if(opcion3==3){
cout<<"¿Cuantas cocinas deseas? "<<endl;
cin>>cantidad;
total=cantidad*8000;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}else{
if(opcion3==4){
cout<<"¿Cuantas camas matrimoniales deseas? "<<endl;
cin>>cantidad;
total=cantidad*6000;
cout<<"Tu cantidad a pagar es de: "<<total<<endl;
cout<<"Introduce tu pago "<<endl;
cin>>pago;
tot2=pago-total;
if (tot2==total){
cout<<"Gracias por tu compra"<<endl;
}
if (tot2>total){
cam=tot2-total;
cout<<"Tu cambio es de: "<<cam<<endl;
}
if (tot2<total){
cam=total-tot2;
cout<<"Falta por pagar: "<<cam<<endl;
}
}
}
}
}
break;
}
}
}while(opcion3<6);
break;
}
}
}while(opcion2<4);
}while(opcion!=4);
getch();
}
martes, 6 de junio de 2017
lunes, 8 de mayo de 2017
Analisis semantico y generacion de codigo intermedio
public class Principal { /** * @param args */ public static void main(String[] args) { System.out.println("-------------------<< Clase Padre Vehiculo >>-----------------------"); Vehiculo miVehiculo = new Vehiculo(); miVehiculo.nombreVehiculo="El Gran Transportador"; System.out.println("usando miVehiculo, nombreVehiculo : "+miVehiculo.nombreVehiculo); System.out.println("usando miVehiculo llama a: "+miVehiculo.transportar()); System.out.println("--------------------------------------------------------------------"); System.out.println(); System.out.println("----------<< SubClase hija Acuatico Extiende de Vehiculo >>---------"); Acuatico miAcuatico= new Acuatico(); miAcuatico.nombreVehiculo="El Navegante"; System.out.println("usando miAcuatico, nombreVehiculo : "+miAcuatico.nombreVehiculo); System.out.println("usando miAcuatico llama a : "+miAcuatico.transportar()); System.out.println("usando miAcuatico llama a : "+miAcuatico.navegar()); System.out.println("---------------------------------------------------------------------"); System.out.println(); System.out.println("-----<< SubClases hijas extienden de la Subclase Padre Acuatico>-----"); Barco miBarco=new Barco(); miBarco.nombreVehiculo="Titanic"; System.out.println("usando miBarco, nombreVehiculo : "+miBarco.nombreVehiculo); System.out.println("usando miBarco llama a : "+miBarco.transportar()); System.out.println("usando miBarco llama a : "+miBarco.navegar()); System.out.println("usando miBarco llama a : "+miBarco.prenderMotor()); System.out.println(); Velero miVelero=new Velero(); miVelero.nombreVehiculo="Tormenta"; System.out.println("usando miVelero, nombreVehiculo : "+miVelero.nombreVehiculo); System.out.println("usando miVelero llama a : "+miVelero.transportar()); System.out.println("usando miVelero llama a : "+miVelero.navegar()); System.out.println("usando miVelero llama a : "+miVelero.izarVelas()); System.out.println("---------------------------------------------------------------------"); System.out.println("----------<< SubClase hija Aereo Extiende de Vehiculo >>---------"); Aereo miAereo= new Aereo(); miAereo.nombreVehiculo="El Volador"; System.out.println("usando miAereo, nombreVehiculo : "+miAereo.nombreVehiculo); System.out.println("usando miAereo llama a : "+miAereo.transportar()); System.out.println("usando miAereo llama a : "+miAereo.volar()); System.out.println("---------------------------------------------------------------------"); System.out.println(); System.out.println("-----<< SubClases hijas extienden de la Subclase Padre Aereo >-----"); Avion miAvion=new Avion(); miAvion.nombreVehiculo="El Condor"; System.out.println("usando miAvion, nombreVehiculo : "+miAvion.nombreVehiculo); System.out.println("usando miAvion llama a : "+miAvion.transportar()); System.out.println("usando miAvion llama a : "+miAvion.volar()); System.out.println("usando miAvion llama a : "+miAvion.bajarTrenDeAterrizaje()); System.out.println(); Helicoptero miHelicoptero=new Helicoptero(); miHelicoptero.nombreVehiculo="El lobo del Aire"; System.out.println("usando miHelicoptero, nombreVehiculo : "+miHelicoptero.nombreVehiculo); System.out.println("usando miHelicoptero llama a : "+miHelicoptero.transportar()); System.out.println("usando miHelicoptero llama a : "+miHelicoptero.volar()); System.out.println("usando miHelicoptero llama a : "+miHelicoptero.encenderHelices()); System.out.println("---------------------------------------------------------------------"); System.out.println(); System.out.println("--<< Propiedad de la clase Vehiculo usada por todas las clases Hijas >--"); System.out.println("nombre Vehiculo :"+miVehiculo.nombreVehiculo); System.out.println("nombre Acuatico :"+miAcuatico.nombreVehiculo); System.out.println("nombre Aereo :"+miAereo.nombreVehiculo); System.out.println("nombre Barco :"+miBarco.nombreVehiculo); System.out.println("nombre Velero :"+miVelero.nombreVehiculo); System.out.println("nombre Avion :"+miAvion.nombreVehiculo); System.out.println("nombre Helicoptero :"+miHelicoptero.nombreVehiculo); System.out.println("---------------------------------------------------------------------"); } }
Vehiculo.Clase Padre./** * @author HENAO * */ public class Vehiculo { public int modeloVehiculo; public String nombreVehiculo=""; public String transportar(){ return "Metodo transportar de clase Vehiculo"; } }Acuatico.SubClase extiende de Vehiculo.public class Acuatico extends Vehiculo{ public String nombreAcuatico=""; public String navegar(){ return "Método navegar de clase Acuatico"; } }Aereo.SubClase extiende de Vehiculo.public class Aereo extends Vehiculo { public String nombreAereo=""; public String volar(){ return "Método volar desde clase Aereo"; } }Barco.SubClase extiende de Acuatico.public class Barco extends Acuatico { public String prenderMotor(){ return "Método prenderMotor en clase Barco"; } }Velero.SubClase extiende de Acuatico.public class Velero extends Barco{ public String izarVelas(){ return "Método izarVelas en clase Velero"; } }Clase Avion. SubClase extiende de Aereo.public class Avion extends Aereo{ public String bajarTrenDeAterrizaje(){ return "Método bajarTrenDeAterrizaje en clase Avion"; } }Clase Helicoptero. SubClase extiende de Aereo.public class Helicoptero extends Aereo{ public String encenderHelices(){ return "Método encenderHelices en clase Helicoptero"; } }
Diferencia entre atributos heredados y atributos sintetizadosAtributos Sintetizados
- Los atributos sintetizados se utilizan ampliamente.
- Si una definición dirigida por sintaxis tiene únicamente atributos sintetizados se dice que es S-atribuida.
- El árbol de análisis sintáctico de una gramática S-atribuida puede decorarse mediante un recorrido en post orden.
Atributos Heredados
- Sirven para expresar la dependencia que hay entre una construcción del lenguaje de programación y su contexto.
- Siempre es posible reescribir una definición dirigida por sintaxis para que sea S-atribuida.
- En ocasiones es más natural utilizar atributos heredados
martes, 4 de abril de 2017
Generacion de codigo
GENERACION DE
CODIGO
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.
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:
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.
El código intermedio que vamos a usar,
posee cuatro apartados:
• Operando 1º
• Operando 2º
• Operador
• Resultado
y se denomina código de 3 direcciones,
de tercetos, o máximo 3 operandos.
Hay algunas instrucciones que carecen de
algunos de estos apartados; los tercetos que podemos usar son:
• Asignación binaria: x := y op z,
donde op es una operación binaria aritmética o lógica.
• Asignación unaria: x := op,
donde op es una operación unaria. Las operaciones unarias principales
incluyen el menos unario, la negación lógica, los operadores de desplazamiento
y operadores de conversión de tipos.
• Asignación simple o copia: x := y,
donde el valor de y se asigna a x.
• Salto incondicional: goto etiqueta.
• Saltos condicionales: if x
oprelacional y goto etiqueta
a = 3 +
b + 5 + c
Hasta ahora, para generar el código de
tercetos no hemos tenido que tener en cuenta los valores de a, b,
y c. Por lo tanto no nos ha hecho falta ninguna tabla de símbolos para
generar el código de terceto. Según el problema que tengamos planteado hay que
ver si hace falta o no una tabla de símbolos. En el ejemplo anterior no hace
falta una tabla de símbolos, porque no hay chequeo de tipos. Pero si tenemos un
problema en el que exista una zona de declaración y una zona de definición
Generación de código en Sentencias de
control
En el caso de las expresiones, nos
basábamos en las variables temporales para generar código. Ahora el problema
son los cambios de flujos
IF - THEN- ELSE
CASE
WHILE
REPEAT
Vamos a trabajar con cambios de
flujos mediante condiciones:
WHILE _
Mientras
se cumple la condición
REPEAT _
Hasta
que se cumpla la condición
Condición
compuesta: Si
se enlazan condiciones mediante operadores lógicos AND u
OR emplearemos la técnica del
cortocircuito, de manera que si enlazamos cond1 y cond2 con un
AND, (cond1 AND cond2), pues si cond1 es falso, no evaluaremos cond2,
dado que su función será falsa sea cual sea el valor de cond2.
Si el conector es OR, (cond1 OR
cond2), la cond2 sólo se evaluará si la cond1 es falsa, pues
en caso contrario, su disyunción será verdad para cualquier valor de cond2.
Sentencias que nos
permite nuestro lenguaje
Ahora se trata de utilizar estas
condiciones y sus etiquetas asociadas, para generar el código de sentencias que
implican condiciones, como son IF, WHILE y REPEAT.
• Sentencia IF-THEN-ELSE
El caso del IF es el caso más
simple. Aquí basta, con indicar que la etiqueta de verdad de la condición está
asociada al código a continuación del THEN, y la etiqueta de falso se asocia al
código que puede haber tras el ELSE. En cualquier caso, una vez acabadas las
sentencias del THEN se debe producir un salto al final del IF, porque no
queremos que se ejecuten también las sentencias del ELSE. Por tanto, tras la
sentencias del THEN, creamos una nueva etiqueta a la cual produciremos un
salto, y colocamos el destino de tal etiqueta al final del código del IF
Sentencia WHILE
El caso de WHILE y REPEAT es muy
similar. En ambos creamos una etiqueta al comienzo del bucle, a la que se
saltará para repetir cada iteración.
En el caso del WHILE, a
continuación se genera el código de la condición. La etiqueta de verdad se pone
justo antes de las sentencias del WHILE, que es lo que se debe ejecutar si la
condición es cierta. Al final de las sentencias se pondrá un salto al inicio
del bucle, donde de nuevo se comprobará la condición. La etiqueta de falso de
la condición, se pondrá al final de todo lo relacionado con el WHILE, o lo que
es lo mismo, al principio del código generado para las sentencias que siguen al
WHILE.
IF
cond THEN sent ELSE sent FIN IF
|
WHILE cond DO sent FIN WHILE
Sentencia REPEAT
Como ya se dijo, creamos una
etiqueta al comienzo del bucle, a la que se saltará para repetir cada iteración
En el caso del REPEAT, a
continuación de la etiqueta de comienzo del bucle colocamos el código de las
sentencias, ya que la condición se evalúa al final. Tras las sentencias
colocamos el código de la condición. Ahora, debemos hacer coincidir la etiqueta
de comienzo del bucle con la etiqueta de falso de la condición,. Como ambos
nombres ya están asignados, la solución es colocar la etiqueta de falso, y en
ella un goto al comienzo del bucle.
Al final de todo el código asociado
al REPEAT pondremos la etiqueta de verdad.
IF
cond THEN sent ELSE sent FIN IF
|
WHILE cond DO sent FIN WHILE
|
REPEAT sent UNTIL cond
Sentencia CASE
La sentencia más compleja de todas
es la sentencia CASE, ya que ésta permite un número indeterminado, y
potencialmente infinito de condiciones, lo cual obliga a arrastrar una serie de
parámetros a medida que se van efectuando reducciones.
El problema es que la sentencia
CASE necesita una recursión (no podemos utilizar una única regla de
producción). Es necesario una regla de producción para la sentencia CASE
diferente.
AST (Abstract Syntax Trees): forma condensada
de árboles de análisis, con sólo nodos semánticos y
sin nodos para símbolos terminales (se
supone que el programa es sintácticamente correcto).
• Ventajas: unificación de pasos de
compilación
– Creación del árbol y la tablade
símbolos
– Análisis semántico
– Optimización
– Generación de código objeto
• Desventaja:
– espacio para almacenamiento
DAG (Directed Acyclic Graphs): árboles
sintácticos concisos
Ahorran algo de espacio
– Resaltan operaciones duplicadas en el
código
– Difíciles de construir
TAC (Three-Address Code): secuencia de instrucciones
de la forma:
– operador: aritmético / lógico
– operandos/resultado: constantes,
nombres, temporales.
• Se corresponde con instrucciones del
tipo:
A := b + c
• Las operaciones más complejas requieren
varias instrucciones:
• Este ‘desenrollado’ facilita la
optimización y generación de código final.
• Ensamblador general y simplificado para
una máquina virtual: incluye etiquetas, instrucciones de flujo de control…
• Incluye referencias explícitas a las direcciones
de los resultados intermedios (se les da nombre).
• La utilización de nombres permite la reorganización
(hasta cierto punto).
• Algunos compiladores generan este código
como código final; se puede interpretar fácilmente (UCSD PCODE, Java).
Notación posfija
• Polaca inversa, código de cero
direcciones:
– notación matemática libre de
paréntesis
– los operadores aparecen después de los
operandos
• Ventajas:
– Código generado conciso.
– No hacen falta temporales.
– Algunas optimizaciones sencillas.
– Mantiene la estructura sintáctica.
• Desventajas:
– Código dependiente de la posición.
– solo efectiva si el ‘target’ es de
pila.
Generación
de código intermedio
• Consideración fundamental: generación
de código correcto.
• no se genera código (hay excepciones).
• se limita a resolver problemas relacionados
con almacenamiento de los objetos:
– Espacio requerido
– Lugar en la memoria
– Valor
• hay información explícita e implícita
en el fuente.
• ¿Y si se permite mezclar declaraciones
de variables y procedimientos?
• ¿Y si necesitas mantener información
sobre el tamaño de cada bloque?
• C: este problema no existe.
• Pascal: muchos compiladores lo
prohíben.
Expresiones
y Asignación
• De los operandos:
– Determinar su localización
– Efectuar conversiones implícitas
• De los operadores:
– Respetar su precedencia
– Respetar su asociatividad
– Respetar orden de evaluación (si
definido)
– Determinar interpretación correcta (si
sobrecargado)
• Instrucciones generadas
– Acceso a datos
» Variables simples
» Registros
» Vectores
– Manipulación de datos
» Conversiones
» Operaciones
– Flujo de control
» Validación de subrangos
» Operadores complejos
Reutilización de temporales
• Una vez que una variable temporal
aparece como operando, deja de utilizarse.
• Al traducir el código intermedio, en
lo posible se utilizarán registros (habrá una cantidad limitada); de lo contrario,
posiciones de memoria.
• Reducción de temporales requeridas:
Invocación de Procedimientos
• Cuando se evalúan las expresiones correspondientes
a los argumentos, éstos van almacenándose en la pila.
• Al crear el BA del procedimiento, debe
respetarse el tamaño del bloque actual
• El cambio de nivel es la diferencia
entre el nivel actual y el invocado.
• La dirección del procedimiento o
función se determina al introducir el símbolo en la tabla.
Utilización de parámetros
1. valor de un parámetro por referencia
2. dirección de un parámetro por
referencia
3. valor de un parámetro por valor y
otro por referencia
4. parámetro por valor utilizado como
argumento a parámetro por referencia
5. parámetro por referencia utilizado
como argumento a parámetro por referencia
6. variables utilizadas como parámetros
por valor y referencia respectivamente
lunes, 27 de marzo de 2017
Analizador Sintáctico
El análisis sintáctico es un
análisis a nivel de sentencias, y es mucho más complejo que el análisis léxico.
Su función es tomar el programa fuente en forma de tokens, que recibe del
analizador léxico, y determinar la estructura de las sentencias del programa.
Este proceso es similar a determinar la estructura de una frase en Castellano,
determinando quien es el sujeto, predicado, el verbo y los complementos.
El análisis sintáctico agrupa
a los tokens en clases sintácticas (denominadas no terminales en la definición
de la gramática), tales como expresiones, procedimientos, etc. El analizador
sintáctico o parser obtiene un árbol sintáctico (u otra estructura equivalente)
en la cual las hojas son los tokens, y cualquier nodo que no sea una hoja,
representa un tipo de clase sintáctica (operaciones). Por ejemplo el análisis
sintáctico de la siguiente expresión
La estructura de la gramática
anterior refleja la prioridad de los operadores, así los operadores “+” y “-”
tienen la prioridad más baja, mientras que “*” y “/” tienen una prioridad
superior. Se evaluaran en primer lugar las constantes, variables y expresiones
entre paréntesis. Los árboles sintácticos se construyen con un conjunto de
reglas conocidas como gramática, y que definen con total precisión el lenguaje
fuente. Al proceso de reconocer la estructura del lenguaje fuente se conoce con
el nombre de análisis sintáctico (parsing). Hay distintas clases de
analizadores o reconocedores sintácticos, pero en general se clasifican en 2
grandes grupos: A.S. Ascendentes y A.S. Descendentes.
Caracteristicas
• Lee componentes léxicos (tokens)
• Comprueba que el orden de
estos corresponde a la sintaxis predeterminada
• Genera errores en caso de que el flujo de
tokens no responda a la sintaxis
• Genera árboles de análisis sintáctico
• Se suele conocer como “Parser”
• El análisis sintáctico
desarrolla el esqueleto de toda la fase de análisis
• Utiliza el analizador léxico
como una rutina dentro del análisis sintáctico ( getNextToken() )
• Integra el análisis semántico como un
conjunto de rutinas a ejecutar durante la comprobación de la sintaxis.
• Aunque el objetivo teórico
es construir un árbol de análisis sintáctico, este raramente se construye como
tal, sino que las rutinas semánticas integradas van generando el árbol de
sintaxis abstracta.
• El análisis sintáctico se
especifica mediante una gramática libre de contexto
• El análisis sintáctico se
implementa mediante un autómata de pila
Analizador sintáctico ascendente: Intenta construir
un árbol de análisis sintáctico, empezando desde la raíz
y descendiendo hacia las hojas. Lo que es lo mismo que
intentar obtener una derivación por la izquierda para
una cadena de entrada, comenzando desde la raíz y
creando los nodos del árbol en orden previo.
Analizador sintáctico descendente: Intenta construir
un árbol de análisis sintáctico, empezando desde
las hojas (la cadena) y ascendiendo hacia la raíz. Lo
que es lo mismo que intentar obtener una reducción
desde una cadena hasta llegar al axioma.
El analizador sintáctico tanto ascendente como descendente
puede representarse de dos formas:
mediante tabla de análisis sintáctico o mediante autómata
de pilas.
Elminacion de re cursiva de izquierda
Una gramática es recursiva por
la izquierda si tiene un no terminal A tal que existe una derivación
A Aα para
alguna cadena α. Los métodos de análisis sintáctico descendente no pueden
manejar gramáticas recursivas por la izquierda, así que se necesita una
transformación que elimine la recursión por la izquierda.
Recursión por la izquierda
inmediata simple (Eliminación de la recursividad izquierda de las
producciones)
En este caso la recursión por
la izquierda se presenta solo en las reglas gramaticales
A → A α | β
Donde α y β son cadenas de
terminales y no terminales y β no comienza en A. Esta regla genera todas
las cadenas de la forma β, β α, β α α…Todas las cadenas comienzan con una β,
seguida por (0 o mas α). Esta regla gramatical es
equivalente a la expresión regular β αⁿ
Para eliminar la
recursión por la izquierda volvemos a escribir estas reglas
gramaticales divididas en dos: una para que primero genere β y otra que
genere las repeticiones de α utilizando recursión por la derecha en vez
de recursión por la izquierda:
A → β A´
A´→ α A´|є
Ejemplo Considere de nueva
cuenta la regla recursiva izquierda de la gramática de expresión simple:
exp → exp opsuma term | term
La forma de esta regla
es A → A α | β, con A= exp, α=opsuma term y β=term. Al volverla a
escribir para eliminar la recursividad por la izquierda obtenemos que
exp → term exp´
Analizador sintáctico ascendente: Intenta construir un árbol de análisis sintáctico, empezando desde la raíz y descendiendo hacia las hojas. Lo que es lo mismo que intentar obtener una derivación por la izquierda para una cadena de entrada, comenzando desde la raíz y creando los nodos del árbol en orden previo.
Suscribirse a:
Entradas (Atom)