Você está na página 1de 65

TECNOLGICO NACIONAL DE MXICO

INSTITUTO TECNOLOGICO DE ACAPULCO

Educacin Tecnolgica con compromiso social

Ingeniera en Sistemas Computacionales


Carrera
Lenguajes y autmatas II
Asignatura
Actividades de aprendizaje
Unidad 2Generacin de cdigo intermedio
Competencia especfica a desarrollar
Aplicar las herramientas para desarrollar una mquina virtual que ejecute cdigo
intermedio a partir del cdigo fuente de un lenguaje prototipo.

Profesor: Silvestre Bedolla Solano.


Integrantes del equipo 7
Alumnos:
Jimenez Gonzalez Alam Emmanuel
Hidalgo Snchez Teresita Berenice
Arancibia Garca ngel Andrs

10320978
11320155
10320918

Acapulco, Guerrero, 6 de Diciembre del 2015

Contenido
Introduccin......................................................................................................... 3
Actividad 1: Reporte de la aplicacin de los tipos de notacin para la conversin de
expresiones: Infija, prefija y posfija, como resultado de su ejecucin en un programa
diseado en C#.................................................................................................... 6
Actividad 2: Reporte de la aplicacin del manejo de tipos en las expresiones y el uso de
operadores........................................................................................................ 13
Actividad 3: Cdigo intermedio de la estructura de un lenguaje de programacin de alto
nivel.................................................................................................................. 14
Actividad 4: Lenguaje prototipo aplicando las acciones construidas a la gramtica.......27
Actividad 5: Tres programas tipo, usando la gramtica definida de su lenguaje de
programacin..................................................................................................... 37
Actividad 6: Reporte del avance por equipo del proyecto final consistente en desarrollar
software de base: traductor, intrprete o compilador................................................46
Conclusin........................................................................................................ 63
Bibliografas....................................................................................................... 64

Introduccin
Generacin de cdigo intermedio

El objetivo del cdigo intermedio es reducir el nmero de programas


necesarios para construir traductores, y permitir ms fcilmente la
transportabilidad de unas mquinas a otras.

Despus de los anlisis sintctico y semntico, algunos compiladores


generan una representacin intermedia explicita del programa fuente. Esta
representacin intermedia debe tener dos propiedades importantes; debe ser fcil
de producir y fcil de traducir al programa objeto.
Lenguajes intermedios
Un lenguaje intermedio es el lenguaje de una mquina abstracta diseada para
ayudar en el anlisis de los programas de computadora. el trmino viene de su
uso en los compiladores, donde un compilador primero traduce el cdigo fuente de
un programa, en una forma ms apropiada para las transformaciones de mejora
del cdigo (forma usualmente llamada bytecode), como un paso intermedio antes
de generar el archivo objeto o el cdigo mquina para una mquina especfica.

Caractersticas destacadas:

Su principal ventaja es la portabilidad, pues el mismo cdigo puede ser ejecutado


en diferentes plataformas y arquitecturas.
Esta ventaja la tiene tambin los lenguajes interpretados, aunque generalmente
con mejor rendimiento. Por esto, muchos lenguajes interpretados se compilan a
bytecode y despus son ejecutados por un intrprete de bytecode.
en java generalmente se transmite el bytecode a la mquina receptora y esta se
encarga de utilizar un compilador just-in-time para traducirlo a cdigo mquina
antes de su ejecucin.

Tipos de lenguaje intermedio

Hay tres tipos de lenguaje intermedio los cuales son:

Tipo 1

Es una representacin ms abstracta y uniforme que un lenguaje mquina


concreto. Su misin es descomponer las expresiones complejas en binarias y las
sentencias complejas en sentencias simples.
3

Ventajas:

permite una fase de anlisis (anlisis semntico) independiente de la


mquina.
*bytecode: cdigo intermedio entre el cdigo fuente y el cdigo mquina. suele
tratrselo como un fichero binario que contiene un programa ejecutable similar a
un mdulo objeto.

Se pueden realizar optimizaciones sobre el cdigo intermedio (las


complejas rutinas de optimizacin son independientes de la mquina.
Desventajas:

perdida de eficiencia (no permite una compilacin de una sola pasada).

introduce en el compilador una nueva fase de traduccin.

Tipo 2

Tipo de lenguajes intermedios:

rbol sintctico.

rbol sintctico abstracto (todos los nodos del rbol representan smbolos
terminales, los nodos hijos son operandos y los nodos internos son operadores).

Grafo dirigido a cclico (gda).

Notacin posfija.

Tipo 3

Tripelatas

Ejemplo:
d = a + b * c [1] (*, b, c) [2] (+, a, [1]) [3] (=, d, [2]) <operador>,<operando_1>,
<operando_2>

Cuartetos

Ejemplo:
d = a + b * c (*, b, c, temp1) (+, a, temp1, temp2) (=, temp2, , d)

Los lenguajes intermedios nos sirven para representar la produccin final de


nuestro lenguaje fuente.

existen muchos lenguajes intermedios, la mayora de ellos son una


representacin ms simplificada del cdigo original para facilitar la traduccin
hacia el cdigo final.

Por ejemplo al compilar un programa en c en windows o dos, se produce un


cdigo objeto con extensin .obj para que posteriormente el enlazador cree
finalmente el cdigo executable .exe

En sistemas basados en unix, tambin ocurre algo similar generndose un


archivo .o y el executablea.out

Otros lenguajes intermedios famosos son los generados para la mquina


virtual de java el bytecode; y para la mquina virtual de .net el misl para luego
ejecutarse en tiempo de ejecucin jit (just in time).

Actividad 1: Reporte de la aplicacin de los tipos de notacin para la


conversin de expresiones: Infija, prefija y posfija, como resultado de su
ejecucin en un programa diseado en C#.

Expresiones infijas, prefija, posfija

PreFija:

La Expresin o Notacin PreFija nos indica que el operador va antes de los


operandos sus caractersticas principales son:
-Los operandos conservan el mismo orden que la notacin infija equivalente.
-No requiere de parntesis para indicar el orden de precedencia de operadores ya
que el es una operacin.
-Se evala de izquierda a derecha hasta que encontrmosle primer operador
seguido inmediatamente de un par de operandos.
-Se evala la expresin binaria y el resultado se cambia como un nuevo operando.
Se repite este hasta que nos quede un solo resultado.

Notacin prefija: El orden es operador, primer operando, segundo operando

InFija:

La Expresin o Notacin InFija es la forma ms comn que utilizamos para escribir


expresiones matemticas, estas notaciones se refiere a que el operador esta entre
los operandos. La notacin infija puede estar completamente patentizada o puede
basarse en un esquema de precedencia de operadores as como el uso de
parntesis para invalidar los arreglos al expresar el orden de evaluacin de una
expresin:
3*4=12
3*4+2=14
3*(4+2)=18
Notacin infija: La notacin habitual. El orden es primer operando, operador,
segundo operando.

PosFija:

Como su nombre lo indica se refiere a que el operador ocupa la posicin despus


de los operandos sus caractersticas principales son:
-El orden de los operandos se conserva igual que la expresin infija equivalente no
utiliza parntesis ya que no es una operacin ambigua.
6

-La operacin posfija no es exactamente lo inverso a la operacin prefija


equivalente:
(A+B)*C AB+C*
Notacin postfija: El orden es primer operando, segundo operando, operador.
Ejemplo:
Si deseamos representar las expresiones (2+(3*4)) = x y ((2+3)*4)= x en las tres
notaciones mencionadas, el resultado sera:
(2+(3*4)) = x ((2+3)*4) = x
Notacin prefija

=+2*34x =*+234x

Notacin infija

2+3*4 = x

Notacin posfija

234*+x= 23+4*x=

(2+3)*4 = x

Desarrollo
Cdigo
Conversin de expresiones infija a posfija
#include <stdio.h>
bool isOperator(char c)
{
if (c=='+' || c=='-' || c=='*' || c=='/' || c=='^' || c=='(' || c==')')
return true;
return false;
}
int precedencia (char x, char y)
{
int prec1, prec2;
switch(x)
{
case '+':
prec1=1;
break;
case '-':
prec1=2;
7

break;
case '*':
prec1=3;
break;
case '/':
prec1=4;
break;
case '^':
prec1=5;
}
switch(y)
{
case '+':
prec2=1;
break;
case '-':
prec2=2;
break;
case '*':
prec2=3;
break;
case '/':
prec2=4;
break;
case '^':
prec2=5;
}
return prec1-prec2;
}
int main()
{
char *inf = new char[401];
char *post = new char[401];
char *pila = new char[200];
int ptr=0;

int n, j=0;
scanf("%d", &n);
while(n>0)
{
scanf("%s", inf);
for(int i=0; inf[i]!='\0'; i++)
{
if (!isOperator(inf[i]))
{
post[j]=inf[i];
j++;
}
else if (inf[i]=='(')
{
pila[++ptr]='(';
}
else if (inf[i]==')')
{
while(pila[ptr]!='(' && ptr>0)
{
post[j]=pila[ptr--];
j++;
}
if (pila[ptr]=='(')
ptr--;
}
else
{
while(precedencia(inf[i], pila[ptr]) < 0 && pila[ptr]!='(' && ptr>0)
{
post[j]=pila[ptr--];
j++;
}
pila[++ptr]=inf[i];
}
}
while(ptr>0)
{
post[j]=pila[ptr--];
j++;
}
post[j]='\0';
9

printf("%s\n", post);
j=0;ptr=0;
n--;
}
return 0;
}
}

Pantallazos

Ejemplo: conversin de expresiones infijas a posfija

Entrada de expresiones infijas:


3 nmeros de elementos que se desean consultar
(a+(b*c))
((a+b)*(z+x))
((a+t)*((b+(a+c))^(c+d)))

Salida de expresiones posfijas:


abc*+
ab+zx+*
at+bac++cd+^*

10

Conclusiones
Para concluir tenemos que las pilas las listas enlazadas, todos sus mtodos y las
diferentes expresiones son una de las herramientas utilizadas para programar y
procesar de una manera automatizada todos los sistemas que usamos da tras da
en relacin a tcnicas o mtodos para agilizar operaciones. Estas herramientas
son uno de los instrumentos ms usados en la programacin para estructurar y
organizar informacin.

Bibliografa
http://www.monografias.com/trabajos44/pilas-listas-expresiones/pilas-listasexpresiones2.shtml#ixzz3nXiPGmfk
http://www.lawebdelprogramador.com/foros/Dev-C/724318-Transformar-notacion-i

11

Actividad 2: Reporte de la aplicacin del manejo de tipos en las expresiones


y el uso de operadores.
Introduccin
Expresiones
Una expresin es una combinacin de operadores y operando. Los datos u
operando pueden ser constantes, variables y llamadas a funciones. Adems,
dentro de una expresin pueden encontrarse subexpresiones encerradas entre
parntesis. Por ejemplo, la siguiente expresin matemtica:
( 3) cos( ) 2
x+b
Cuando se ejecuta una sentencia de cdigo que contiene una expresin, sta se
evala. Al evaluarse la expresin toma un valor que depende del valor asignado
previamente a las variables, las constantes y los operadores y funciones utilizadas
y la secuencia de la ejecucin de las operaciones correspondientes. Este valor
resultante de la evaluacin de la expresin ser de un determinado tipo de dato.
Por ejemplo, de un tipo numrico entero (integer, shortint), de un tipo real o de
un tipo lgico o booleano.
Operadores
En el cdigo fuente de un programa un operador es un carcter o una secuencia
de caracteres. Por ejemplo: +, *, div o shr. Los operadores definen las operaciones
que van a realizarse con los datos u operando. En TurboPascal existen distintos
tipos de operadores. Por un lado, pueden clasificarse, dependiendo del nmero de
operando, en unarios o unitarios (un operando) y binarios (dos operandos). Por
otro lado, pueden clasificarse, dependiendo del tipo de operando y de su
resultado, en operadores aritmticos, de cadenas de caracteres, de relacin,
lgicos o booleanos, de bit y de conjuntos. Algunos operadores estn
sobrecargados, lo que significa que la operacin que representan depende del
nmero o tipos de operando sobre los que acta. De esta forma, por ejemplo el
operador + puede hacer referencia a la suma de valores numricos, a la
concatenacin de caracteres o a la unin de conjuntos dependiendo del tipo de
sus operando.

Desarrollo
12

Operador de asignacin
El operador de asignacin se representa por la secuencia de caracteres:=. Permite
asignar a una variable el valor de una expresin. Por ejemplo:
var x,y,z: real;
Begin
x:=12.5;
y:=-5.7;
z:=2*x+3*y;
Operadores aritmticos
Los operadores aritmticos operan sobre valores de tipo entero o real. Los
operadores aritmticos se resumen en la Tabla 12. En el caso del operador
unitario de cambio de signo, el resultado es del mismo tipo que el del operando; en
el caso de los tres primeros operadores binarios (suma, resta y producto) si ambos
operandos son enteros el resultado es entero, si alguno es real el resultado es
real. Con el fin de mantener la coherencia durante la operacin, para un operador
binario, operandos con distinto tipo se convierten a un mismo tipo comn antes de
la operacin. El tipo comn es el tipo de dato predefinido de TurboPascal con el
menor intervalo de representacin que incluye los valores de ambos operandos.
Un concepto equivalente sera el de mnimo comn mltiplo.
Por ejemplo, el tipo comn de dos tipos byte e integer es el tipo integer. El tipo
comn de dos tipos integer y word es un longint. El tipo comn de dos tipos integer
y real es un real. La operacin se lleva a cabo dentro del intervalo de
representacin y con la precisin de este tipo comn y el resultado es tambin de
este tipo comn.

Operadores de relacin
Los operadores de relacin son operadores binarios en los que los operandos son
ordinales, reales o de cadena. Los dos primeros operadores sirven tambin para
13

operandos de tipo record y punteros. Todos ellos dan lugar a resultados de tipo
booleano. Losoperadores de relacin se resumen en la Tabla 13.

No hay que confundir el operador lgico igualdad =, con el operador de


asignacin:=, que asigna valores a variables o funciones. La expresin a=b
compara los valores almacenados en la variables a y b y devuelve true o false
segn el resultado, mientras que la sentencia a:=b; asigna a la variable a el valor
almacenado en la variable b.
Operadores lgicos o booleanos
Los operadores lgicos o booleanos realizan operaciones con operandos de tipo
lgico o booleano y tiene como resultado un dato tambin del mismo tipo. Los
operadores booleanos definidos en TurboPascal se resumen en la Tabla:

14

Niveles de prioridad de los operadores


Una expresin puede contener distintos tipo de operadores mientras cada
operador trabaje con operandos del tipo adecuado. La pregunta que surge a
continuacin es: qu operacin de las que se pueda encontrar en una expresin
se realiza antes que las dems? Los niveles de prioridad entre operadores en una
misma expresin se resumen en la Tabla 16.
Las secuencias de operadores de igual prioridad normalmente se evalan de
izquierdaa derecha dentro de una expresin, aunque, en algunos casos, el
compilador puede reordenar los operandos durante el proceso de compilacin
para generar cdigo objeto ptimo para su posterior ejecucin. En muchas
ocasiones se recomienda el uso de los parntesis para hacer que las expresiones
sean ms claras y fciles de entender. En la Tabla 17 se muestran algunos
ejemplos de expresiones y de los correspondientes resultados al ser evaluadas.

Las reglas de evaluacin de expresiones pueden resumirse en las siguientes:


a) Un operando situado entre dos operadores de diferente prioridad se liga al
operador de mayor prioridad.
b) Un operando situado entre dos operadores de igual prioridad se liga al operador
de la izquierda.
c) Las expresiones entre parntesis se evalan primeramente para ser tratadas
como operandos simples.

15

Conclusin
En este tema se presentan los siguientes elementos de la programacin: las
expresiones y los operadores. Se define el concepto de expresin y se contina
con el estudio de los distintos tipos de operadores: aritmtico, de relacin,
bolanos y de bit. En el apartado final se analizan las reglas de prioridad de los
operadores que se siguen en la evaluacin de expresiones de todo tipo. Una
expresin es una combinacin de operadores y operandos. Los datos u operandos
pueden ser constantes, variables y llamadas a funciones. Adems, dentro de una
expresin pueden encontrarse subexpresiones encerradas entre parntesis.

Bibliografas
Garca-Beltrn, A., Martnez, R. y Jan, J.A. Mtodos Informticos en TurboPascal,
Ed.Bellisco, 2 edicin, Madrid, 2002
Joyanes, L. Fundamentos de programacin, Algoritmos y Estructuras de Datos,
McGrawHill, Segunda edicin, 1996
Duntemann, J. La Biblia de TurboPascal, Anaya Multimedia, Madrid, 1991
16

Actividad 3: Cdigo intermedio de la estructura de un lenguaje de


programacin de alto nivel.
Cdigo intermedio
Existen cdigos intermedios de diversos tipos que varan en cuanto a su sencillez,
lo prximos que estn a las maquinas reales y lo fcil que es trabajar con ellos.
Nosotros nos centraremos en un tipo de cdigo que se parece bastante al
lenguaje ensamblador. Existen otros tipos de cdigo intermedio que representan
los programas como rboles o grafos. Tambin existen representaciones mixtas
que combinan grafos o rboles y representaciones lineales.

El formato que usaremos para las operaciones binarias es similar al del


ensamblador MIPS:
Op dst, op1, op2, donde:

* op es un operador.
*dst es el registro destino de la operacin.
*op1 y op2 son los operandos. Si op termina en i, el segundo operando es un valor
inmediato
(Entero o real).

En caso de que el operador sea unario, la forma de la instruccin es op dst, op1.


Para acceder
A memoria utilizaremos instrucciones de acceso a memoria usando un registro
base y un desplazamiento. Para leer de memoria utilizamos lw dst, desp (base)
donde dst es el registro destino, desp es un entero que representa el
desplazamiento y base es el registro base. Si queremos acceder a una direccin
absoluta, utilizamos $zero como registro base, aprovechando que este registro
siempre contiene el valor 0. Para escribir en memoria utilizamos sw fnt, desp
(base) donde fnt es el registro fuente y el resto tiene el mismo significado que
antes.

17

Por ejemplo, la sentencia a:= b*(-c), donde a es una variable local en la direccin 1
respecto al registro $fp y b y c son variables globales en las direcciones 1000 y
1001, se puede traducir como:

Lw $r1, 1000($zero)
lw $r2, 1001($zero)
multi $r3, $r2, -1
mult $r4, $r1, $r3
sw $r4, 1($fp)

Uno de los objetivos que suele perseguirse es reducir al mnimo el nmero de


registros utilizados.
En nuestro caso, podemos emplear dos:

lw $r1, 1000($zero)
lw $r2, 1001($zero)
multi $r2, $r2, -1
mult $r1, $r1, $r2
sw $r1, 1($fp)

Si las variables estuvieran en los registros $r1, $r2 y $r3, podramos incluso no
utilizar ningn registro auxiliar:

multi $r1, $r3, -1


mult $r1, $r2, $r1

18

Tambin tendremos instrucciones para controlar el flujo de ejecucin, para


gestionar entrada salida, etc. A lo largo del tema iremos viendo esas instrucciones
segn las vayamos necesitando.

Generacin de cdigo para expresiones.


Empezaremos por generar cdigo para las expresiones. Asumiremos que para
gestionar el cdigo disponemos de una funcin auxiliar, emite. Esta funcin recibe
una cadena que representa una lnea de cdigo intermedio y hace lo necesario
para que termine en el programa final; por ejemplo, puede escribirla en un fichero,
almacenarla en una lista para pasarla a otro modulo, etc.

Expresiones aritmticas
Comenzamos el estudio por las expresiones aritmticas. Lo que tendremos que
hacer es crear por cada tipo de nodo un mtodo, genera Cdigo, que genere el
cdigo para calcular la expresin y lo emita. Ese cdigo dejar a el resultado en un
registro, cuyo nombre devolver a genera Cdigo como resultado.

Para reservar estos registros temporales, utilizaremos una funcin,


reservaRegistro. En principio bastara con que esta funcin devuelva un registro
distinto cada vez que se la llame. Cada nodo generara el cdigo de la siguiente
manera:

Por cada uno de sus operandos, llamara al mtodo correspondiente para


que se evale la sub expresin.

Si es necesario, reservara un registro para guardar su resultado.

Emitir las instrucciones necesarias para realizar el clculo a partir de los


operandos.
Con este esquema, la generacin del cdigo para una suma ser:
Objeto Nodo Suma:
...

19

Mtodo generaCdigo ()
izda:= i.generaCdigo ();
dcha:= d.generaCdigo ();
r =reserva Registro ();
emite (add r, izda, dcha);
devuelve r;
fin genera Cdigo
...
fin Nodo Suma

En el caso de los operadores unarios, bastara con reservar un registro y hacer la


correspondiente operacin.
Ejercicio 1
[Escribe el mtodo de generacin de cdigo para el operador unario de cambio de
signo.]

La generacin de cdigo para constantes se limita a almacenar el valor en un


registro:

Objeto Nodo Constante:


...
Mtodo generaCdigo ()
r :=reserva Registro ();
emite (addi r, $zero, valor);
devuelve r;

20

fin generaCdigo
...
fin Nodo Constante

Para las variables, tendremos que distinguir segn si son locales o globales y
acceder a la direccin correspondiente. Las variables globales tendrn una
direccin absoluta a la que accederemos utilizando el registro $zero como base y
las variables locales y parmetros de las funciones tendrn una direccin relativa
al registro $fp (frame pointer):

Objeto NodoAccesoVariable:
...
Mtodo generaCdigo()
r :=reserva Registro();
if eslocal entonces
emite(lw r, dir($fp) );
si no
emite(lw r, dir($zero) );
fin si
devuelve r;
fin generaCdigo
...
fin NodoVariableGlobal

21

Observa que asumimos que las variables estn en memoria y no


permanentemente en registros. Esto no es ptimo, pero nos permite presentar un
mtodo de generacin razonablemente sencillo.

Por ejemplo, vamos a traducir la expresin (a+2)*(b+c). Si suponemos que las


variables estn en las direcciones 1000, 1001 y 1002, respectivamente, el cdigo
que se generara es:

lw $r1, 1000($zero)
addi $r2, $zero, 2
add $r3, $r1, $r2
lw $r4, 1001($zero)
lw $r5, 1002($zero)
add $r6, $r4, $r5
mult $r7, $r3, $r6

Es bueno intentar reducir el nmero de registros utilizados. Por ejemplo, al llamar


a una funcin, hay que guardar en la trama de activacin todos los registros
activos en ese punto. Por eso, ser bueno intentar reutilizar los registros y tener
el mnimo nmero de ellos ocupados. Si vamos a tener una fase de optimizacin,
no hace falta ocuparse ahora de esta cuestin. Si no tenemos un optimizador,
podemos utilizar una estrategia sencilla que reduce bastante el nmero de
registros empleados. La idea es tener tambin una funcin liberaRegistro que
marca un registro como disponible para una nueva llamada de reservaRegistro.
Para implementarlas, podemos tener una lista de registros activos y otra de
registros libres. La llamada a reservaRegistro devuelve un elemento de la lista de
registros libres, si no est vaca, o crea un nuevo registro si lo est. La llamada a
liberaRegistro mueve el registro a la lista de registros libres. La lista de registros
activos se emplea, por ejemplo, para saber que registros hay que guardar en las
llamadas a funcin.

22

Siguiendo esta idea, el no do de la suma sera:

Objeto NodoSuma:
...
Mtodo generaCdigo()
izda:= i.generaCdigo();
dcha:= d.generaCdigo();
emite(add r, izda, dcha);
liberaRegistro(dcha);
devuelve izda;
fin generaCdigo
...
fin NodoSuma

Para (a+2)*(b+c) se generara:

lw $r1, 1000($zero)
addi $r2, $zero, 2
add $r1, $r1, $r2
lw $r2, 1001($zero)
lw $r3, 1002($zero)
add $r2, $r2, $r3
mult $r1, $r1, $r2

En el caso de los unarios, directamente reutilizaremos el registro correspondiente


al operando.
23

Actividad 4: Lenguaje prototipo aplicando las acciones construidas a la


gramtica.
La sintaxis de un lenguaje de programacin describe la forma correcta en la cual
las sentencias, expresiones y unidades de programa se deben escribir, mientras
que la semntica denota el significado de esas sentencias, expresiones y
unidades de programa. Por ejemplo la sintaxis de una sentencia Pascal if then es:

if <condicin> then <sentencia>

La semntica de esta sentencia es que si el valor actual de la condicin es


verdadero, se ejecutar <sentencia>.
Describir sintaxis es ms fcil que describir semntica, ya que existen notaciones
aceptadas universalmente para la descripcin de sintaxis y no as de semnticas.
En la definicin de un lenguaje de programacin la sintaxis usualmente se expresa
en BNF (Backus- Naur Form) y la semntica est expresada en lenguaje natural
(espaol, ingls, etc.).
BNF es un ejemplo de un metalenguaje, es decir, un lenguaje usado para definir
otros lenguajes. Algol 60 fue el primer lenguaje que utiliz BNF para su descripcin
sintctica.
Una gramtica consiste de un conjunto de no-terminales, terminales y una serie de
reglas de produccin. Un no-terminal est definido en una regla de produccin,
mientras que un terminal es un smbolo del lenguaje que se est definiendo. En
una regla de produccin el no-terminal (que aparece en la parte izquierda) est
definido en trminos de una secuencia de no-terminales y terminales (que se
encuentran en la parte derecha)

Ejemplo:

24

<dgito>::= 0|1|2|3|4|5|6|7|8|9
<letra>::= a|b|c|x|y|z
<identificador>::=<letra>|<identificador><dgito>|<identificador><letra>

En BNF, un no-terminal se escribe entre <>, el smbolo ::= significa se define


como y el smbolo | significa o.
Estas reglas definen <dgitos> como uno de los smbolos 0, 1 al 9; <letra> como
una letra minscula e <identificador> se define como una nica letra, un
identificador seguido de una letra o un identificador seguido de un dgito.
As, el identificador ab1 puede ser derivado de <identificador>como sigue:
<identificador>
<identificador><dgito>
<identificador><letra>><dgito>
<letra><letra><dgito> a <letra><dgito> a
a

<dgito>

En cada etapa, el no-terminal de ms a la izquierda es reemplazado por la parte


derecha de una de sus reglas de produccin, la secuencia de terminales y noterminales producidos en cada etapa en una derivacin se conoce como formas
sentenciales. La forma sentencia final (que ya no contiene smbolos no-terminales)
se conoce como una sentencia.
La estructura de una derivacin se muestra mejor en un rbol de derivacin. El
rbol de derivacin que muestra cmo ab1 de <identificador> es:

<identificador>
|
<identificador> <dgito>
|
|
25

<identificador><letra>
|
|
<letra>
b
|a

Un lenguaje de programacin completo se define comenzando con un smbolo noterminal tal como <programa>, conocido como start symbol (smbolo inicial) y
desde el cual todos los posibles programas pueden ser derivados. En la prctica,
los rboles de derivacin se crean de dos formas posibles. En un esquema topdown, la sentencia requerida se deriva del smbolo inicial tal cual como hicimos en
el ejemplo (ab1). En un esquema bottom-up, el punto de partida es la sentencia
requerida, la cual es reducida al smbolo inicial reemplazando las partes derechas
por sus correspondientes partes izquierdas de las reglas de produccin. Ambos
esquemas se utilizan en la fase de anlisis sintctico de muchos compiladores.
Una gramtica que define un lenguaje de programacin tiene un nmero finito de
reglas de produccin, pero como las reglas de produccin contienen recursin, es
posible generar infinitos programas posibles.
Ejemplo:

<ident>::=<ident><dgito>

Cuando se incluye recursin en las reglas de produccin hay que tener cuidado.
Hay que asegurarse que la recursin termine. Una regla de produccin tal como la
anterior se dice que es recursiva a izquierda. Existen definiciones similares pero
recursivas a derecha.
Ejemplo: Gramtica para una sentencia de asignacin

<asig>::= <id>:=<exp>
<id>::= A| B| C |D (tambin podra ser la definicin de identificador anterior)
<exp>::= <exp> + <exp>
| <exp> * <exp>
| <id>
26

Qu pasa con esta gramtica? Es correcta? Veamos el rbol de derivacin de


la siguiente sentencia.

A:= B + C * D
rbol 1
<asig>
|
<id>
|
A
|
<id>
|
B
|
C

:= <exp>
|
<exp>
+
<exp>
|
<exp> * <exp>
|
|
<id> <id>
|
D

rbol 2

<asig>
|
<id> :=
<exp>
|
|
A
<exp> * <exp>
|
|
<exp> + <exp>
<id>
|
|
|
<id> <id> D
|
|
B
C
En general la ambigedad sintctica de las estructuras de un lenguaje es un
problema, debido a que los compiladores basan la semntica de esas estructuras
en su estructura sintctica. Si una estructura del lenguaje tiene ms de un rbol de

27

derivacin, entonces, el significado de la estructura no podra determinarse


unvocamente.

Cmo desambiguamos la gramtica anterior?


<asig>::= <id> := <exp>
<id>::= A| B| C| D
<exp>::= <exp> + <trmino> | <trmino>
<trmino>::= <trmino> * <factor> | <factor>

En general puede ser una declaracin o un conjunto separados por ;. Y una


declaracin puede ser un identificador o un conjunto separados por ,:

<declaracin>::= var <lista-de-dcls>


<lista-de-dcls>::= <unaDeclaracin> | <unaDeclaracin>; <lista de-dcls>
<unaDeclaracin>::= <lista-de-ident> : <tipo>
<lista-de-ident>::= <ident> |<ident>, <lista-de-ident>
<ident>::= Se defini en la teora!!!
<tipo>::= ..no hacerlo, en este caso para ac

Las anteriores son slo reglas de produccin de la gramtica. La gramtica se


compone adems de reglas de:

Dnde:
G={ N, T, P, S}

28

T = {var, , , ; , : , etc}

N = { <declaracin>, <lista de-dcls>, <unaDeclaracin>, <lista-de-ident>,


<tipo>, <ident>}

P = { <declaracin>::= var <lista-de-dcls>


<lista-de-dcls>::= <unaDeclaracin> | <unaDeclaracin>; <lista-de-dcls>
<unaDeclaracin>::= <lista-de-ident> : <tipo>
<lista-de-ident>::= <ident> |<ident>, <lista-de-ident>
<ident>::= Se defini en la teora!!!
<tipo>::= ..no hacerlo, en este caso para ac

}
S = {<declaracin>}

Prototipo de gramatica

abstract class Comm {


public Object visita(Visitor v);
}

class While extends Comm { public Expr e;


public Comm c;
29

public Object visita(Visitor v) { return v.visitaWhile(this);


}
}

class If extends Comm { public Expr e;


public Comm c1, c2;

public Object visita(Visitor v) { return v.visitaIf (this);


}
}

class Seq extends Comm { public Comm c1, c2;

public Object visita(Visitor v) { return v.visitaSeq(this);


}
}

class Assign extends Comm { public String name;


public Expr e;

public Object visita(Visitor v) { return v.visitaAssign(this);


}
}
class Skip extends Comm { Object visita(Visitor v) {
30

return v.visitaSkip(this);
}
}

En el caso de las expresiones, se realiza el mismo esquema.

abstract class Expr {


public abstract Object visita(Visitor v);
}

class BinOp extends Expr { public Operator op; public Expr e1,e2;

public Object visita(Visitor v) { return v.visitaBinOp(this);


}
}

class Var extends Expr { public String name;

public Object visita(Visitor v) { return v.visitaVar(this);


}
}

class Const extends Expr { public int n;

public Object visita(Visitor v) { return v.visitaConst(this);


31

}
}
Se define una clase abstracta Visitor cuyas subclases representarn posibles
recorridos. La clase incluye mtodos del tipo Object visitaX(X n) para cada tipo de
nodo X del rbol sintctico.

abstract class Visitor { Object visitaWhile(While w); Object visitaIf(If i); Object
visitaSeq(Seq s);
Object visitaAssign(Assign a); Object visitaSkip(Skip s); Object visitaBinOp(BinOp
b); Object visitaVar(Var v); Object visitaConst(Const c);
}
A continuacin se define como un posible recorrido del rbol sintctico y por tanto,
una subclase de Visitor.

class Interp extends Visitor {


// Aqu se pueden definir los elementos del contexto (Tabla, Memoria, etc.) Object
visitaWhile(While w) {
for (;;) {
BValue v = (BValue) w.e.visita(this); if (!v.b) break;
w.c.visita(this);
}
}

Object visitaIf(If i){


BValue v = (BValue) i.e.visita(this); if (!v.b) i.c1.visita(this);
else i.c2.visita(this);
}

32

Object visitaSeq(Seq s){ s.c1.visita(this); s.c2.visita(this);


}

Object visitaAssign(Assign a) { Value v = (Value) a.e.visita(this); update(a.name,v);


}

Object visitaSkip(Skip s) {
}
Object visitaBinOp(BinOp b) {
Value v1 = (Value) b.e1.visita(this); Value v2 = (Value) b.e2.visita(this); return
(b.op.apply(v1,v2));
}
Object visitaVar(Var v){ return lookup(v.name);
}

Object visitaConst(Const c) { return c.n;


}
// Funcin de ejecucin de rdenes
c.visita(this);
}
}

33

Object exec(Comm c) {

Actividad 5: Tres programas tipo, usando la gramtica definida de su


lenguaje de programacin.

Programacin basada en prototipos es un estilo de programacin orientada a


objetos en el cual los objetos no son creados mediante la instanciacin de clases
sino mediante la clonacin de otros objetos o mediante la escritura de cdigo por
parte del programador. De esta forma los objetos ya existentes pueden servir de
prototipos para los que el programador necesite crear.
El original (y el ms cannico) ejemplo de lenguaje prototipado es el lenguaje Self,
desarrollado por David Ungar y Randall Smith.
Sin embargo el paradigma sin clases est comenzando a popularizarse y ya ha
sido implementado en lenguajes de programacin como JavaScript, Cecil,
NewtonScript, IO,MOO, REBOL, Squeak.
Analgicamente.
Un ejemplo de instancia en un lenguaje de programacin visual, sera tomar o
arrastrar un objeto de la barra de herramientas o de la lista de libreras y colocarlo
en el escritorio o escenario de trabajo (estamos creando una instancia de ese
objeto, una copia). Si arrastramos 10 botones al entorno visual de trabajo,
estamos creando una instancia del botn original, si a cada botn le cambiamos el
nombre, tendremos 10 botones que heredan las mismas propiedades y mtodos
del objeto original. Tenemos como resultado que con un solo botn hicimos 10 y
nuestro archivo pesara como si tuviese uno solo.
De esta forma, partiendo de lo que conforma a un objeto original (propiedades y
mtodos) se reutilizan sus funciones creando una instancia del mismo en distintas
partes del programa donde se necesite. Si el objeto original cambia o le es
agregado algn nuevo atributo, las instancias lo heredaran puesto que son una
copia del objeto original.
Comparacin del modelo basado en clases
En lenguajes basados en clases los objetos pueden ser de dos tipos generales,
las clases y las instancias. Las clases definen la disposicin y la funcionalidad
bsicas de los objetos, y las instancias son objetos "utilizables" basados en los
patrones de una clase particular. En este modelo, las clases actan como
34

colecciones de comportamiento (mtodos) y estructuras que son iguales para


todas las instancias, mientras que las instancias llevan los datos de los objetos. La
distincin del papel se basa as sobre todo en una distincin entre la estructura y
el comportamiento en un lado, y el estado en el otro.
Los entusiastas de la programacin basada en prototipos a menudo argumentan
que los lenguajes basados en clases animan un modelo del desarrollo que se
centra primero en la taxonoma y las relaciones entre las clases. En cambio, la
programacin basada en prototipos intenta animar al programador que se centre
en el comportamiento de un cierto sistema de ejemplos y despus de clasificar
estos objetos en objetos arquetipos que se utilizan ms adelante en una manera
similar a las clases. Como tal, muchos sistemas basados en prototipos animan la
alteracin de prototipos durante tiempo de ejecucin, mientras que solamente muy
pocos sistemas orientados a objeto, basados en clase (como el primer sistema
orientado a los objetos dinmicos, Smalltalk) permiten que las clases sean
alteradas durante la ejecucin de un programa.
Mientras que la amplia mayora de sistemas basados en prototipos se refieren a
lenguajes de programacin interpretados y de tipos de datos dinmicos, es
importante precisar que los sistemas de tipos de datos estticos son tcnicamente
factibles. El lenguaje de programacin de Omega que es basado en prototipos es
un ejemplo de tal sistema, aunque segn el Web site de Omega, Omega no es
exclusivamente de tipos de datos estticos, pero su "compilador puede elegir
utilizar el tipo de dato esttico donde es posible esto y puede mejorar la eficacia
del programa.
Gramticas formales
Las gramticas de todos los lenguajes humanos conocidos tienen una cosa en
comn: estn organizadas por frases. Digamos a grosso modo que una frase es
una unidad de lenguaje. A su vez una frase para que sea sintcticamente correcta
debe estar formada por sujeto y predicado; el predicado debe incluir un verbo; si el
verbo es transitivo debe llevar un objeto directo, etc.. Tratamos de expresarlo
con smbolos:
<frase>::= <sujeto><predicado><sujeto>::= juan / antonio / mara / pepa
<predicado>::= <verbo transitivo><objeto directo>
<predicado>::= <verbo intransitivo>
<verbo transitivo>::= ama / lava / peina / adora
35

<objeto directo>::= paula / antonio / sultn


<verbo intransitivo>::= corre / salta / camina
Si partimos de <frase> y seguimos estas reglas podemos obtener
<frase> <sujeto><predicado> mara<predicado>
mara<verbo transitivo><objeto directo>
mara ama <objeto directo> mara ama a sultn.
Hemos construido una frase utilizando slo las reglas anteriores. Decimos que
mara ama a sultn es una frase de la gramtica. De modo anlogo
<frase> <sujeto><predicado> juan<predicado>
juan<verbo intransitivo> juan camina
As juan camina es otra frase de nuestra gramtica.
Queremos hacer una definicin formal de gramtica, para ello vamos a tratar de
abstraer lo principal de lo que en el lenguaje normal llamamos gramtica.
Observamos que hay dos tipos de componentes: los que escribimos entre
corchetes <>y las que no. Llamaremos a esos dos tipos de objetos no terminales y
terminales, respectivamente. Obsrvese que una verdadera frase est escrita slo
con terminales y los no terminales se usan slo en pasos intermedios, para
construir con sintaxis correcta.
Lo fundamental de la gramtica son las reglas que nos van a permitir formar
frases correctas. Slo las frases que formemos de acuerdo a esas reglas sern
frases correctas del lenguaje de nuestra gramtica.
Las gramticas son mecanismos generadores de lenguajes, es decir, nos dicen
cmo podemos obtener o construir palabras de un determinado lenguaje.
Una gramtica es una cudrupla G = (VN, VT, S, P) donde:
VT : Es el alfabeto de smbolos terminales.
V N: Es el alfabeto de smbolos no terminales o variables, de forma que debe ser
VN VT = y denotamos con V al alfabeto total de la gramtica, esto es,
V = VN VT.
S: Es el smbolo inicial y se cumple que S VN.
P: Es un conjunto nito de reglas de produccin.
A veces se utiliza una notacin especial para describir gramticas llamada
notacin BNF (Backus-Naus-Form ). En la notacin BNF los smbolos no
terminales o variables son encerrados entre ngulos y utilizaremos el smbolo ::=
para las producciones, en lugar de . Por ejemplo, la produccin S aSa se
36

representa en BNF comoS ::= aS a. Tenemos tambin la notacin BNFextendida que incluye adems los smbolos [] y {} para indicar elementos
opcionales y repeticiones, respectivamente.
Tenemos un lenguaje de programacin cuyas dos primeras reglas de produccin
para denir su sintaxis son:

Esto viene a decir que un programa se compone de una cabecera opcional,


seguido de la palabra clave begin, a continuacin una lista de sentencias (debe
haber al menos una sentencia) y naliza con la palabra clave end. Podemos
transformar las producciones anteriores para especicarlas, segn la notacin que
nosotros hemos introducido (estndar)
Programa 1:
Programa que acepta expresiones, para realizar este programa se utiliza la
siguiente gramtica.
E > E+T | T
T > T*R | R
R > R-W | W
W > W/F | F
E > (E) | 09
Cdigo:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>

using namespace std;

37

char entrada[50];
char *ca=entrada; /*caracter actual*/

//declaracion de funcionees
void E();
void Eprima();
void T();
void Tprima();
void R();
void Rprima();
void W();
void Wprima();
void F();
void Aceptado();
int main(){
cout<<"ingrese la expresion: ";
gets(entrada);
E();
cout<<"\nLa expresion si es valida\n"<<endl;
system("pause");
}
void E()// *E > TE
{
T();
38

Eprima();
}

void Eprima() // E > +TE|vaco


{
if(*ca=='+')
{
Aceptado();
ca++;
T();
Eprima();
}
//vaco
}
void T() // T > RT
{
R();
Tprima();
}
void Tprima() // T > *RT|vaco
{
if(*ca=='*')
{
Aceptado();
39

ca++;
R();

Tprima();
}
//vaco
}
void R() // R > WR
{
W();
Rprima();
}
void Rprima() // R > -WR|vaco
{
if(*ca=='-')
{
Aceptado();
ca++;
W();
Rprima();
}
//vaco
}
void W() // W > FW
40

{
F();
Wprima();
}

void Wprima() // W > /FW|vaco


{
if(*ca=='/')
{
Aceptado();
ca++;
F();
Wprima();
}
//vaco
}
void F() // F > (E)|09
{
if(isdigit(*ca))
{
Aceptado();
ca++;
}
else if (*ca=='(')
{
41

Aceptado();
ca++;
E();
if (*ca==')')
{
Aceptado();
ca++;
}
else
{
cout<<"se espera parentesis derecho u operador :"<<endl;
system("pause");
exit(0);
}
}
else
{
cout<<"se espera digito o parntesis izquierdo:"<<endl;
system("pause");
exit(0);
}
}
void Aceptado() //esta funcin avisa que el caracter actual es aceptado
{
cout<<" caracter ' "<<*ca<<" ' aceptado"<<endl;
42

Programa 2:
#include<iostream>
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string>
#define TAM_BUFFER 100
using namespace std;
classLexico
{
char *nombreFichero;
FILE* entrada;
43

int n1;
int traza;
char buffer[TAM_BUFFER];
int pBuffer;
public:
Lexico(char *unNombreFichero, int una_traza=0);
~Lexico(void);
char siguienteToken(void);
void devuelveToken(char toke);
int lineaActual(void){return n1;};
int existeTraza(void){if(traza)return 1; else return 0;}
};

Lexico::Lexico(char *unNombreFichero, int una_traza)


{
entrada=fopen(unNombreFichero, "rt");
if((entrada==NULL))
{
cout<<"No se puede abrir el archivo"<<endl;
system("pause");
exit(-2);
}
if(una_traza) traza=1;
else traza = 0;
n1=1;
pBuffer=0;
}
44

Lexico::~Lexico()
{
fclose(entrada);
}

char Lexico::siguienteToken(void)
{
char car;
while((car=((pBuffer>0) ? buffer[-pBuffer]:getc(entrada)))!=EOF)
{
if(car==' ') continue;
if(car=='\n'){++n1; continue;}
break;
}

if(traza) cout<<"ANALIZADOR LEXICO: Lee el token : "<<car<<endl;


switch(car)
{
case'M':
case'R':
case'W':
case'=':
case'(':
case')':
case';':
case'}':
45

case'{':
case'.':
case'+':
case'*':
case'-':
case'/':
case'%':
return(car);
}
if(islower(car))return(car);
else if(isdigit(car)) return(car);
else
{
cout<<"Error Lexico: Token Desconocido"<<endl; system("pause");
exit(-4);
}
return(car);
}

void Lexico::devuelveToken(char token)


{
if(pBuffer>TAM_BUFFER)
{

cout<<"ERROR: Desbordamiento del buffer del analizador lexico"<<endl;


system("pause");

46

exit(-5);
}
else { buffer[pBuffer++]=token;
if(existeTraza())
cout<<"ANALIZADOR LEXICO: Recibe en buffer el token"<<token<<endl;
system("pause");
}
}

int main()
{
int traza;
char token;
Lexicoobj("ejemplo_minidev.txt",1);
if(obj.existeTraza()) cout<<"INICIO DE ANALISIS"<<endl;
while((token=obj.siguienteToken() )!='}') cout<<token<<endl;
system("pause");
return 0;
}

47

Programa 3:
void inapre(){
system("cls");
int cy=0,rt=0,p=0,uui=0;

for(int g=0;g<=n;g++){
if(Frase[g] == ')' || Frase[g] == '+' || Frase[g] == '-' ||Frase[g] == '/' ||
Frase[g] == '*'||Frase[g] == '('||Frase[g] == '^'){{
//cout<<endl<<prioridad(Frase[g])<<" "<<prioridad(pi[cy1])<<endl<<endl;
//cout<<Frase[g]<<" "<<pi[cy-1]<<endl;
if( (Frase[g] != pi[cy-1]) && ( prioridad(Frase[g]) == prioridad(pi[cy-1]) )
&& cy != 0 && Frase[g] != '(' && Frase[g] != ')'&& pi[cy-1] != '(' && pi[cy-1] !=
')'){
pref[rt] = pi[cy-1];
cout<<pref[rt]<<" prio"<<endl;
cout<<pi<<" SP "<<endl;
rt++;
pi[cy-1] = Frase[g];
cy--;
}
if(Frase[g] == ')' ){
for(int jj=p+1;jj<cy;jj++){
pref[rt] = pi[jj];
cout<<pref[rt]<<" SS "<<endl;
rt++;
}
for(int hrh = p;hrh<=cy;hrh++){
pi[hrh] = ' ';
}
cy = p;
}
if(Frase[g] == '('){
p = cy;
}
if(Frase[g] != ')'){
pi[cy] = Frase[g];
cout<<pi<<" S "<<endl;
cy++;
}
}
48

}else if(Frase[g] == '9' ||Frase[g] == '8' ||Frase[g] == '1' ||Frase[g] ==


'2' ||Frase[g] == '3' ||Frase[g] == '4' ||Frase[g] == '6' || Frase[g] == '5' ||
Frase[g] == '7'){
pref[rt] = Frase[g];
cout<<pref[rt]<<" N "<<endl;
rt++;
}else if(g==n){
int t=cy-1;
if(pi[0] == ')'){t=1;}
for(t;t>=0;t--){
pref[rt] = pi[t];
cout<<pref[rt]<<" F"<<endl;
rt++;
}
}
cout<<endl<<pref<<endl<<endl;
}// TERMINO DE FOR
cout<<pref<<endl;
/* strcpy(Volt,pref);
cout<<Volt<<"frase1"<<endl;
uui = n-1;
for(int xx=0;xx<n;xx++,uui--){
cout<<xx<<" "<<uui<<endl;
pref[xx] = Volt[uui];
cout<<endl<<Volt[xx]<<" "<<Frase[uui];
}
cout<<endl<<pref<<"frase2"<<endl;
cout<<Volt<<"volt"<<endl;
cout<<pref<<endl;
*/
system("pause");
}//TERMINO DE INAPRE
Conversin de infijo a postfijo y de infijo a prefijo:

49

Introduccin de sentencia.

Infijo a postfijo:
50

Infijo a prefijo:

Actividad 6: Reporte del avance por equipo del proyecto final consistente en
desarrollar software de base: traductor, intrprete o compilador.
51

void CodInterIf(){//Codigo intermedio


system("cls");
char fu[100];
int guu=0;
int qww=0;
int cyu=0;
char ins[100];
for(int jn=0;jn<=n;jn++){
if(Frase[jn] == '(' && Frase[jn+1] == ')'){
cout<<"Debe ingresar una condicion"<<endl;
}else{//FIN IF 1
if(Frase[jn] == 'I' && Frase[jn+1] == 'f' && Frase[jn+2] == '(')
{//IF 2
for(int gu = (jn+3) ; Frase[gu] != ')' ; gu++,guu++){
fu[guu] = Frase[gu];
}
cyu++;
} //FIN IF 2
}//FIN ELSE
if(Frase[jn] == ')' ){//FIN IF3
for(int qw = (jn+2) ; Frase[qw] != '}' ;qw++,qww++){//FOR
ins[qww] = Frase[qw];
}//FIN FOR
}//FIN IF 3
}//FIN FOR
cout<<Frase<<endl;
if(cyu>0){
for(int mm=0;mm<guu;mm++){
cout<<fu[mm];
}
cout<<endl;
cout<<"Salta Si falso Etiqueta1"<<endl;
for(int mm=0;mm<qww;mm++){
cout<<ins[mm];
}
cout<<endl;
cout<<"Etiqueta1:"<<endl;
cout<<"END"<<endl;
52

}
system("pause");
} //Fin codigo intermedio
void CodInterFor(){//Codigo intermedio For
system("cls");
int cyf=0;
int pc=0;
int qw2=0,qw1=0;
char pcl[10];
char ins1[10];
for(int jn=0;jn<=n;jn++){
if(Frase[jn] == '(' && Frase[jn+1] == ')'){
cout<<"Debe ingresar una condicion"<<endl;
}else{//FIN IF 1
if(Frase[jn] == 'F' && Frase[jn+1] == 'o' && Frase[jn+2] == 'r'
&& Frase[jn+3] == '('){//IF 2
cyf++;
}
} //FIN IF 2
if(Frase[jn] == ';'){
pc++;
}
if(pc == 1 && Frase[jn] == ';'){
for(int qw = jn+1; Frase[qw] != ';' ;qw++,qw2++){
pcl[qw2] = Frase[qw];
}
}
if(Frase[jn] == ')' ){//FIN IF3
for(int qw = (jn+2) ; Frase[qw] != '}' ;qw++,qw1++){//FOR
ins1[qw1] = Frase[qw];
}//FIN FOR
}//FIN IF 3
}//FIN FOR
cout<<Frase<<endl;
if(cyf > 0 && pc == 2){
cout<<"Etiqueta1:"<<endl;
53

for(int mm=0;mm<qw2;mm++){
cout<<pcl[mm];
}
cout<<endl;
cout<<"Salta Si falso Etiqueta2"<<endl;
for(int mm=0;mm<qw1;mm++){
cout<<ins1[mm];
}
cout<<endl;
cout<<"Salta Etiqueta1"<<endl;
cout<<"Etiqueta2:"<<endl;
cout<<"END"<<endl;
}
system("pause");
}//Fin codigo intermedio for

Ventajas: dentro de las ventajas de la generacin de cdigo intermedio se


encuentran que: permite abstraer la mquina, separar operaciones de alto nivel de
su implementacin a bajo nivel, permite la reutilizacin de los front-ends y backends; y permite optimizaciones generales.

Desventajas: implica una pasada ms para el compilador (no se puede utilizar el


modelo de una pasada), dificulta llevar a cabo optimizaciones especficas de la
arquitectura destino; y suele ser ortogonal a la mquina destino, la traduccin a
una arquitectura especfica ser ms larga e ineficiente.

Tipos de cdigo intermedio.

AST (AbstractSyntaxTrees): forma condensada de rboles de anlisis, con slo


nodos semnticos y sin nodos para smbolos terminales (se supone que el
programa es sintcticamente correcto).
54

DAG (DirectedAcyclicGraphs): rboles sintcticos concisos.

TAC (Three-AddressCode): secuencia de instrucciones de la forma: operando,


operador, operando, requieren varias instrucciones y permite la reorganizacin de
cdigo, manejo de ensamblador, utiliza direcciones de memoria y nemotcnicos,
pueden ser instrucciones de 2, 3 o 4 por cada operacin.
Se genera una condicin donde este nos indica los identificadores, palabras
reservadas y operadores que este analiza este es posible, una vez que realiza la
identificacin de tokens este procede a generar lo que es el cdigo intermedio,
este lo hace posible tomando en cuenta una funcin donde desglosa su rbol
sintctico.

55

56

Como se observa en la siguiente imagen adems de generar una operacin y mostrarnos los tokens de dicha operacin
este nos genera el cdigo intermedio y a su vez nos muestra el ejemplo de nuestra operacin en lo que seria el lenguaje
ensamblador, para ello necesitamos lo que es la generacin de cdigo intermedio y anlisis lxico y sintctico, para poder
llevar a cabo la Graficacin de nuestro rbol sintctico.

57

Anexo

Para llevar a cabo la funcin del analizador tomamos en cuenta los que son los
caracteres del cdigo asccii esto ms que nada es para tener un control de los
tokens y as mismo poder identificarlos ms fcilmente cuando se realice su
compilacin o ejecucin. El siguiente cdigo realiza el trabajo de la imagen
anterior, identifica cada token y este los va almacenando de manera que los
compare con nuestro alfabeto.
Public Sub analizar()
token = ""
Dim estadios As Integer = 0
Dim numtoken As Integer
Dim arr() As String = RichTextBox1.Text.Split(ChrW(10))
Dim nn, mm As Integer
For nn = 0 To arr.Length - 1
For mm = 0 To Len(arr(nn)) - 1

Dim c, d As String
c = Asc(arr(nn).Chars(mm))
If (estadios = 0) Then
estadios = estado(c)
End If
Try
d = Asc(arr(nn).Chars(mm + 1))
Catch
d = -4
End Try
sig = d

Select Case estadios


Case 1
token = token + arr(nn).Chars(mm)
If (sig > 64 And sig < 92) Or (sig > 96 And sig < 123) Or
(sig < 58 And sig > 47) Then
estadios = 1
Else
58

estadios = 0
numtoken = 1
End If
Case 2
token = token + arr(nn).Chars(mm)
If (sig < 58 And sig > 47) Then
estadios = 2
ElseIf (sig = 46) Then
estadios = 3
Else
estadios = 0
numtoken = 2
End If
Case 3
token = token + arr(nn).Chars(mm)
If (sig < 58 And sig > 47) Then
estadios = 4
Else
estadios = -1
End If
Case 4
token = token + arr(nn).Chars(mm)
If (sig < 58 And sig > 47) Then
estadios = 4
Else
estadios = 0
numtoken = 3
End If
Case 100
estadios = -2
Case -1
token = token + arr(nn).Chars(mm)
numtoken = 10
estadios = 0
Case 300
token = token + arr(nn).Chars(mm)
numtoken = 20
estadios = 0
Case 400
token = token + arr(nn).Chars(mm)
numtoken = 40
estadios = 0
Case 500
59

token = token +
numtoken = 50
estadios = 0
Case 501
token = token +
numtoken = 60
estadios = 0
Case 502
token = token +
numtoken = 70
estadios = 0
Case 503
token = token +
numtoken = 80
estadios = 0
Case 504
token = token +
numtoken = 90
estadios = 0

arr(nn).Chars(mm)

arr(nn).Chars(mm)

arr(nn).Chars(mm)

arr(nn).Chars(mm)

arr(nn).Chars(mm)

End Select

If estadios = 0 Then
numerotoken.Add(numtoken)
lexema.Add(token)
token = ""

ElseIf estadios = -2 Then


estadios = 0
ElseIf estadios = -1 Then
numerotoken.Add(10)
lexema.Add(token)
token = ""
ElseIf (sig = -3) Then
If estadios <> 0 Then
numerotoken.Add(-1)
lexema.Add(token)
End If
End If
60

Next
Next
For ii = 0 To numerotoken.Count - 1
If (numerotoken(ii) = 1) Then
If lexema(ii) = palabras_reservadas(1) Or lexema(ii) =
palabras_reservadas(2) Or lexema(ii) = palabras_reservadas(3) _
Or lexema(ii) = palabras_reservadas(4) Or lexema(ii) =
palabras_reservadas(5) Or lexema(ii) = palabras_reservadas(6) _
Or lexema(ii) = palabras_reservadas(7) Or lexema(ii) =
palabras_reservadas(8) Or lexema(ii) = palabras_reservadas(9) _
Or lexema(ii) = palabras_reservadas(10) Or lexema(ii) =
palabras_reservadas(11) Or lexema(ii) = palabras_reservadas(12) _
Or lexema(ii) = palabras_reservadas(13) Or lexema(ii) =
palabras_reservadas(14) Or lexema(ii) = palabras_reservadas(15) _
Or lexema(ii) = palabras_reservadas(16) Or lexema(ii) =
palabras_reservadas(17) Or lexema(ii) = palabras_reservadas(18) _
Or lexema(ii) = palabras_reservadas(19) Or lexema(ii) =
palabras_reservadas(20) Or lexema(ii) = palabras_reservadas(21) _
Or lexema(ii) = palabras_reservadas(22) Or lexema(ii) =
palabras_reservadas(23) Or lexema(ii) = palabras_reservadas(24) _
Or lexema(ii) = palabras_reservadas(25) Or lexema(ii) =
palabras_reservadas(26) Or lexema(ii) = palabras_reservadas(27) _
Or lexema(ii) = palabras_reservadas(28) Or lexema(ii) =
palabras_reservadas(29) Or lexema(ii) = palabras_reservadas(30) Then
reserva(cont1) = lexema(ii)
cont1 = cont1 + 1
ListBox2.Items.Add("Palabra Reservada:" & " " &
lexema(ii))
Else
reserva(cont1) = lexema(ii)
cont1 = cont1 + 1
ListBox2.Items.Add("identificador" & " " & lexema(ii))
End If
ElseIf (numerotoken(ii) = 10) And (lexema(ii) <> ChrW(10)) And
(lexema(ii) <> ChrW(13)) Then
ListBox2.Items.Add("Operador Matematico" & " " &
lexema(ii))
ElseIf (numerotoken(ii) = 40) And (lexema(ii) <> ChrW(10)) And
(lexema(ii) <> ChrW(13)) Then
ListBox2.Items.Add("Operador Comparativo" & " " & lexema(ii))
61

ElseIf (numerotoken(ii) = 90) Then


If lexema(ii) = "(" Then
parenta(cont2) = lexema(ii)
cont2 = cont2 + 1
cont5 = cont5 + 1
End If
If cont5 = 0 Then
If lexema(ii) = ")" Then
parenta(cont2) = lexema(ii)
End If
Else
If lexema(ii) = ")" Then
parentc(cont3) = lexema(ii)
cont3 = cont3 + 1
End If
End If
ListBox2.Items.Add("Comp. De Operacion:" & " " & lexema(ii))
ElseIf (numerotoken(ii) = 80) Then
ListBox2.Items.Add("Operador Exponencial" & " " &
lexema(ii))
ElseIf (numerotoken(ii) = 60) Then
ListBox2.Items.Add("Operador Booleano" & " " & lexema(ii))
ElseIf (numerotoken(ii) = 70) Then
ListBox2.Items.Add("Corte" & " " & lexema(ii))
ElseIf (numerotoken(ii) = 50) Then
ListBox2.Items.Add("Comentario" & " " & lexema(ii))
ElseIf (numerotoken(ii) = 20) And (lexema(ii) <> ChrW(10)) And
(lexema(ii) <> ChrW(13)) Then
ListBox1.Items.Add("Error" & " " & lexema(ii))
ElseIf (numerotoken(ii) = 3) Then
num(cont4) = lexema(ii)
cont4 = cont4 + 1
cont6 = 1
'ListBox2.Items.Add("Decimal" & " " & lexema(ii))
ElseIf (numerotoken(ii) = 2) Then
If cont6 = 0 Then
num(cont4) = lexema(ii)
cont4 = cont4 + 1
cont6 = 0
End If
'ListBox2.Items.Add("Entero" & " " & lexema(ii))
62

End If

Next

'For i = 0 To cont1
'If reserva(i) = palabras_reservadas(2) Or reserva(i) =
palabras_reservadas(3) Or reserva(i) = palabras_reservadas(4) _
' Or reserva(i) = palabras_reservadas(5) Or reserva(i) =
palabras_reservadas(6) Or reserva(i) = palabras_reservadas(11) _
' And parenta(i) = caracteres(1) And parentc(i) = caracteres(2) Then
'ListBox2.Items.Add("Funcion" & " " & reserva(i) & parenta(i) &
num(i) & parentc(i))
'Else
'ListBox1.Items.Add("Error" & " " & reserva(i) & parenta(i) & num(i)
& parentc(i))
'End If
'Next

End Sub

Conclusion
Esta fase del compilador no es en realidad una parte separada del compilador, la
mayora de los compiladores generan cdigo como parte del proceso de anlisis
63

sintctico, esto es debido a que requieren del rbol de sintaxis y si este no va a


ser construido fsicamente, entonces deber acompaar al analizador sintctico
al barrer el rbol implcito. En lugar de generar cdigo ensamblador directamente,
los compiladores generan un cdigo intermedio que es ms parecido al cdigo
ensamblador, las operaciones por ejemplo nunca se hacen con ms de dos
operandos. Al no generarse cdigo ensamblador el cual es dependiente de la
computadora especfica, sino cdigo intermedio, se puede reutilizar la parte del
compilador que genera cdigo intermedio en otro compilador para una
computadora con diferente procesador cambiando solamente el generador de
cdigo ensamblador al cual llamamos back-end, la desventaja obviamente es la
lentitud que esto conlleva.

La tarea de sntesis suele comenzar generando un cdigo intermedio. El cdigo


intermedio no es el lenguaje de programacin de ninguna mquina real, sino que
corresponde a una mquina abstracta, que se debe de definir lo ms general
posible, de forma que sea posible traducir este cdigo intermedio a cualquier
mquina real. El objetivo del cdigo intermedio es reducir el nmero de
programas necesarios para construir traductores, y permitir ms fcilmente la
transportabilidad de unas mquinas a otras. Supngase que se tienen n
lenguajes, y se desea construir traductores entre ellos. Sera necesario construir
n*(n-1) traductores.

Sin embargo si se construye un lenguaje intermedio, tan slo son necesarios 2*n
traductores.
As por ejemplo un fabricante de compiladores puede construir un compilador
para diferentes mquinas objeto con tan slo cambiar las dos ltimas fases de la
tarea de sntesis.

Referencias
Garca-Beltrn, A. M. (s.f.). Mtodos Informticos . Mc Graw Hill.
64

J., D. (1991). La Biblia de TurboPascal. Madrid.: Anaya Multimedia.


Jaume. (22 de Enero de 2010.). Ingeniera Informtica, Procesadores de
Lenguaje. Obtenido de Ingeniera Informtica, Procesadores de
Lenguaje.: Generacin de Cdigo.
Joyanes. (1996). Fundamentos de programacin, Algoritmos y Estructuras de
Datos, Segunda edicin. McGrawHill.
lawebdelprogramador. (s.f.). Transformar-notacion-infija-a-postfija. Obtenido
de http://www.lawebdelprogramador.com/foros/Dev-C/724318Transformar-notacion-infija-a-postfija.html
pilas-listas-expresiones. (s.f.). monografias. Obtenido de
http://www.monografias.com/trabajos44/pilas-listas-expresiones/pilaslistas-expresiones2.shtml#ixzz3nXiPGmfk
TurboPascal. (s.f.). Obtenido de Ed. Bellisco, 2 edicin, Madrid, 2002

65

Você também pode gostar