Está en la página 1de 56

COMPILADORES

Revisión General de Temas tratados


durante el cursado de la Materia
Fecha de Exposición: 14 de Junio del 2010
Profesora: Ing. Reinoso
Alumnas:
CORIMAYO, Carina Melisa
MAMANI, Gabriela
NOBLEGA, Valeria Laura

1
¿Qué es un Compilador?
Traductor: Un Traductor es un programa que toma como entrada un texto
escrito en un lenguaje, llamado fuente y da como salida otro texto en un
lenguaje, denominado objeto.

Lenguaje Lenguaje
Traductor
Fuente Objeto

Tipos de Compilación:
Compilador: es un traductor que convierte un texto escrito en un lenguaje de
alto nivel a un lenguaje de bajo nivel (código máquina).
Ensamblador: es un lenguaje de bajo nivel, donde cada sentencia del
lenguaje fuente se traduce a una instrucción en código máquina.
Intérprete: no genera código objeto, analiza y ejecuta directamente cada
proposición del código fuente.
Preprocesador: procesan un texto fuente modificándolo en cierta forma
previamente a la compilación 2
Compilador:
Un compilador presenta las siguientes características:
Programa que lee un programa fuente en un lenguaje, lo
traduce a un programa equivalente en otro lenguaje además da
mensajes de error y lleva a cabo determinadas correcciones y
puede optimizar el código generado.

Programa Programa
Compilador
Fuente Objeto

Error

3
Interprete:
Es un programa que lee un programa escrito en un lenguaje de
programación y produce el resultado de ejecutar tal programa.

Programa
Intérprete Salida
Fuente

Datos

4
Compilador vs. Intérprete
 Ventajas Compilador:
* Se compila una vez, se ejecuta muchas veces.
* Produce un código optimizado.
* La ejecución del programa objeto es mucho mas rápida que si se interpreta
el programa fuente.
* El compilador tiene una visión global del programa, por lo que la
información de mensajes de error es más detallada.
* Mayor consumo de memoria
 Ventajas Intérprete:
* Un Intérprete necesita menos memoria que un compilador.
* Permiten una mayor interactividad con el código en tiempo de desarrollo, lo
que facilita la búsqueda de errores.
* En algunos lenguajes está permitido es frecuente añadir código según se
ejecuta otro código.
* Menor consumo de memoria
5
Contexto de un Compilador
En el Proceso un programa fuente puede
Programa Fuente
estar dividido en módulos almacenados en ficheros
diferentes, la tarea de recopilar el código
PREPROCESADOR almacenado en estos ficheros pueden ser
encomendados a un preprocesador.
Programa Fuente Final
En el Ensamblador muchos compiladores
proporcionan el programa final en lenguaje para
COMPILADOR
poder obtener un programa ejecutable es preciso
Código Ensamblador
ensamblar este programa final con un ensamblador
convencional.
Esta herramienta toma el código máquina
ENSAMBLADOR
relocalizable de los distintos objetos compilados y
LIBRERIAS
Código Objeto en Código de librerías modifica las direcciones relocalizables
Máquina para situarlos a los valores absolutos adecuados y
ENLAZADOR
crear el programa ejecutable

Programa Final

6
Compilación
Existe 2 partes importantes en la compilación:

Compilación

Análisis Síntesis

Léxico Sintáctico Semántico Generación de


“Tokens” “Intrucciones” “significado” Código

En la etapa de análisis se divide el programa fuente en sus piezas


constituyentes y crea una representación intermedia del mismo.
En la etapa de síntesis se construye el programa destino deseado a partir
de una descripción en un lenguaje de representación intermedia.
7
Fases de un Compilador
Programa Fuente

Analizador
Léxico Independencia Física

Analizador
Sintáctico

Analizador
Semático
Administrador de la Generador de
Tabla de Símbolos Generador de Código
Código Intermedio

Optimizador de Dependencia Física


Código

Generador de
Código

8
Programa Objeto
Análisis Léxico
Definición:
El analizador léxico o scanner, trasforma el texto fuente en una secuencia
ordenada de elementos léxicamente válidos (tokens).

Tipos de Tokens:
 Específicos:
•Palabras Reservadas
•Separadores División de Componentes
•Operadores Programa Fuente Analizador Léxicos
Analizador
 No Específicos Léxico Sintáctico
•Identificadores
•Constantes
•Etiquetas Tabla de
 Estructura Simbolos
•Tipo
•Lexema

9
Análisis Léxico
 Al iniciarse el proceso de compilación el código objeto es un flujo de caracteres que el analizador léxico debe reconocer y presentarlos en una
representación mas útil para el analizador sintáctico. Las funciones características del analizador léxico son:
 Eliminar espacios
 Ignorar comentarios
 Tratar con la tabla de símbolos
 Reconocer identificadores y palabra reservadas
 Manejar el fichero fuente
 Contabilizar posición de tokens
 Procesar macros, constantes, includes…
 Generar tokens bajo demanda del analizador sintáctico

Pasos para especificar un analizador léxico:

 Estructurar la colección de tokens


 Identificar la colección de tokens
 Describir el lenguaje como expresiones regulares
 Especificar un diagrama de transición
 Traducir el diagrama a una tabla de transición.

10
Análisis Sintáctico
Definición:
El Analizador Sintáctico o parser recibe los tokens y comprueba su
ordenación correcta. Genera un árbol sintáctico.
Siguiente Token()
Programa Árbol
Fuente Analizador Analizador Sintáctico
TOKENS
Lexicográfico Sintáctico

Tabla de
Simbolos

Tiene como objetivo analizar la secuencia de tokens y comprobar que son


correctas sintácticamente. A partir de una secuencia de tokens el analizador
sintáctico nos devuelve si la secuencia es correcta o no sintácticamente,
también nos devuelve el orden en el que hay que aplicar las producciones de la
gramática para obtener la secuencia de entrada (árbol sintáctico).
11
Análisis Sintáctico
Función:

Comprobar el orden en el que llegan los tokens.


Construir una representación del programa fuente.
Si es sintácticamente incorrecto generara error

Criterios de diseño del Analizador Sintáctico:

Eficiencia: El tiempo de análisis debe ser proporcional al tamaño del


programa analizado
Predictivo: Al detectar algún error debe determinar que quiso decir.
Sin Retroceso: Al ejecutar una tarea no vuelve para atrás.

12
Analizador Semántico
Definición:

El analizador semántico comprueba que el árbol sintáctico es


semánticamente válido. Revisa el programa fuente para comprobar que
las reglas semánticas se cumplen. Genera un árbol semántico o
etiquetado.

Validación:

 Tipos de resultados intermedios


 Conversiones implícitas de tipo
 Sobrecarga de operadores

13
Tabla de Símbolos y Gestión de Errores
 Tabla de Símbolo: Es el medio de almacenamiento de toda la
información referente a las variables y objetos en general del programa
que se está compilando.

 Gestión de Errores: Están incluidas en cada uno de los procesos de


compilación (análisis lexicográfico, sintáctico y semántico), y se
encargan de informar de los errores que encuentran en texto fuente,
después de detectar un error cada fase debe tratar de alguna forma
ese error para poder continuar la compilación.

14
Tipos de Analizadores Sintácticos
 Analizador Descendente:
Se construye el árbol de análisis sintáctico partiendo del símbolo inicial y aplicando las producciones
mediante derivaciones por la izquierda, el símbolo a expandir es el que este más a la izquierda.

Ejemplo:
G=({+,*, ID, (, )}, {E, T, P}, E, P)
P={ E:=E+T | T; T:=T*P | P; P:= ID | ( E ) }
Frase
Analizador Ascendente: ID + ( ID * ID )
Se construye el árbol de análisis sintáctico partiendo de la frase a reconocer y
aplicando las producciones mediante reducciones hasta llegar a símbolo inicial de
la gramática.

Ejemplo:
G=({+,*, ID, (, )}, {E, T, P}, E, P)
P={ E:=E+T | T; T:=T*P | P; P:= ID | ( E ) }
Frase
ID + ( ID * ID )
15
Tipos de Analizadores Sintácticos
L L (1)

Es Predictivo
Descendentes Se aplican las producciones por izquierda

El orden de lectura de la entrada es de izquierda a derecha

S L R (1)

Tipos de Es Predictivo
Analizadores Se aplican las producciones por derecha

El orden de lectura de la entrada es de izquierda a derecha

Simple
L R (1)

Es Predictivo
Ascendentes Se aplican las producciones por derecha

El orden de lectura de la entrada es de izquierda a derecha


LA L R (1)

Es Predictivo
Se aplican las producciones por derecha

El orden de lectura de la entrada es de izquierda a derecha


16
Look a Head: Al construir el analizador va a tratar de mirar por adelantado el texto para
comprenderlo y hacer mas sencillo y mejores estados
Rutinas de Recuperación de Error…
 Objetivo del Manejador de Errores:
El analizador sintáctico informará de cualquier error de sintaxis de
manera inteligible. A su vez, deberá recuperarse de ellos para poder
continuar procesando el resto de su entrada.

 Objetivo de la Rutina de Recuperación de


Errores:
 Localizar el error
 Corregir el error
 Recuperar
 Continuar el análisis

17
Rutinas de Recuperación de Error
Estrategias :
 Modo de Pánico
 Método más sencillo de implementar
 Utilizado por la mayoría de los analizadores sintácticos
 Su sencillez está garantizada contra lazos infinitos

A Nivel de Fase
 Puede corregir supuestamente cualquier error
 El diseñador se encarga de elegir la correcion a utilizar
 Puede caer en lazos infinitos

 Producción de Error
 Informa de los errores que podría corregir
 No detecta todos los errores solo aquellos predeterminados en su diseño

Corrección Global
 Tienen interés desde un punto de vista teórico
 Se basa en el metodo de minima distancia de corrección de error

18
Analizadores Descendentes
Recursivos
 Características:

 Producen retrocesos
 Prueban todas las posibilidades con un algoritmo de
backtracking.
 Fáciles de implementar.

 Analizadores predictivos:

 Utilizan información de la cadena de entrada para predecir qué


 subcadena lleva al éxito.

 Producen los árboles de análisis desde el axioma hasta


llegar a la frase (construcción de forma explícita)

19
Analizador LL(1)
RUTINA DE
RECUPERACIÓN DE
ERRORES

ENTRADA ANALIZADOR SALIDA


LL(1)
COMPONENTES LÉXICOS El que crea el árbol y lo analiza OK, ERROR

TABLA DE ANÁLISIS
MOTOR DEL PILA DE ANÁLISIS
ELEMENTOS DE UN ANALIZADOR LRANALIZADOR

Entrada: cadena de componente obtenida del análizador léxico


Salida: representación implícita del árbol de análisis sintáctico que va ha ser una lista de todas
las producciones aplicadas.
Pila: simula la construcción del árbol de análisis y sus derivaciones.
Tabla de análisis: en las columnas van los símbolos terminales, en las filas los no terminales y
en la intersección de las celdas se encuentra la producción a aplicar
Recuperación de error: métodos utilizados por el analizador sintáctico que permiten continuar
con su funciones 20
Tabla de Análisis Sintáctico
Pasos para la construcción de la Tabla:

1) Obtener:
1) Conjunto Primero: es el conjunto formado TABLA LL(1)

por todos los símbolos terminales que Term 1 Term 2 ... ... Term n
inician las cadenas y que se derivan del no No Terminal 1
terminal para el cual estamos calculando el No Terminal 2
conjunto .
2) Conjunto Siguiente: es el conjunto formado .

por todos los símbolos terminales que .

cumplen con las reglas para el cálculo de No Terminal m

este conjunto. En donde en cada celda va una producción o un error

Basados en las reglas para la obtención de los


mismos

2) Elaboración de la Tabla

21
Conjunto Primero: Reglas
 Si x es un Terminal y esta al inicio de la producción agregar al
Conj. Primero del no terminal para el que se calcula el Conj.
Primero ese no terminal

Prim(NT)={x}

 Si el No terminal produce λ añadir al Conj. Primero del no


terminal para el que se calcula el Conj. Primero ese

Prim(NT)={λ}

 Si NT ->UYZ, donde U es un no terminal añadir al Conj. Primero


del no terminal para el que se calcula el Conj. Primero de ese
No Terminal
Prim(NT)={Prim(U)}

22
Conjunto Siguiente: Reglas
Se considera el lado derecho de las producciones donde
aparezca el no terminal en cuestión y las veces en que este
aparezca:

 Si NT es el símbolo inicial de la gramática entonces al Conj.


Siguiente de ese simbolo agregar el símbolo $
Sig(NT que es axiona)={$}

 Si A deriva BCD y C es el no terminal en cuestión y D deriva en


λ o es λ entonces al Conj. Siguiente de A añadir el Conj. Sig de
A excepto λ
Sig(NT)={Sig (A)}
 Si A deriva BCD y C es el no terminal en cuestión y D NO
deriva en λ entonces al Conj. Siguiente de A añadir el Conj. Sig
de A unido el Conj de Primero de D
Sig(NT)={Sig (A) U Prim (D)}
23
Elaboración de la Tabla
 Se considerará en primer lugar los símbolos
obtenidos en el Conj. Primero, la intersección de este
símbolo junto con el no terminal asociado al Conj
determinará la producción aplicada para este caso.
 Si el Conj. Primero contiene algún símbolo lamba
entonces se considerarán los Conj Siguiente y el
mismo no terminal pero en este caso la intersección
contendrá la producción derivada en lambda.
 Una vez que se han contemplado todos los Conj.
Primeros se procede a completar la tabla con error el
las celdas vacías.

24
Algoritmo del Analizador LL(1)
 Se carga la pila con el símbolo final de la cadena y el axioma y en la cima
podemos tener:
a) un no terminal en cuyo caso se consulta a la tabla entrando a la misma
con:

Tabla(NT, componente léxico)


Si en ella existe un producción se saca este no terminal y se lo reemplaza
por el lado derecho de la producción y en el caso de que haya un error
podemos afirmar que la frase no pertenece a la gramática y se acude a la
rutina de recuperación de error.
b) si en la cima de la pila tenemos un terminal y este coincide con la
entrada avanzamos en la secuencia y se saca de la pila. Si no se lo
encuentra entonces tenemos un error con lo que la frase no pertenece a la
gramática
 Todo esto se repite hasta que la pila quede vacía
 Si la pila esta vacía y la entrada también entonces se ha reconocido la
frase sino se ha encontrado un error, aunque este error no suele darse ya
que este analizador lo detecta antes.

25
Rutina de Recuperación de Errores
en el LL(1)
 Modo de Pánico:
 Se crea un conjunto de sincronización (formado por
componentes léxicos que podrían recuperar el análisis)
 En el caso de error:
 Se omite el error
 Desecha el componente hasta que encuentre uno del conjunto
 Se eliminan los elementos de la pila hasta que coincide con
la entrada y pueda proseguir el análisis y puede ocurrir que
 Si se encuentra el análisis se recupera u sigue de forma
normal
 Sino no hay recuperación

Inconveniente de la Rutina: trabaja de forma independiente a la


pila de entrada.

26
Analizador Sintáctico Ascendente LR
 Características

 No existe el retroceso
 Esta dirigido por tablas
 Su acción la decide con leer un componente
léxico (por ello se dice que es predictivo)
 Se basa en el Pivote o Mango

27
Método del Pivote o Mango…
 Primero encontrar en la pila de Análisis un
Prefijo viable

 Es la forma de frase
 Símbolo final no coincide con el final de la
parte derecha de una producción de la
gramática
 El prefijo contiene todos los símbolo de parte
derecha de la producción.

28
Método del Pivote o Mango…
En cada forma de frase detectamos un mango,
una pareja
[Producción, posición de la forma de frase]
Indica a partir de que punto es
aplicable el mango en la producción

S  aAcBe  aAcde  aAbcde  abbcde


[2,2]
[2,2]
[2,2]*
[1,1] [3,2]*
[3,2]

[4,4]*

29
Analizador LR
 Elementos de un analizador

RUTINA DE
RECUPERACIÓN DE
ERRORES

ANALIZADOR SALIDA
ENTRADA
Lista de Producciones o
COMPONENTES LÉXICOS LR Representación implicita del árbol

PILA DE ANÁLISIS
TABLA LR
(símbolo, estado)

30
Tabla LR
ACCION Ir A

E
S
T
A Terminales No Terminales
D
O
S

31
Tabla de Simbolo LR
 Acción
 dn: Desplazar el símbolo de la entrada la pila
desplazar
 rn: Reducción por la producción n
 Aceptar: esta acción detecta el final del
análisis e indica que acepta la frase ($)
 Error: detecta el error sintactico
 Ir A
 n: desplazar a la pila el estado n
 Error: error detectado

32
Construcción del Analizador LR (1)

1. Construir el autómata LR(0)


2. Construir la tabla LR
3. Se compacta la tabla cuando se puede
(número de estado tiene que ser lo menor
posible, + rápido)

33
Construcción del Autómata LR(0)

 El LR(0) tiene, en primer lugar los estados

Estado

Núcleo
Estados
LR(0)
Resto

34
Algoritmo para la construcción del
Autómata
1. Ampliar la Gramática S añadiendo S’S
2. Se construye el núcleo del estado 0: S’S
a) Para cada núcleo n: se fijan los símbolos cerradura, (no terminal a al
derecha de un punto en AA·Bc, B seria el símbolo cerradura)
b) Para cada símbolo de cerradura se introduce en un nuevo estado.
3. Para cada nuevo elemento se repite a y b, hasta que no se puedan
introducir nuevos elementos
4. Para cada estado cerrado nuevo (n) construyó los nucleos de nuevos
estados mediante transiciones
a) Realizo una particion del estado con una parte para cada simbolo con
estado t y otra parte con los elemtos LR(0)
b) Para cada parte de la particion correspondiente a t, se crea un nuevo
nucleo, desplazando el punto de la derecha
c) Si n es nucleo nuevo se traza una arista de n a m etiquetado con t .

35
Ejemplo
G=({a,b}, {S,B},S,P) para
P={ 0. S’S
1. SBB 1
2. BaB S’S
3. Bb}
S
0 2 5
B SBB
S’S B SBB
BaB
SBB
Bb
BaB a
a
Bb
b 3 B 6
b SaB SaB
BaB
Bb
b a

4
Bb
36
Analizadores Ascendentes(LR, LALR)
 Algunos problemas no se pueden resolver de forma
descendente ya que no es tán fácil quitar la
ambigüedad. En algunos casos es más fácil demostrar
algo ya existente.
 Analizador ascendente
 El analizador trata de reducir la cadena de entrada w al
símbolo inicial S. En un proceso que recorre el árbol de
derivación en sentido inverso que se llama reducción.
 No sólo es necesario una gramática que no presente
ambigüedades sino que también tenga el valor de k
más pequeño.

37
Analizadores Ascendentes(LR, LALR)
SLR(1): aplica las búsquedas hacia delante después de
construir el autómata de elementos LR(0)
– Mismo autómata que LR(0), sólo cambia la
construcción de la tabla.
– El autómata ignora la búsqueda hacia delante.
• La capacidad de los métodos LR(k) radica en la
construcción de un autómata que integra las
búsquedas hacia delante.
• Se utilizan nuevos elementos, denominados LR(1).

38
Análisis sintáctico LR(1) simple o
SLR(1)
Capaz de analizar prácticamente todas las construcciones
que se presentan en un lenguaje
 No obstante, hay situaciones en las que no sirve y por
tanto no es analizable.
 Un estado puede tener tanto reducciones como
desplazamientos
 Utiliza el autómata finito determinista del LR(0) con mayor
potencia, impleando el token siguiente en la entrada para
guiar sus acciones:
 Consulta el token de entrada antes de cada
desplazamiento para asegurar que existe una transición
adecuada
 Utiliza el conjunto siguiente de un no terminal para decidir
si se debería realizar una reducción o no.
39
Análisis sintáctico LR(1) simple o
SLR(1)
• Una gramática es SLR(1) si es posible construir una
tabla de análisis SLR sin entradas múltiples.
• Gramática LR(1) – No es usada en la práctica debido
al gran número de estados que produce, sino que se
utiliza una gramática simplificada, LALR(1); más
potente que LR(0) pero menos que LR(1). .
• Una gramática es LALR(1) si no incluye conflictos de
análisis. Es la más importante y la que implementan
la mayoría de los generadores como CUP, Bison, y
Yacc reconocen gramáticas LALR(1).
 
40
Gramáticas de Atributos
 Una gramática de atributos es una gramática libre de contexto
cuyos símbolos pueden tener asociados atributos y las
producciones pueden tener asociadas reglas de evaluación de los
atributos

 En la creación de compiladores se utilizan ecuaciones de atributos


o reglas semánticas como método para expresar la relación entre el
cálculo de los atributos y las reglas del lenguaje.

 Cada producción (regla sintáctica) tiene asociada una acción


semántica que se aplica cuando se realiza una reducción en el
análisis sintáctico ascendente.

41
Tipos de Atributos

 Sintetizados: Su valor se calcula en función de


atributos de nodos hijos en el árbol de análisis
sintáctico.

 Heredados: Para un hijo se calculan a través de


los atributos del padre y hermanos en el árbol
de análisis sintáctico.

42
Sistema de Tipos
 Sistema de tipos: reglas de un lenguaje que
permiten asignar tipos a las distintas partes de un
programa y verificar su corrección

 Formado por las definiciones y reglas que permiten


comprobar el dominio de un identificador, y en qué
contextos puede ser usado.

 Cada lenguaje tiene un sistema de tipos propio,


aunque puede variar de una a otra implementación.

 La comprobación de tipos es parte del análisis


semántico.

43
Sistema de Tipos
 Funciones principales
– Inferencia de tipos: calcular y mantener la información sobre los tipos de
datos.
– Verificación de tipo: asegurar que las partes de un programa tienen
sentido según las reglas de tipo del lenguaje.

• La información de tipos puede ser estática o dinámica:


– LISP, CAML o Smalltalk utilizan información de tipos dinámica.
– En ADA, Pascal o C la información de tipos es estática.
– También puede ser una combinación de ambas formas.

• Cuantas más comprobaciones puedan realizarse en la fase de


compilación, menos tendrán que realizarse durante la ejecución
– Mayor eficiencia del programa objeto.

44
Sistema de Tipos
• Es parte de la comprobación de tipos:
– Conversión de tipos explícita: transformación del tipo de una expresión
con un propósito determinado.
– Coerción: conversión de tipos que realiza de forma implícita el
compilador.

• Conversión de tipos explícita: el programador indica el tipo destino.


– Funciona como una llamada a función: recibe un tipo y devuelve otro.

• Conversión de tipos implícita: el compilador convierte automáticamente


elementos de un tipo en elementos de otro.
– La conversión se lleva a cabo en la acción semántica de la regla donde
se realiza.

45
Sistema de Tipos
• Comprobador de tipos seguro: Durante la compilación
(comprobación estática) detecta todos los posibles
errores de tipo.

• Lenguaje fuertemente tipado: Si un fragmento de


código compila es que no se van a producir errores
de tipo.

• En la práctica, ningún lenguaje es tan fuertemente


tipado que permita una completa comprobación
estática.

46
Sistema de Tipos
 Información de tipos dinámica: El compilador debe
generar código que realice la inferencia y verificación
de tipos durante la ejecución del programa que se
está compilando.

• Información de tipos estática:


– Se utiliza para verificar la exactitud del programa antes
de la ejecución.
– Permite determinar la asignación de memoria
necesaria para cada variable.

47
Sistema de Tipos
 Un lenguaje de programación contiene un conjunto
de tipos predefinido denominados tipos simples

 Algunos lenguajes permiten definir nuevos tipos


simples: enumerado, subrango.

 Todos los lenguajes permiten crear nuevos tipos


complejos a partir de otros más simples mediante
constructores de tipos:

 Matrices, productos, registros, punteros, funciones, …


 En Pascal: array, set, record, ...
 En C++: struct, class, union, ...
48
Generación de Código Intermedio
 Después de los análisis sintácticos y
semánticos, algunos compiladores generan
una representación intermedia explicita del
programa fuente. Se puede considerar esta
representación intermedia como un programa
para una maquina abstracta. Esta
representación intermedia debe tener dos
propiedades importantes, debe ser fácil de
producir y fácil de traducir al programa objeto.

49
Generación de Código Intermedio

 El código intermedió es particularmente


utilizado cuando el objetivo de compilador es
producir código muy eficiente, ya que para
hacerlo así se requiere una cantidad
importante del análisis de las propiedades del
código objetivo, y esto se facilita mediante el
uso del código intermedio.

50
Generación de Código Intermedio
 El código intermedio también puede ser útil al hacer
que un compilador sea mas fácilmente re dirigible: si
el código intermedio es hasta cierto punto
independiente de la maquina objetivo, entonces
genera código para una maquina objetivo diferente
solo requiere volver a escribir el traductor de código
intermedio a código objetivo, y por lo regular esto es
mas fácil que volver a escribir todo un generador de
código.

51
Generación de Código Intermedio
La representación intermedia tiene varias propiedades.

 Primera cada Instrucción de tres direcciones tiene a lo sumo un


operador, además de la asignación. Por tanto, cuando se
generan esas instrucciones, el compilador tiene que decidir el
orden en que deben efectuarse las operaciones; la
multiplicación precede ala adición.
 Segunda, el compilador debe generar un nombre temporal para
guardar los valores calculados por cada instrucción.
 Tercera, algunas instrucciones de "tres direcciones“ tienen
menos de tres operandos, por ejemplo, la primera y la última
instrucción.

52
Lenguajes Intermedios
 Árboles sintácticos abstractos (ASA)

 El código se representa en forma de árbol


donde
-Cada nodo no terminal representa un operador
-Cada nodo terminal representa un operando

 Más próximo al lenguaje fuente

53
Lenguajes Intermedios
 Grafos dirigidos acíclicos (GDA)
 El código se representa en forma de grafo
-Cada nodo no terminal representa un operador
-Cada nodo terminal representa un operando
-Se reutilizan los nodos
 Más próximo al lenguaje fuente

54
Optimización de Código
 La fase de optimización de código trata de mejorar el código
intermedio, de modo que resulte un código de Maquina más
rápido de ejecutar. Algunas optimizaciones son triviales.

 Hay mucha variación en la cantidad de optimización de código


que ejecutan los distintos compiladores, una parte significativa
del tiempo del compilador se ocupa en esta fase. Sin embargo,
hay optimizaciones sencillas que mejoran sensiblemente el
tiempo de ejecución del programa objeto sin retardar
demasiado la compilación

55
Generación de Código

 La fase final de un compilador es la generación de


código objeto, que por lo general consiste en código
máquina relocalizable o código ensamblador. Las
posiciones de memoria se seleccionan para cada
una de las variables usadas por el programa.
Después cada una de las instrucciones intermedias
se traduce a una secuencia de instrucciones de
máquina que ejecutan la misma tarea. Un aspecto
decisivo es la asignación de variables a registros.

56

También podría gustarte