Anda di halaman 1dari 37

INSTITUTO TECNOLOGICO SUPERIOR DE ZONGOLICA

LENGUAJES Y AUTOMATAS II

LSC. RAFAEL JUAN CORDOBA DE LA LLAVE

MAYO 2014

INTRODUCCION
El desarrollo de software se puede dividir en 2 grandes categoras. El
software comercial y el software cientfico. La presente materia proporciona las
bases para crear software cientfico. Es comn pensar que el estudiante normal
nunca tendr acceso a desarrollar software cientfico, sin embargo, esto es un
error ya que cada da las necesidades se van ampliando y todo va siendo ms
accesible. Tenemos el clsico ejemplo de la robtica. Actualmente ya hay tiendas
donde venden accesorios para hacer un pequeo robot de juguete. Eso antes no
se vea y ahora ya es comn.
Por lo mismo, es importante proporcionarle al alumno las bases para que l se
introduzca con profundidad en el mundo de los compiladores. Esta materia abre
horizontes impresionantes ya que se conoce a fondo las etapas por las que
atraviesa la creacin de un lenguaje de computacin. Desde la etapa lxica hasta
la etapa de generacin de cdigo, el estudiante debe profundizar en
conocimientos que colindan con la parte electrnica de la computadora, el
lenguaje ensamblador, el lenguaje mquina.
Esta materia es una aventura racional. Algunos pensarn que es un tormento
cerebral, pero los inteligentes sabrn apreciar todas las competencias que se
desarrollan en esta materia.
Cabe mencionar que esta materia es la 2. Parte de la materia Lenguajes y
autmatas, por lo tanto se debe dedicar cierto tiempo a dar un repaso prctico a la
1. Parte de la materia que consisti en las 2 primeras fases de los compiladores:
fase lxica y fase sintctica.
Si no se da este repaso se corre el peligro de que el alumno no entienda sta
segunda parte ya que van muy ligadas.
Es muy recomendable utilizar un compilador didctico.
Se recomienda
ampliamente el compilador desarrollado por Kenneth Louden. En la bibliografa al
final de este documento se encuentra con la referencia nmero 3 y nmero 12.
Esto debido a que el alumno debe conocer un compilador ya hecho para as
entender al 100% todos los conceptos.

PROPOSITO

CONTENIDO

En esta asignatura se debe desarrollar el anlisis semntico, la generacin de


cdigo, la optimizacin y la generacin del cdigo objeto para obtener el
funcionamiento de un compilador.
Esta asignatura busca proveer al estudiante de herramientas, conocimientos y

habilidades necesarias para desarrollar un compilador con base en los conocimientos


previos de la asignatura lenguajes y autmatas I. La aportacin de esta materia es
relevante en el mbito del desarrollo de software de sistemas.
Es indispensable distinguir que la carrera de Ingeniera en Sistemas Computacionales
se basa no slo en el desarrollo de software comercial y administrativo, sino tambin
en el desarrollo de software cientfico. Esta materia se ubica en la segunda categora
y es indispensable desarrollar software en estos campos para preparar a los
egresados y tengan la posibilidad de cursar posgrados de alto nivel.
La asignatura trata de concretar un traductor iniciado en la materia previa para que el
estudiante comprenda que es capaz, mediante tcnicas bien definidas, de crear su
propio lenguaje de programacin.
La aportacin de la asignatura al perfil del egresado ser especficamente la siguiente:
Desarrollar, implementar y administrar software de sistemas o de aplicacin que
cumpla con los estndares de calidad buscando como finalidad apoyar la
productividad y competitividad de las organizaciones.
Integrar soluciones computacionales con diferentes tecnologas, plataformas o
dispositivos.
Disear e implementar interfaces hombre mquina y maquina mquina para la
automatizacin de sistemas.
Identificar y comprender las tecnologas de hardware para proponer, desarrollar y
mantener aplicaciones eficientes.

OBJETIVO
Desarrollar software de base: traductor, intrprete o compilador.

COMPETENCIAS PREVIAS Y RELACION CON CURSOS ANTERIORES Y


POSTERIORES
Definir, disear, construir y programar las fases del analizador lxico y sintctico de un
traductor o compilador.

Su relacin con materias anteriores: Fundamentos de programacin, Tpicos


avanzados de programacin, Fundamentos de Ingeniera de Software, Lenguajes
y autmatas I.

Su relacin con materias posteriores: Sistemas programables


Las competencias logradas en esta materia son: razonamiento deductivo e
inductivo, anlisis sntesis.

CONTENIDO

UNIDAD 1 Anlisis semntico


1.1.

Arboles de expresiones.

1.2.

Acciones semnticas de un analizador sintctico.

1.3. Comprobaciones de tipos en expresiones .


1.4. Pila semntica en un analizador sintctico.
1.5. Esquema de traduccin.
1.6. Generacin de la tabla de smbolo y de direcciones.
1.7. Manejo de errores semnticos.

UNIDAD 2 Generacin de cdigo intermedio.


2.1 Notaciones
2.1.1 Prefija
2.1.2 Infija
2.1.3 Postfija
2.2 Representaciones de cdigo Intermedio.
2.2.1 Notacin Polaca
2.2.2 Cdigo P
2.2.3 Triplos
2.2.4 Cudruplos.
2.3 Esquema de generacin.
2.3.1 Variables y constantes.
2.3.2 Expresiones.

2.3.3 Instruccin de asignacin.


2.3.4 Instrucciones de control.
2.3.5 Funciones
2.3.6 Estructuras

UNIDAD 3 Optimizacin

3.1 Tipos de optimizacin.


3.1.1 Locales.
3.1.2 Ciclos.
3.1.3 Globales.
3.1.4 De mirilla.
3.2 Costos.
3.2.1 Costo de ejecucin. (memoria, registros, pilas)
3.2.2 Criterios para mejorar el cdigo.
3.2.3 Herramientas para el anlisis del flujo de datos.

UNIDAD 4 Generacin de cdigo objeto


4.1 Registros.
4.2 Lenguaje ensamblador.
4.3 Lenguaje maquina.
4.4 Administracin de memoria.

COMPETENCIAS A ALCANZAR EN EL CURSO

Al trmino del curso el participante lograr las siguientes competencias:


Unidad 1: Anlisis Semntico.
Disear mediante el uso de arboles de expresiones dirigida por la sintaxis un
analizador semntico para un meta-compilador.

Unidad 2: Generacin de cdigo intermedio.


Aplicar las herramientas para desarrollar una mquina virtual que ejecute cdigo
intermedio a partir del cdigo fuente de un lenguaje prototipo.
Unidad 3: Optimizacin.
Conocer e Identificar los diferentes tipos de optimizacin que permita eficientar el
cdigo intermedio.

Unidad 4: Generacin del cdigo objeto.


Utilizar un lenguaje de bajo nivel para traducir el cdigo construido a lenguaje
mquina para su ejecucin.

UNIDAD 1 Anlisis Semntico.


Competencia especfica de la unidad:
Disear mediante el uso de arboles de expresiones dirigida por la sintaxis un
analizador semntico para un meta-compilador.

CONTENIDO TEMATICO
En este captulo analizamos la fase del compilador que calcula la informacin
ad~cional necesaria para la compilacin una vez que se conoce la estructura
sintctica de un programa. Esta fase se conoce como anlisis semntico debido a que
involucra el clculo de informacin que rebasa las capacidades de las gramticas

libres de contexto y los algoritmos de anlisis sintctico estndar, por lo que no se


considera como sintaxis.'
La informacin calculada tambikn est estrechamente relacionada con el significado
final, o semntica, del programa que se traduce. Como el anlisis que realiza un
compilador es esttico por definicin (tiene lugar antes de la ejecucin), dicho anlisis
semntico tambin se conoce como anlisis semntico esttico. En un lenguaje
tpico estticamente tipificado como C. el anlisis semntico involucra la
construccin de una tabla de smbolos para mantenerse al tanto de los significados de
nombres establecidos en declaraciones e inferir tipos y verificarlos en expresiones y
sentencias con el fin de determinar su exactitud dentro de las reglas de tipos del
lenguaje.
El anlisis semntico se puede dividir en dos categoras. La primera es el anlisis de
un programa que requiere las reglas del lenguaje de programacin para establecer su
exactitud y garantizar una ejecucin adecuada. La complejidad de un anlisis de esta
clase requerido por una definicin del lenguaje vara enormemente de lenguaje a
lenguaje. En lenguajes orientados en forma dinmica, tales como LISP y Smalltalk,
puede no haber anlisis semntico esttico en absoluto, mientras que en un lenguaje
como Ada existen fuertes requerimientos que debe cumplir un programa para ser
ejecutable. Otros lenguajes se encuentran entre estos extremos (Pascal, por ejemplo.
no es tan estricto en sus requerimientos estticos como Ada y C, pero no es tan
condescendiente como LISP).
La segunda categora de anlisis semntico es el anlisis realizado por un compilador
para mejorar la eficiencia de ejecucin del programa traducido. Esta clase de anlisis
por lo regular se incluye en anlisis de "optimizacin", o tcnicas de mejoramiento de
cdigo. Investigaremos algunos de estos mtodos en el capitulo sobre generacin de
cdigo, mientras que en este capitulo nos enfocaremos en los anlisis comunes que
por exactitud son requeridos para una definicin del lenguaje. Conviene advertir que
las tcnicas estudiadas aqui se aplican a ambas situaciones. Tambin que las dos
categoras no son mutuamente excluyentes, ya que los requerimientos de exactitud,
tales como la verificacin de tipos estticos, tambin permiten que un compilador
genere cdigo ms eficiente que para un lenguaje sin estos requerimientos. Adems,
vale la pena hacer notar que los requerimientos de exactitud que aqui se comentan
nunca pueden establecer Ia exactitud completa de un programa, sino slo una clase
de exactitud parcial. Tales requerimientos todava son tiles debido a que
proporcionan al programador informacin para mejorar la seguridad y fortaleza del
programa.
El anlisis semntico esttico involucra tanto la descripcin de los anlisis a realizar
como la implementacin de los anlisis utilizando algoritmos apropiados. En este
sentido, es semejante al anlisis lxico y sintctico. En el anlisis sintctico, por
ejemplo, utilizamos gramticas libres de contexto en la Forma Backus-Naus (BNF, por
sus siglas en ingls) para describir la sintaxis y diversos algoritmos de anlisis
sintctico descendente ascendente para implementar la sintaxis. En el anlisis
semntico la situacin no es tan clara, en parte porque no hay un mtodo estndar
(como el BNF) que permita espeficar la semntica esttica de un lenguaje, y en parte
porque la cantidad y categora del anlisis semntico esttico vara demasiado de un
lenguaje a otro. Un mtodo para describir el anlisis semntico que los escritores de

compiladores usan muy a menudo con buen efectos es la identificacin de atributos,


o propiedades, de entidades del lenguaje que deben calcularse y escribir ecuaciones
de atributos o reglas semnticas, que expresan cmo el clculo de tales atributos
est relacionado con las reglas gramaticales del lenguaje. Un conjunto as de atributos
y ecuaciones se denomina gramtica con atributos.
Las gramticas con atributos son ms tiles para los lenguajes que obedecen el
principio de la semntica dirigida por sintaxis, la cual asegura que el contenido
semntico de un programa se encuentra estrechamente relacionado con su sintaxis.
Todos los lenguajes modernos tienen esta propiedad. Por desgracia, el escritor de
compiladores casi siempre debe construir una gramtica con atributos a mano a partir
del manual del lenguaje, ya que rara vez la da el diseador del lenguaje. An peor, la
construccin de una gramtica con atributos puede complicarse innecesariamente
debido a su estrecha adhesin con la estructura sintctica explcita del lenguaje. Un
fundamento mucho mejor para la expresin de los clculos semnticos es la sintaxis
abstracta, como se representa mediante un rbol sintctico abstracto. Incluso. el
diseador del lenguaje, tambin suele dejar al escritor del compilador la
especificacicin de la sintaxis abstracta.
Los algoritmos para la implementacin del anlisis semntico tampoco son tan
claramente expresables como los algoritmos de anlisis sintctico. De nuevo, esto se
debe en parte a los mismos problemas que se acaban de mencionar respecto a la
especificacin del anlisis semntico. No obstante, existe un problema adicional
causado por la temporizacin del anlisis durante el proceso de compilacin. Si el
anlisis semntico se puede suspender hasta que todo el anlisis sintctico (y la
construccin de un rbol sintctico abstracto) est completo, entonces la tarea de
implementar el anlisis semntico se vuelve considerablemente ms fcil y consiste
en esencia en la especificacin de orden para un recorrido del rbol sintctico. junto
con los clculos a realizar cada vez que se encuentra un nodo en el recorrido. Sin
embargo, esto implica que el compilador debe ser de paso mltiple. Si. por otra parte,
el compilador necesita realizar todas sus operaciones en un solo paso (incluyendo la
generacin del cdigo), entonces la implementacin del anlisis semntico se convierte
en mucho ms que un proceso a propsito para encontrar un orden correcto y un mtodo
para calcular la informacin semntica (suporiiendo que un orden correcto as exista en
realidad). Afortunadamente, la prctica moderna cada vez ms permite al escritor de
compiladores utilizar pasos mltiples para simplificar los procesos de anlisis semntico y
generacin de cdigo.
A pesar de este estado algo desordenado del anlisis semntico, es muy til para estudiar
gramticas con atributos y cuestiones de especificacin. ya que esto redundar en la
capacidad de escribir un cdigo ms claro, ms conciso y menos proclive a errores para
anlisis semntico, adems de permitir una comprensin ms fcil de ese cdigo.
Por lo tanto, el captulo comienza con un estudio de atributos y gramticas con atributos.
Contina con tcnicas para implementar los clculos especificados mediante una
gramtica con atributos, incluyendo la inferencia de un orden para los clculos y los
recorridos del rbol que los acompaan. Dos secciones posteriores se concentran en las
reas principales del anlisis semntico: tablas de smbolos y verificacin de tipos. La
ltima seccin describe un analizador semdntico para el lenguaje de programacin TlNY .

ATRIBUTOS Y GRAMATICAS CON ATRIBUTOS

Un atributo es cualquier propiedad de una construccin del lenguaje de programacin.


Los atributos pueden variar ampliamente en cuanto a la infrmacin que contienen, su
complejidad y en particular el tiempo que les torna realizar el proceso de
traducci<n/ejec~icincu ando pueden ser determinados. Ejemplos tpicos de atributos son
El tipo de <latos de una variable El valor de una expresin La ubicacin de una variable
en la memoria El cbdigo objeto de un procedimiento El nmero de dgitos significativos en
un nmero Los atributos se pueden csrablecer antes del proceso de compilacin (o
incluso la construccin de un con~pilador).P or ejemplo, el nmero de dgitos significativos
eri un nmero se puede establecer (o por lo menos dar un valor mnimo) mediante la
definicin de un Ienguaje.
Adems, los atributos s6lo se pueden determiriar durante la ejecuciti tiel progrini;~, ti11
como el valor de una expresicn (no consiante). o la ubicaci6n de una estructura {le datos
dininiicaniente asignada. El proceso (te calcular un atributo y asociar su valor calculado
con la construccin del lenguaje en cuestin se define corno fijacin del atrihuio. El
tiempo que toma el proceso de compilacin cuando se presenta la fijacin de un atributo
se enomina tiempo de fijacin. Los tiempos de fijacin de atributos diferentes varan, e
incluso el mismo atributo puede tener tiempos de fijacin bastante diferentes de un
lenguaje a otro.
Definicin de otro autor:

Anlisis sintctico, semntico y generacin de cdigo


Como lo hemos mencionado antes, la sintaxis trata con la forma de los programas vlidos,
mientras que la semntica trata con su significado. Se dice que la sintaxis de un lenguaje es
aquella porcin del mismo que puede ser descrita de manera adecuada por medio de una
Gramtica Libre de Contexto (GLC), mientras que la semntica es aquella porcin del
lenguaje que no puede ser descrita de esta manera.
El anlisis semntico y la generacin de cdigo intermedio pueden ser descritos en
trminos de la anotacin o decoracin de un rbol sintctico o rbol de anlisis sintctico
(parse tree). Las anotaciones de un rbol sintctico son llamados atributos.
El analizador sintctico recibe una serie de tokens del analizador lxico y los organiza en
un rbol sintctico. La manera en que estos tokens son organizados est definida por un
conjunto de reglas, potencialmente recursivas. Este conjunto de reglas es la gramtica libre
de contexto.
En general, una GLC consiste de:

Un conjunto finito N de smbolos no terminales,


Un conjunto finito T de smbolos terminales,
Un subconjunto finito P de [(N U T)* - T*] x (N U T)* llamado conjunto de
producciones, y

Un smbolo inicial N.

La tarea del analizador sintctico (parser) es determinar si una cadena de entrada puede
derivarse a partir del smbolo inicial, y si es as, cmo puede hacerse. Hay dos maneras
bsicas de hacer esto:

Anlisis sintctico descendente (top-down): puede verse como el intento de


encontrar la derivacin ms a la izquierda de un flujo de entrada recorriendo el rbol
sintctico de arriba hacia abajo. Los tokens son analizados de izquierda a derecha.
Para manejar la ambigedad se suele utilizar lo que se conoce como opcin
inclusiva, expandiendo los lados derechos de las reglas gramaticales. Los
analizadores LL (Left-to-right, Leftmost derivation) y Recursivos-descendentes son
ejemplos de este tipo de anlisis.
Anlisis sintctico ascendente (bottom-up): el analizador inicia con la secuencia de
entrada e intenta re-escribirla hasta llegar al smbolo inicial. Intuitivamente el
analizador intenta localizar el elemento ms bsico, despus los elementos que
contienen stos, y as sucesivamente. Los analizadores LR (Left-to-right, Rightmost
derivation) son ejemplos de este tipo de analizadores, que tambin son conocidos
como Analizadores Desplaza-Reduce (Shift-Reduce).

Analizadores LL vs. LR

El acrnimo LL viene de Left-to-Right, Leftmost Derivation, lo que significa que


cuando se encuentra una regla de produccin no terminal que contiene componentes
no terminales en su parte derecha, el componente no terminal de ms a la izquierda
es sustituido por el lado derecho de su respectiva regla. Si esa regla tambin
contiene componentes no terminales, el proceso se repite.
Debido a este comportamiento, los rboles sintcticos generados por los
analizadores LL tienden a crecer ms hacia la izquierda que hacia la derecha. Para
tratar de evitar ambigedades, el analizador siempre lee el siguiente smbolo en la
cadena de entrada, y lo llama look-ahead. Por otro lado, el analizador LL decide
la regla de produccin a utilizar, dependiendo de lo que resta por analizar en la
cadena de entrada. No mantiene informacin sobre el progreso del anlisis. Si surge
alguna ambigedad que no pueda ser resuelta con el auxilio del smbolo lookahead, el analizador produce un error. Aunque es posible aumentar el nmero de
smbolos look-ahead, el problema esencial persiste; adems de los smbolos
look-ahead, no hay otro mtodo para recuperarse de ambigedades en este tipo de
analizadores.
Los analizadores LR (Left-to-right, Rightmost derivation) tambin utilizan
smbolos look-ahead, pero adems mantienen informacin sobre el estado del
proceso de anlisis. Para este registro utilizan una pila (stack) donde guardan
informacin del estado inmediato anterior. Cada regla de produccin es considerada
un estado y cada regla que resulta en un smbolo no terminal es considerada una

transicin a otro estado. Esto hace que los analizadores LR sean ms resistentes a
las ambigedades que los LL, pero pueden resultar en analizadores que requieren
ms recursos (en trminos de tiempo de procesamiento y espacio de memoria).
Los analizadores LALR (Look Ahead LR) son una especializacin de los
analizadores LR. Pueden manejar ms GLC que el LR bsico. Es un tipo de
analizador muy popular porque logra un buen balance entre el nmero de
gramticas que puede manejar y su consumo computacional (en trminos de
procesador y memoria). Las herramientas Yacc y Bison generan analizadores
sintcticos de este tipo.

Ejemplo de anlisis sintctico


Para ilustrar estos conceptos, supongamos que tenemos un lenguaje de expresiones
algebraicas escritas con los smbolos T = {x, y, z, +, *, (, )}, que constituyen los smbolos
terminales de la gramtica. Los smbolos no-terminales que utilizaremos son E para una
expresin y T para trminos que constan de factores (smbolo no-terminal F), es decir,
N={E,T,F}.
Una expresin algebraica puede consistir de un solo trmino:
ET
O la suma de una expresin y un trmino:
EE+T
Un trmino puede consistir de un factor, o del producto de un factor y un trmino:
TF
TF*T
Un factor puede consistir de una expresin algebraica entre parntesis o de uno de los
smbolos terminales:
F(E)
Fx
Fy
Fz
Estas reglas, tambin llamadas producciones, definen el conjunto de todas las cadenas
vlidas de este lenguaje.

Una expresin vlida para este lenguaje es x * y + z * (x + y). El rbol sintctico


correspondiente a esta expresin es el siguiente:

Figura 1. rbol sintctico de la expresin algebraica x * y + z * (x + y)


Gramtica de atributos
Cuando describimos un lenguaje por medio de una GLC, no se puede decir nada acerca de
los significados de las expresiones. Para el manejo de los significados es comn usar una
gramtica de atributos, la cual asigna un valor a cada smbolo (terminal y no-terminal) del
lenguaje. La gramtica se incrementa con un conjunto de reglas de produccin que
especifican como se relaciona cada smbolo con su valor.
Para ilustrar el uso de las gramticas de atributos, supongamos la siguiente gramtica de
expresiones algebraicas compuesta por constantes y que maneja precedencia y
asociatividad:
EE+T
EE-T
E T
TT*F
TT/F
TF
F -F
F(E)
F constante
Ahora presentamos la gramtica de atributos para este lenguaje de expresiones algebraicas:

1. E1 E2 + T
E1.val := suma(E2.val, T.val)
2. E1 E2 - T
E1.val := diferencia(E2.val, T.val)
3. E T
E.val := T.val
4. T1 T2 * F
T1.val := producto(T2.val, F.val)
5. T1 T2 / F
T1.val := cociente(T2.val, F.val)
6. T F
T.val := F.val
7. F1 -F2
F1.val := inverso(F2.val)
8. F ( E )
F.val := E.val
9. F constante
F.val := constante.val
Como vemos, en estas reglas de la gramtica de atributos, asignar significados a las
sentencias del lenguaje equivale a asignar una funcin que recibe como parmetros los
componentes de la sentencia y regresa un valor que se asigna a esa expresin.
Resumen
Hemos visto hasta ahora que el anlisis sintctico y el anlisis semntico utilizan algunas
herramientas matemticas para realizar sus funciones: rboles sintcticos y gramticas de
atributos. Estas herramientas nos permiten definir la sintaxis y semntica de un lenguaje y
nos preparan para la generacin de cdigo intermedio.

UNIDAD 2 Generacin
cdigo intermedio.

de

Competencia especfica de la unidad:


Aplicar las herramientas para desarrollar una mquina virtual que ejecute cdigo
intermedio a partir del cdigo fuente de un lenguaje prototipo.

CONTENIDO TEMATICO

Cdigo mquina
La aparicin de los lenguajes de alto nivel mejor la productividad de los programadores al
liberarlos de los detalles de bajo nivel de la computadora que estaban programando. El
compilador es quien se encarga de realizar la conversin del cdigo fuente en lenguaje de alto
nivel al cdigo mquina de la computadora que ejecutar el programa. Es, por tanto, el
compilador quien ahora maneja los detalles de bajo nivel de la arquitectura a programar. Esto
implica que el desarrollo del compilador requiere del conocimiento de los detalles de la
arquitectura de la mquina destino. En este apartado conoceremos la computadora abstracta para
la que Tiny traduce sus programas.

3.2.1 La mquina abstracta


En este apartado describimos la computadora para la cual el compilador de Tiny genera
cdigo objeto. Est diseada para facilitar la traduccin de un lenguaje similar al Pascal a
una arquitectura abstracta. Esta computadora es un subconjunto de la computadora Dream
(Dream machine) diseada por Frank DeRemer. Se trata de una computadora orientada a
pila (stack) sin registros direccionales, por lo que carece de instrucciones como carga
registro X con ; es decir, todas las instrucciones suponen que los datos estn en la pila y
guardan los resultados en la pila.
Adems, se han eliminado algunas restricciones normales en las mquinas reales:

Las instrucciones de ramificacin no estn limitadas a un determinado rango.


Todas las instrucciones tienen el mismo formato, y no dos o tres formatos
diferentes, como en la arquitectura IA32, por ejemplo.

La computadora tiene tres memorias diferentes y separadas entre s:

De cdigo
De datos
De direcciones de retorno

Los lmites de cada tipo de memoria estn indicados por una serie de registros. La siguiente
figura ilustra estas memorias y sus registros lmite:

La memoria de cdigo se considera de slo-lectura. Ningn programa puede saltar (branch)


fuera de su rea de cdigo, ya que todas sus instrucciones estn confinadas al rango de
direcciones limitado por los registros CBR y CLR. Ni el cdigo ni las direcciones de
retorno pueden modificarse ni copiarse, debido a que todas las lecturas y escrituras a
memoria estn restringidas a realizarse entre los registros GBR (Global Base Register) y
STR (Stack Top Register).
En otras palabras, en esta mquina es imposible ejecutar cdigo que se automodifique.
El lmite de la memoria disponible est determinado por el registro SLR (Stack Limit
Register). Este registro simula el tamao limitado de la memoria fsica de las computadoras
reales; sin embargo, para fines del compilador de Tiny, supondremos que la mquina no
tiene limitacin de memoria, es decir, el contenido de SLR es infinito.
Todo el direccionamiento de las variables globales y locales es relativo a GBR (Global
Base Register) o a LBR (Local Base Register), segn corresponda. Por tanto, la instruccin
LLV i (Load Local Value i) significa coloca en el tope de la pila (push) el valor de la isima palabra del marco local (local frame). Por tanto, i puede verse como un

desplazamiento (offset) a partir de LBR. La ejecucin de esta instruccin ajustar el


registro del tope de la pila (STR). Otro ejemplo es SGVi (Storage Global Value i), que
significa saca de la pila el valor en el tope (pop) y almacnalo en la i-sima palabra
global. De nuevo, la ejecucin de esta instruccin ajustar el STR, e i es el desplazamiento
respecto de GBR. Otro ejemplo ms es LIT i (Literal i), que significa coloca i en la
pila.
Con el fin de simplificar, asumimos que la ejecucin del programa, una vez cargado en
memoria, inicia en la instruccin indicada en CBR; es decir, asumimos que el cargador
carga el programa a partir de esa localizacin. La herramienta TWS incluye un intrprete
que hace las veces de la mquina abstracta.
3.2.2 Formato de instrucciones
El formato de las instrucciones de la mquina abstracta es el siguiente:
{etiqueta} [mnemnico de la instruccin] [0, 1 o 2 operandos]
Donde la etiqueta es opcional, adems vemos que hay instrucciones que no manejan datos,
otras que manejan un slo dato y otras que manejan dos datos. Es decir, en el conjunto de
instrucciones encontramos instrucciones con 0, 1 o 2 campos de direccionamiento.
3.2.3 Conjunto de instrucciones
Las instrucciones que la mquina abstracta puede ejecutar son las siguientes:
De control del programa
NOP : Hacer nada
HALT : Detenerse (halt)
De transferencia de datos
LIT v : Cargar (Push) la Literal v en Local frame (Lf) de la memoria de datos.
LLV i : Cargar valor local (Load Local Value) i en Lf.
LGV i : Cargar valor global (Load Local Value) i en Lf.
SLV i : Almacena valor local i (Store Local Value i) en Lf.
SGV i : Almacena valor global i.
LLA i : Cargar Direccin Local i (Load Local Address i) en Lf.
LGA i : Cargar Direccin Global i (Load Global Address i) en Lf.
POP n : Extrae n valores (Pop n values).
DUP : Duplica el tope de la pila.
SWAP : Intercambia los dos valores superiores de la pila.
Aritmticas y lgicas

UOP i : Operacin unitaria i (Unary Operation i): const X = Pop Lf.


Push (Unop(i,X)) en Lf
BOP i : Operacin binaria i: const Xr,Xl = Pop Lf, Pop Lf
Push (Binop(i,Xl,Xr)) en Lf
De control de flujo
CALL n : Llamada a una subrutina.
RTN n : Retorno de rutina.
GOTO L : I <- L Salto incondicional a L
COND L M: I <- if Pop Lf = True # Pop Stack. Si el valor es:
then L # Verdadero, salta a L
else M # Falso, salta a M.
fi
CODE F : Push F on Lf # Carga el punto de entrada.
SOS i : Llamada a la funcin i del sistema operativo
Donde
Unop(i,X) significa:
case i of
UNOT : not(X)
UNEG : -(X)
USUCC : X+1
UPRED : X-1
Binop(i,Xl,Xr) significa:
case i of
BAND : Xl and Xr
BOR : Xl or Xr
BPLUS : Xl + Xr
BMINUS : Xl - Xr
BMULT : Xl * Xr
BDIV : Xl div Xr
BMOD : Xl mod Xr
BEQ : Xl = Xr
BNE : Xl <> Xr
BLE : Xl <= Xr
BGE : Xl >= Xr
BLT : Xl < Xr
BGT : Xl > Xr
Llamadas al sistema
Para simplificar el manejo de los dispositivos de Entrada/Salida suponemos que tenemos
disponibles algunas llamadas al sistema operativo, a las cuales se accede por medio de la
instruccin SOS:

SOS (Sistema operativo) i significa:


case i of
TRACEX : Trace_Execution <- not TraceExecution
DUMPMEM: Dump_Memory
INPUT : readln(i)
Push i on Lf
INPUTC : readln(ch)
Push Ord(ch) on Lf
OUTPUT : write (Pop Lf)
OUTPUTC: write (Chr(Pop(Lf)))
OUTPUTL: writeln
EOF : if eof(input)
then Push True on Lf
else Push False on Lf
Vemos que la mquina abstracta puede ejecutar las cuatro operaciones aritmticas bsicas:
suma, resta, multiplicacin y divisin, adems la operacin mdulo; tambin puede ejecutar
las tres operaciones lgicas bsicas: NOT, ANDy OR; puede ejecutar saltos condicionales e
incondicionales. Cuenta con llamadas al sistema operativo para las operaciones de
Entrada/Salida y para funciones de depuracin.
Como sabemos, el compilador debe traducir del lenguaje de alto nivel a este conjunto de
instrucciones. Es, por tanto, necesario entender como utilizar este lenguaje ensamblador
para escribir programas en bajo nivel para la mquina abstracta. A continuacin
presentamos un par de ejemplos de traduccin de Tiny al ensamblador de la mquina
abstracta.
Ejemplo 1
Vamos a mostrar la traduccin del siguiente programa en Tiny:
Program copy:
{ Despliega en pantalla (eco) los primeros 10 nmeros ledos con input }
Var count: integer;
Begin
Count:=1;
While( count <= 10) do
Begin
Output(read);
Count := count + 1;
End
End copy.

El cdigo mquina para este programa se muestra abajo. Obviamente, los comentarios no
son generados por el generador de cdigo.
LIT 0 # Espacio para Count
LIT 1 # Asigna 1
SGV 0 # Count := 1
L2 LGV 0 # Carga Count
LIT 10 # Carga 10
BOP BLE # POP, Compara. Push resultado T/F
COND L3 L4 # Pop stack, si V, ve a L3, sino, ve a L4.
L3 SOS INPUT # Llamada al SO. Lee y coloca en la pila
SOS OUTPUT # Llamada al SO. Saca de la pila y despliega
SOS OUTPUTL # Despliega un avance de lnea
LGV 0 # Carga Count
LIT 1 # Carga 1
BOP BPLUS # Smalos y guarda resultado en la pila
SGV 0 # Saca de la pila y almacena en Count
GOTO L2 # Regresa a L2
L4 HALT # Salta aqu cuando termines. Detnte.
Ejemplo 2
Con el fin de ayudar al entendimiento de esta mquina estudiaremos otro programa
ejemplo, escrito en el lenguaje Medium, que es el lenguaje intermedio para Tiny:
program fact:
var m: integer;
function fact(n: integer) : integer
begin
If n > 0 then
fact := n * fact( n 1 );
else
fact := 1;
m := m + 1;
end;
begin
m := 0;
output( fact( read ), m );
end fact.
El cdigo para la mquina abstracta es el siguiente:
LIT 0
GOTO L1
L2 LLV 1

LIT 0
BOP BGT
COND L3 L4
L3 LLV 1
LIT 0
LLV 1
LIT 1
BOP BMINUS
CODE L2
CALL 3
BOP BMULT
SLV 0
GOTO L5
L4 LIT 1
SLV 0
NOP
L5 LGV 0
LIT 1
BOP BPLUS
SGV 0
LLV 0
RTN 1
L1 LIT 0
SGV 0
LIT 0
SOS INPUT
CODE L2
CALL 1
SOS OUTPUT
LGV 0
SOS OUTPUT
SOS OUTPUTL
HALT
Es muy recomendable que traces con papel y lpiz la ejecucin de estos dos programas de
ejemplo para que entiendas mejor la programacin en bajo nivel de la mquina abstracta.

UNIDAD 3 Optimizacin.
Competencia especfica de la unidad:
Conocer e Identificar los diferentes tipos de optimizacin que permita eficientar el
cdigo intermedio.

CONTENIDO TEMATICO

Estrategias de optimizacin
La optimizacin del cdigo es el proceso de "puesta a punto" (tuning) de la salida de un
compilador con el fin de minimizar o maximizar algn atributo del programa objeto. Es
comn que la meta de la optimizacin sea minimizar el espacio en memoria que ocupa del
cdigo o maximizar la velocidad de ejecucin.
Una forma de clasificar las estrategias de optimizacin del cdigo se basa en el alcance de
la optimizacin: desde una sola instruccin (optimizacin local), hasta un programa entero
(optimizacin global).
Tcnicamente hablando es ms sencillo implementar estrategias locales que globales,
aunque normalmente el beneficio es menor que el obtenido con estrategias globales.
Algunos ejemplos de estrategias de optimizacin clasificadas por su alcance son:

Optimizaciones locales: Slo toman en cuenta la informacin local de una funcin.


Requieren menos tiempo de anlisis.
Optimizacin interprocedural o de programa completo: Requieren analizar el
programa completo. Un ejemplo de estrategia de este tipo es el reemplazo de una
llamada a funcin con el cdigo de la funcin, lo que reduce la sobrecarga normal
de una llamada a funcin.
Optimizacin de lazos: Se aplica slo a las estructuras repetitivas, como for() y
while(). Este tipo de optimizacin puede tener un fuerte impacto porque muchos
programas dedican un buen porcentaje de su tiempo de ejecucin a este tipo de
instrucciones.

Adems de la clasificacin por su alcance, las estrategias de optimizacin se dividen en dos


categoras generales:

Independiente vs. dependiente del lenguaje de programacin. La optimizacin


independiente del lenguaje de programacin se basa en el hecho de que muchos
lenguajes de programacin comparten estructuras comunes. La optimizacin
dependiente del lenguaje trata de aprovechar las particularidades de cada lenguaje
de alto nivel.
Independiente vs. dependiente de la mquina destino. Muchas de las mejores
optimizaciones se logran explotando las caractersticas particulares de la plataforma
destino.

Obviamente las caractersticas de la plataforma destino tambin afectan las estrategias de


optimizacin. Entre estas caractersticas tenemos las siguientes:

Nmero de registros internos en el CPU.


Tipo de procesador: RISC vs. CISC.
Nmero de unidades funcionales: coprocesador numrico o no, pipelining, etctera.

Para evitar complicar mucho al compilador de Tiny, la herramienta TWS no maneja ningn
tipo de optimizacin; sin embargo, muchos compiladores s lo hacen, ya que la posibilidad
de obtener cdigo optimizado siempre es un atractivo ms para cualquier compilador,
independientemente del lenguaje a traducir.

Deteccin de errores
Los errores de programacin pueden clasificarse en tres categoras:

Errores de compilacin
Errores de ejecucin
Errores lgicos

Errores de compilacin
Son errores que aparecen cuando se est compilando el programa y eventualmente
ocasionan que se detenga el proceso de traduccin.
Muchos de estos errores son causados por equivocaciones de captura, por ejemplo, un mal
deletreo de alguna palabra clave, mezcla incorrecta de maysculas y minsculas en los
nombres de variables, o la falta de un signo de puntuacin, entre otros.
Son los errores ms fciles de corregir porque contamos con la ayuda del compilador.
Cuando el compilador detecta un error durante el analizador sintctico o no puede asignar
significado a una expresin durante el anlisis semntico, genera un mensaje de error
mostrando una breve descripcin del error y la lnea del cdigo fuente donde lo encontr.
Normalmente el compilador intenta seguir el proceso de traduccin con el fin de detectar la
mayor cantidad posible de errores e informarlos al programador para que proceda a
corregirlos.
Cuando aparecen varios errores de compilacin, por lo general slo el primer error es real,
los dems pueden no serlo.
Errores de ejecucin
Son errores que aparecen mientras el programa est en ejecucin.

Un ejemplo tpico es la divisin entre cero; por ejemplo, supn que tienes la siguiente
expresin:
velocidad = kilmetros / horas
Si la variable horas = 0 cuando se intente ejecutar la instruccin, la divisin no puede
calcularse y se genera un error de ejecucin.
Errores lgicos
Causan que el programa no funcione correctamente y que arroje resultados equivocados.
En este tipo de errores la compilacin termina sin errores y el programa se ejecuta sin
errores de ejecucin, pero arroja resultados no esperados, stos son los ms difciles de
encontrar y corregir.

PRACTICA: Agregando la multiplicacin al traductor


inicial
En este apartado vamos a ilustrar la manera de expandir el lenguaje inicial agregando la
multiplicacin de dos enteros. Esto requiere modificar los siguientes componentes del
traductor:

El analizador lxico (lex.tiny)


El analizador sintctico (parse.tiny)
El analizador semntico (constrainer)
El generador de cdigo (gencode)

Vamos a ver como se realiza este proceso:


Cambios al analizador lxico lex.tiny
Las reglas para las operaciones dentro del analizador lxico son las siguientes:
"+"
{
"-" { returnrule(yytext[0]); }

returnrule(yytext[0]);

Para agregar el operador "*" se debe agregar la siguiente lnea:


"*" { returnrule(yytext[0]); }
Cambios al analizador sintctico parser.tiny

A continuacin reproducimos la parte del analizador sintctico que define las operaciones
aritmticas:
Expression ->Term
->Term LTE Term => "<=";
Term ->Primary
->Primary '+' Term => "+";
Primary -> '-' Primary => "-"
-> READ => "read"
->Name
->INTEGER_NUM => "<integer>"
-> '(' Expression ')';
Name -> IDENTIFIER => "<identifier>";
Para introducir el operador de la multiplicacin, se debe agregar un nuevo productor de
factor:
Expression ->Term
->Term LTE Term => "<=";
Term ->Primary
->Primary '+' Term => "+";
Factor ->Primary
->Primary '*' Factor => "*";
Primary -> '-' Primary => "-"
-> READ => "read"
->Name
->INTEGER_NUM => "<integer>"
-> '(' Expression ')';
Name -> IDENTIFIER => "<identifier>";
Modificaciones al constrainer
El constrainer consiste de la clase tws::constrainer y del archivo de cabecera nodes.h, que
definen los nodos del rbol que el constrainer y el generador de cdigo deben recorrer para
realizar su trabajo. El archivo nodes.h contiene las siguientes lneas:
addnode(ProgramNode,"program");
addnode(TypesNode, "types");
addnode(TypeNode, "type");
addnode(DclnsNode ,"dclns");
addnode(DclnNode, "dcln");
addnode(IntegerTNode,"integer");
addnode(BooleanTNode, "boolean");
addnode(BlockNode,"block");
addnode(AssignNode, "assign");

addnode(OutputNode, "output");
addnode(IfNode ,"if");
addnode(WhileNode ,"while");
addnode(NullNode , "null");
addnode(LENode ,"<=");
addnode(PlusNode ,"+");
addnode(MinusNode,"-");
addnode(ReadNode,"read");
addnode(IntegerNode,"<integer>");
addnode(IdentifierNode,"<identifier>");
Se debe agregar la siguiente lnea para el nodo de la multiplicacin:
addnode(MultNode ,"*");
El archivo de la clase tws::constrainer tiene el mtodo expression(), que analiza las
expresiones en el AST y determina si estn bien formadas. A continuacin mostramos el
fragmento de este mtodo que verifica los nodos "+" y "-":
if ((nodename == PlusNode) or (nodename == MinusNode)){
Type1 = expression(T->get_child(0));
if(T->get_degree()==2){
Type2 = expression(T->get_child(1));
}else{
Type2 = TypeInteger;
}
if( (Type1 != TypeInteger) or (Type2 != TypeInteger)){
error(T);
cout<< "ARGUMENTS OF '+', '-' etc. MUST BE OF TYPE\
INTEGER" <<endl;
}
returnTypeInteger;
}
Para manejar el nuevo nodo de multiplicacin "*", se debe agregar el siguiente cdigo al
mtodo:
if (nodename == MultNode){
Type1 = expression(T->get_child(0));
Type2 = expression(T->get_child(1));
if( (Type1 != TypeInteger) or (Type2 != TypeInteger)){
error(T);
cout<< "ARGUMENTS OF '*', MUST BE OF TYPE\
INTEGER" <<endl;

}
returnTypeInteger;
}
Modificaciones al generador de cdigo
El cdigo para las expresiones aritmticas es generado en la clase tws::codegenerator, en el
mtodo expression(). A continuacin mostramos el fragmento de este mtodo que genera el
cdigo para el nodo "-":
if (name == MinusNode){
expression(T->get_child(0),CurrLabel);
if (T->get_degree() == 2){
expression(T->get_child(1),NoLabel);
codegen(NoLabel,BOPOP,BMINUS);
dec_framesize();
}else{
codegen(NoLabel,UOPOP,UNEG);
}
}
El cdigo para el nodo "*" debe generarse de la siguiente manera:
if (name == MultNode){
expression(T->get_child(0),CurrLabel);
expression(T->get_child(1),NoLabel);
codegen(NoLabel,BOPOP,BMULT);
dec_framesize();
}
Donde BMULT es la instruccin en ensamblador para la multiplicacin.
Recompilando el traductor
Una vez realizados todos los cambios anteriores en sus respectivos archivos fuente, es
necesario recompilar nuestro traductor. Esto lo hacemos por medio de la utilera make, es
decir, estando ubicados en el directorio tws simplemente tecleamos:
make
Probando la multiplicacin
El ltimo paso es capturar y compilar un programa que utilice la nueva instruccin, por
ejemplo:

{Archivo: mult.tiny }
programmulti:
var factor1,factor2, producto : integer;
begin
factor1 := read;
factor2 := read;
producto = factor1 * factor2;
output(producto)
endmulti.
Recuerda que compilas el programa con la instruccin:
tc mult.tiny

UNIDAD 4 Generacin
cdigo objeto.

del

Competencia especfica de la unidad:


Utilizar un lenguaje de bajo nivel para traducir el cdigo construido a lenguaje mquina
para su ejecucin.

Anlisis del cdigo objeto a crear


La funcin del compilador es traducir un programa escrito en un lenguaje fuente (un
lenguaje de alto nivel) a un programa equivalente en lenguaje mquina del procesador
destino. Este programa est escrito en cdigo objeto. En esta seccin del Mdulo 4 veremos
cmo obtener el cdigo objeto que se genera a partir de algunas instrucciones en lenguaje
fuente.
A manera de recordatorio, a continuacin estn reproducidas las instrucciones en lenguaje
ensamblador de la mquina abstracta. Toda instruccin del lenguaje fuente debe traducirse
a una o varias de estas instrucciones.
Las instrucciones que la mquina abstracta puede ejecutar son las siguientes:
De control del programa

NOP
HALT : Detenerse (halt)

Hacer

nada

De transferencia de datos
LIT v : Cargar (Push) la Literal v en Local frame (Lf) de la memoria
LLV
i
:
Cargar
valor
local
(Load
Local
Value)
i
LGV
i
:
Cargar
valor
global
(Load
Local
Value)
i
SLV i : Almacena valor local i (Store Local Value i)
SGV
i
:
Almacena
valor
global
LLA i : Cargar Direccin Local i (Load Local Address i)
LGA i : Cargar Direccin Global i (Load Global Address i)
POP
n
:
Extrae
n
valores
(Pop
n
DUP
:
DUPlica
el
tope
de
la
SWAP : Intercambia los 2 valores superiores de la pila.

de datos.
en
Lf.
en
Lf.
en Lf.
i.
en Lf.
en Lf.
values).
pila.

Aritmticas y lgicas
UOP i : Operacin unitaria i (Unary Operation i): const X = Pop Lf.
Push
(Unop(i,X))
en
Lf
BOP i : Operacin binaria i: const Xr,Xl = Pop Lf, Pop Lf
Push (Binop(i,Xl,Xr)) en Lf
De control de flujo
CALL
n
:
Llamada
a
una
subrutina.
RTN
n
:
Retorno
de
rutina.
GOTO
L
:
I
<L
Salto
incondicional
a
L
COND L M : I <- if Pop Lf = True # Pop Stack. Si el valor es:
then
L
#
Verdadero,
salta
a
L
else
M
#
Falso,
salta
a
M.
fi
CODE
F
:
Push
F
on
Lf
#
Carga
el
punto
de
entrada.
SOS i : Llamada a la funcin i del sistema operativo
Para las operaciones aritmticas y lgicas tenemos que:
Unop(i,X)
case
UNOT
UNEG
USUCC
UPRED : X-1

i
:
:
:

significa:
of
not(X)
-(X)
X+1

Binop(i,Xl,Xr)
case
BAND
BOR
BPLUS
BMINUS
BMULT
BDIV
BMOD
BEQ
BNE
BLE
BGE
BLT
BGT : Xl > Xr

:
:
:
:
:
:
:
:
:
:
:
:

i
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl
Xl

and
or
+
*
div
mod
=
<>
<=
>=
<

significa:
of
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr
Xr

Llamadas al sistema
Para simplificar el manejo de los dispositivos de Entrada/Salida suponemos que tenemos
disponibles algunas llamadas al sistema operativo, a las cuales se accede por medio de la
instruccin SOS:
SOS i significa:
case
i
TRACEX
:
Trace_Execution
DUMPMEM:
INPUT
:
Push
i
INPUTC
:
Push
Ord(ch)
OUTPUT
:
write
OUTPUTC:
write
OUTPUTL:
EOF
:
then
Push
True
else Push False on Lf

<-

not

on
on
(Pop

if
on

of
TraceExecution
Dump_Memory
readln(i)
Lf
readln(ch)
Lf
Lf)
(Chr(Pop(Lf)))
writeln
eof(input)
Lf

Cdigo generado por el compilador de Tiny

Cuando compilamos un programa de Tiny se generan varios archivos a partir del programa
fuente; estos archivos son:

_CONS: Creado por el analizador semntico, contiene comentarios sobre el


cumplimiento de las restricciones de Tiny.

_CGEN: Creado por el generador de cdigo, con comentarios sobre la traduccin.


Contiene adems la traduccin de las instrucciones del programa fuente,
enriquecido con algunos comentarios tiles para entender mejor el proceso de
traduccin.
_TREE: Creado por el analizador sintctico, contiene el rbol sintctico obtenido a
partir del programa fuente.
_CODE: Creado por el generador de cdigo, contiene el programa objeto, sin
comentarios.

Es importante anotar que estos archivos se sobrescriben cada vez que compilo un programa
en Tiny. Esto es til porque me permite analizar el cdigo generado por el compilador de
Tiny para el ltimo programa traducido, y se evita el uso inmoderado del espacio en disco.
A manera de ejemplo, vamos a ver el cdigo generado por el compilador de Tiny para el
programa de prueba p7, que se muestra a continuacin:
program
begin
output(3)
end x.

x:

Recuerda que para compilar este programa debes ejecutar el programa Cygwin. El
comando para compilar este archivo, esta ubicado en el directorio tiny, es:
./tc tests/p7
En la siguiente figura se muestra el resultado de la compilacin y ejecucin de p7.
Tambin se pueden observar los comandos "cd" para posicionarme en el directorio de tiny:
A continuacin te muestro el contenido del archivo _CGEN creador por el compilador de
Tiny:
<<< CODE
<<< CODE
<<< CODE
<<< CODE
<<< CODE
LIT
Incrementing
SOS
Decrementing
SOS
HALT

GENERATOR >>> Processing Node program ,


GENERATOR >>> Processing Node dclns ,
GENERATOR >>> Processing Node block ,
GENERATOR >>> Processing Node output ,
GENERATOR >>> Processing Node <integer> ,
Framesize

to

Framesize

to

Label
Label
Label
Label
Label

is
is
is
is
is
3
1
OUTPUT
0
OUTPUTL

Recuerda que el generador de cdigo recorre el rbol sintctivo generado por el analizador
sintctico y revisado por el analizador semntico, para ir generando el cdigo objeto.

Observa que el primer nodo analizado es el nodo program, despus el nombre del
programa, que es un nodo decln, posteriormente un nodo block (bloque), cuyo inicio es
indicado por el begin, despus una instruccin de salida (ouput), que recibe como
parmetro un nodo entero (3, en este caso). Esta instruccin output(3) se traduce por las
instrucciones lit 3, sos output y sos outputl. Posteriormente, la instruccin end x.que se
traduce por halt.
El contenido del archivo _CODE es el siguiente:
LIT
SOS
SOS
HALT

3
OUTPUT
OUTPUTL

Fcilmente puede verse que es el mismo cdigo objeto que aparece en el archivo _CGEN,
pero sin comentario alguno. Este archivo nos muestra el contenido del archivo ejecutable
que se "cargar" al intrprete de la mquina abstracta para su ejecucin.

Ejemplo del cdigo generado por el compilador de Tiny para una estructura
selectiva

Para ilustrar el cdigo generado por el compilador de Tiny para una estructura selectiva,
vamos a analizar brevemente el cdigo generado por el siguiente programa:
program
begin
if(
1
end ejemplo2.

ejemplo2:
<=

then

output(1)

else

output(2)

El contenido del archivo _CGEN es el siguiente:


<<< CODE GENERATOR >>> Processing Node program
<<< CODE GENERATOR >>> Processing Node dclns
<<< CODE GENERATOR >>> Processing Node block
<<<
CODE
GENERATOR
>>>
Processing
Node
if
<<<
CODE
GENERATOR
>>>
Processing
Node
<=
<<< CODE GENERATOR >>> Processing Node <integer>
LIT
Incrementing
Framesize
to

Label
Label
Label
,
Label
,
Label
, Label
,
,

is
is
is
is
is
is
1
1

<<< CODE GENERATOR


LIT
Incrementing
BOP
Decrementing
COND
Decrementing
<<< CODE GENERATOR
<<< CODE GENERATOR
L1
Incrementing
SOS
Decrementing
SOS
GOTO
<<< CODE GENERATOR
<<< CODE GENERATOR
L2
Incrementing
SOS
Decrementing
SOS
NOP
L3 HALT

>>>

Processing

Node

Framesize
Framesize
L1
Framesize
>>> Processing Node
>>> Processing Node
LIT
Framesize
Framesize

>>> Processing Node


>>> Processing Node
LIT
Framesize
Framesize

<integer>

Label

is
2
to
2
BLE
to
1
L2
to
0
output , Label is L1
<integer> , Label is L1
1
to
1
OUTPUT
to
0
OUTPUTL
L3
output , Label is L2
<integer> , Label is L2
2
to
1
OUTPUT
to
0
OUTPUTL

Observa el orden del recorrido del rbol sintctivo en el archivo _CGEN:

Node program: Siempre debe iniciar con este nodo.


Node dclns: Y continuar con ste, por el nombre del programa.
Node block: Inicio del begin.
Node if: En este ejemplo, primera instruccin del programa.
Node <= : Operador relacional de la condicin del if.
Node <integer>: Entero 1, etctera.

El cdigo ejecutable de este programa, que es el contenido del archivo _CODE, es el


siguiente:
LIT
LIT
BOP
COND
L1
SOS
SOS
GOTO

L1
LIT

1
2
BLE
L2
1
OUTPUT
OUTPUTL
L3

L2
SOS
SOS
NOP
L3 HALT

LIT

2
OUTPUT
OUTPUTL

Que realiza las siguientes operaciones:


1. Coloca el nmero 1 en el tope de la pila (LIT 1).
2. Coloca el nmero 2 en el tope de la pila (LIT 2).
3. Realiza la operacin binaria (con dos operandos) BOP BLE (Branch if less or equal,
salta si es menor o igual), que compara los dos datos en el tope de la pila.
4. Si la condicin es verdadera (COND L1 L2), salta a L1, si no salta a L2.
5. L1: Coloca el 1 en el tope de la pila (LIT 1) y llama a la funcin output (SOS
OUTPUT) del SO, para desplegar el tope de la pila, llama a outputl (SOS
OUTPUTL), para desplegar un avance de lnea y salta a L3 (GOTO L3), con lo que
termina la ejecucin del programa.
6. L2: Coloca el 2 en el tope de la pila (LIT 2) y llama a la funcin output del SO
(SOS OUTPUT), para desplegar el tope de la pila, llama a outputl (SOS
OUTPUTL), para desplegar un avance de lnea, ejecuta nada (NOP) y termina
(HALT) la ejecucin del programa.

Ejemplo del cdigo generado por el compilador de Tiny para una estructura
repetitiva

Para analizar brevemente el cdigo generado por el compilador de Tiny para una estructura
repetitiva, vamos a revisar brevemente el cdigo generado para el siguiente programa:
program
var
begin
while
begin
output(i);
i
end;
end mientras.

mientras:
i:integer;
i

:=

<=

do

1;

El cdigo generado para este programa es el siguiente:


LIT
L1
LIT
BOP
COND

LGV

L2

0
0
5
BLE
L3

L2
SOS
SOS
LGV
LIT
BOP
SGV
GOTO
L3 HALT

LGV

0
OUTPUT
OUTPUTL
0
1
BPLUS
0
L1

Donde:
1. LIT 0 es la instruccin que utiliza el compilador de Tiny para definir una variable
(en este caso la variable entera i).
2. LGV 0 (que en este ejemplo est etiquetada con L1), es la instruccin para referirse
a esa primera variable y cargarla en el tope de la pila.
3. Posteriormente carga el nmero 5 en el tope de la pila (LIT 5) y compara con la
operacin BOP BLE (Salta si menor o igual). Si el contenido de la variable i es
menor o igual a 5, entonces salta a L2, si no salta a L3 (COND L2 L3).
4. L2: Carga i en el tope de la pila (LGV 0), llama a output para que se despliegue en
pantalla (SOS OUTPUT) y despliega un "avance de lnea" llamando a outputl (SOS
OUTPUTL).
5. Carga i en el tope de la pila (LGV 0) y el 1 en el tope de la pila (LIT 1).
6. Realiza la operacin suma con los dos datos en el tope de la pila y guarda el
resultado en la variable i (BOP BPLUS).
7. Salta incondicionalmente a L1 (GOTO L1), que es la verificacin de la condicin
del while().
8. L3: Termina (halt).
Tomando como base estos ejemplos, realiza ahora la actividad correspondiente a esta
seccin del Mdulo 4: Disear el cdigo que deben generar cada una de las instrucciones
que agregars al compilador de Tiny:

Operacin mdulo.
Operacin autoincremento.
Operacin autodecremento.
Estructura for().
Estructura repeat ... until().

Tarea. Aumentando la gramtica del lenguaje tiny


Instrucciones: Lee detenidamente estas instrucciones y resuelve los ejercicios que se te
indican.
NOTA: En caso de que tengas alguna duda, hazla llegar al facilitador.
Ponderacin: 15%
Actividad 1
Elabora una investigacin documental electrnica y bibliogrfica acerca de la definicin
formal de la gramtica de los lenguajes de programacin, y agrega a la gramtica inicial
de Tiny las definiciones de las instrucciones:

Mdulo
Autoincremento
Autodecremento
Estructura for ()
Estructura repeat ... until

Para realizar esta actividad:


1. Lee detenidamente los contenidos del Tema 4.1, Proposiciones del lenguaje a
implementar.
1. Con base en la lectura y para reafirmar tus conocimientos y poder continuar
tus actividades, contesta las preguntas de investigacin.
2. Cmo se especifica formalmente la operacin mdulo (i%j)?
3. Cmo se especifica formalmente la operacin autoincremento (x++)?
4. Cmo se especifica formalmente la operacin autodecremento (x--)?
5. Cmo se especifica formalmente la estructura for()?
6. Cmo se especifica formalmente la estructura repeat ... until()?
Actividad 2
Disear el cdigo que deben generar cada una de las instrucciones que agregars al
compilador de Tiny:
Mdulo Autoincremento, Autodecremento, Estructura for() , Estructura repeat ... until
Para realizar esta actividad:
1. Lee detenidamente los contenidos del Tema 4.2, Anlisis del cdigo objeto a crear.
2. Con base en la lectura y para reafirmar tus conocimientos y poder continuar tus
actividades, contesta las preguntas de investigacin.
1. Cmo se especifica formalmente la operacin mdulo (i%j)?

2.
3.
4.
5.
f.

Cmo se especifica formalmente la operacin autoincremento (x++)?


Cmo se especifica formalmente la operacin autodecremento (x--)?
Cmo se especifica formalmente la estructura for()?
Cmo se especifica formalmente la estructura repeat ... until()?
Definicin formal de la gramtica de las instrucciones indicadas.

BIBLIOGRAFIA

1. Aho, Sethi, Ullman. Compiladores Principios, tcnicas y herramientasEd.


Addison Wesley.
2. Lemone Karen A. , Fundamentos de compiladores Cmo traducir al
lenguaje de computadora, Ed. Compaa Editorial Continental.
3. Kenneth C. Louden. Construccin de compiladores Principios y prctica.Ed.
Thomson.
4. Martin John, Lenguajes formales y teora de la computacin, ED. Mc Graw
Hill
5. Hopcroft John E., Introduccin a la Teora de Autmatas, Lenguajes y
Computacin, ED. Addison Wesley
6. Guerra Crespo. Hector. Compiladores. Ed. Tecnologica didctica.
7. Ronald Mak. Writing compilers and interpreters. Ed. Wiley Computer
Publishing.
8. Fischer, LeBlanc. Crafting a compiler with C. Ed. Cummings Publishing
Company, Inc.
9. Salas Parrilla, Jess. Sistemas Operativos y Compiladores. McGraw Hill.
10. Beck. Software de Sistemas, Introduccin a la programacin de Sistemas.
Addison-Wesley Iberoamericana.
11. Teufel, Schmidt, Teufel. Compiladores Conceptos Fundamentales.
Addison-Wesley Iberoamericana.
12. C. Louden, Kenneth. Lenguajes de programacin Principios y prctica.
Thomson.
13. Levine Gutirrez, Guillermo. Computacin y programacin moderna
Perspectiva integral de la informtica. Pearson Educacin.
14. Abel, Peter. Lenguaje ensamblador y programacin para PC IBM y
compatibles. Pearson Educacin.
15. Mak, Ronald. Writing compilers and interpreters. Wiley Computer
Publishing.
16. Pittman, Thomas, Peters, James. The art of compiler design Theory and
practice. Prentice Hall.
17. Temblay & Sorenson. Compilers Writing. Mc Graw Hill.
18. R. Levine, John; Mason, Tony, Brown, Doug. Lex y Yacc. O'Reilly &

Associates.
19. The Lex & Yacc Page, 3-mar-04, 12:45, http://dinosaur.compilertools.net
20. A compact guide to lex & Yacc, Thomas Niemann, 3-Mar-04, 12:50,
http://epaperpress.com/lexandyacc
21. Lex & Yacc HOWTO, Bert Hubert (PowerDNS.COM.BV), 3-Mar-04, 12:55,
http://ds9a.nl/lex_yacc
22. Flex, 3-mar-04, 13:02, http://www.gnu.org/software/flex/flex.html
23. Compiler construction using flex and Bison, Anthony Aaby, 3-mar-04, 13:05,
http://cs.wwc.edu/aabyan/464/BooK/
24. Flex, version 2.5 A fast scanner generator, Edition 2.5, March 1995, Vern
Paxson, 3-mar-04, 13:10,
http://www.cs.princelon.edu/appel/modern/c/software/flex/flex_toc.html
25. Bison. The Yacc-compatible Parser Generator, November 1995, Bison
Version 1.5, Charles Donnelly and Richard Stallman, 3-mar-04, 13:10,
http://www.cs.princelon.edu/appel/modern/c/software/bison/bison_toc
.html, 13/dic/2009
26. Bison. http://3d2f.com/programs/30-170-microprocessor-emulator-andassemblerdownload.shtml, 13/dic/2009
27. 2/Ago/2005 ,Microprocessor Emulator and Assembler 3.10-k,
http://software.intel.com/en-us/articles/all/1/, 24/feb/2010
28. Intel, 31/dic/2009, Intel Software Development EmulatorBottom of Form,
http://software.intel.com/enus/articles/intelsoftwaredevelopmentemulator/,
24/feb/2010

Anda mungkin juga menyukai