Está en la página 1de 35

Semana 1: Introducción

MG. GÓMEZ AVILA, JOSÉ


Presentación…
Mg. Gómez Avila José
3 Unidades de Aprendizaje
◦ 1 Proyecto de Curso
◦ 3 Exámenes
◦ Teórico
◦ Laboratorio (2)
◦ Exposición Proyecto

Correo:
◦ jgomez@steperu.com
◦ jgomez@unitru.edu.pe

Horario de Consultas
◦ Jueves 4 – 5 pm

MG. GÓMEZ AVILA, JOSÉ


Autómata
Compiladores
Es un compilador es un traductor especial que toma un lenguaje de alto nivel, y lo traduce a
una representación de bajo nivel que el computador puede ejecutar en última instancia.

Los compiladores que hacen la traducción de un lenguaje de alto nivel a lenguaje


ensamblador. El ensamblador puede entonces finalizar el proceso de traducción y el
sistema enlazador/cargador puede preparar el programa para su ejecución.

Lenguaje de alto nivel Compilador Programa de bajo nivel


Adicional…
PROGRAMAS RELACIONADOS CON LOS COMPILADORES
INTÉRPRETES
Un intérprete es un traductor de lenguaje, igual que un compilador, pero difiere de éste en que ejecuta el
programa fuente inmediatamente, en vez de generar un código objeto que se ejecuta después de que se
completa la traducción.
Cualquier lenguaje de programación se puede interpretar o compilar, pero se puede preferir un intérprete a un
compilador dependiendo del Lenguaje que se esté usando y de la situación en la cual se presenta la traducción.
Es preferible usar un compilador si lo que importa es la velocidad de ejecución, ya que el código objeto
compilado es siempre más rápido que el código fuente interpretado, en ocasiones hasta por un factor de 10 o
más.
Ejemplo: LISP, BASIC, etc.
ENSAMBLADORES
Un ensamblador es un traductor para el lenguaje ensamblador de una computadora en particular.
El lenguaje ensamblador es una forma simbólica del lenguaje de máquina de la computadora y es particularmente
fácil de traducir.
En ocasiones un compilador generará lenguaje ensamblador como su lenguaje objetivo y dependerá entonces de un
ensamblador para terminar la traducción a código objeto.
LIGADORES
Los compiladores como los ensambladores a menudo dependen de un programa conocido como ligador, el cual
recopila el código que se compila o ensambla por separado en diferentes archivos objeto, a un archivo que es
directamente ejecutable.
Se puede hacerse una distinción entre código objeto (código de máquina que todavía no se ha ligado) y código de
máquina ejecutable. Un ligador también conecta un programa objeto con el código de funciones de librerías
estándar, así como con recursos suministrados por el sistema operativo de la computadora, tales como asignadores
de memoria y dispositivos de entrada y salida.
Los ligadores ahora realizan la tarea que originalmente era una de las principales actividades de un compilador
(compilador: construir mediante la recopilación o compilación de fuentes diferentes)
CARGADORES
Un compilador, ensamblador o ligador produce un código que todavía no está completamente organizado y
Iisto para ejecutarse, pero cuyas principales referencias de memoria se hacen relativas a una localidad de
arranque indeterminada que puede estar en cualquier sitio de la memoria.
Por tanto el código es relocalizable y un cargador resolverá tantas las direcciones relocalizables relativas a una
dirección base, o de inicio, dada.
El uso de un cargador hace más flexible el código ejecutable, pero el proceso de carga con frecuencia ocurre en
segundo plano (como parte del entorno operacional) o conjuntamente con el ligado.
PREPROCESADORES
Un preprocesador es un programa separado que es invocado por el compilador antes de que comience la
traducción real.
Un preprocesador de este tipo puede eliminar los comentarios, incluir otros archivos y ejecutar sustituciones
de macro (una macro es una descripción abreviada de una secuencia repetida de texto).
Los preprocesadores pueden ser requeridos por el lenguaje (como en C) o pueden ser agregados posteriores
que proporcionen facilidades adicionales.
EDITORES
Los compiladores por lo regular aceptan programas fuente escritos utilizando cualquier editor que pueda
producir un archivo estándar, tal como un archivo ASCII.
Los compiladores han sido integrados junto con editores y otros programas en un ambiente de desarrollo
interactivo o IDE.
Un editor, mientras que aún produce archivos estándar, puede ser orientado hacia el formato o estructura del
lenguaje de programación en cuestión. Estos editores se denominan basados en estructura y ya incluyen
algunas de las operaciones de un compilador.
Ejemplo, el editor puede informar al programador de los errores a medida que el programa se vaya escribiendo
en lugar de hacerlo cuando está compilado.
El compilador y sus programas acompañantes también pueden llamarse desde el editor, de modo que el
programador pueda ejecutar el programa sin tener que abandonar el editor
DEPURADORES
Un depurador es un programa que puede utilizarse para determinar los errores de ejecución en un programa
compilado. A menudo está integrado con un compilador en un IDE.
La ejecución de un programa con un depurador se diferencia de la ejecución directa en que el depurador se
mantiene al tanto de la mayoría o la totalidad de la información sobre el código fuente, tal como los números
de línea y los nombres de las variables y procedimientos.
También puede detener la ejecución en ubicaciones previamente especificadas denominadas puntos de
ruptura, además de proporcionar información de cuáles funciones se han invocado y cuáles son Los valores
actuales de las variables.
Para efectuar estas funciones el compilador debe suministrar al depurador la información simbólica
apropiada, lo cual en ocasiones puede ser difícil, en especial en un compilador que intente optimizar el código
objeto.
PERFILADORES
Un perfilador es un programa que recolecta estadísticas sobre el comportamiento de un programa objeto
durante la ejecución.
Las estadísticas típicas que pueden ser de interés para el programador son el número de veces que se llama
cada procedimiento y el porcentaje de tiempo de ejecución que se ocupa en cada uno de ellos.
Las estadísticas pueden ser muy útiles para ayudar al programador a mejorar la velocidad de ejecución del
programa.
A veces el compilador utilizará incluso la salida del perfilador para mejorar de manera automática el código
objeto sin la intervención del programador
FASES DEL COMPILADOR
El proceso de compilación puede describirse como una secuencia de fases seriadas que comienzan con el
análisis lexicográfico y finalizan con la generación de código, con el manejo de tablas, módulos de error y de
E/S que interactúan con más de una fase:

Análisis Preparación para


Análisis sintáctico
lexicográfico Análisis semántico Optimización la generación del
(gramatical)
(rastreo) código

Generación del
código
Manejo de tabla
• Tabla de símbolos
• Tabla de literales Manejo de
errores
E/S
• Tabla de ciclos iterativos
• Tabla de representación
intermedia
Por ejemplo: muchos compiladores son “controlados por el analizador gramatical” (parsing) que significa que
el analizador sintáctico recurre al analizador lexicográfico, en vez de que el analizador lexicográfico complete la
tarea antes de que comience el analizador sintáctico.

Esquema:
Manejo de tabla
• Tabla de símbolos
• Tabla de literales
• Tabla de ciclos iterativos
Análisis • Tabla de representación intermedia
sintáctico
Análisis (gramatical)
Manejo de Preparación para
Errores
lexicográfico
a la generación
(rastreo)
Análisis E/S
semántico
Generación
Optimización del código
EJEMPLO: Un problema simple de compilador
Compilador ?

Análisis
? Análisis sintáctico
? ? ? Preparación para
? Generación del
lexicográfico Análisis semántico Optimización la generación del
(gramatical) código
(rastreo) código

X1= a + bb*12;
X2= a/2 + bb*12;
Primera fase: Análisis lexicográfico
Análisis Análisis Preparación para
Análisis
lexicográfico sintáctico Optimización la generación del
semántico
(rastreo) (gramatical) código

TOKENS
Generación del
código
Manejo de tabla
• Tabla de símbolos
Manejo de
• Tabla de literales
errores
E/S
• Tabla de ciclos iterativos
• Tabla de representación
intermedia

El análisis lexicográfico, también conocido como rastreo o en ocasiones rastreo y filtrado o incluso menos
formalmente, lexicografía o reconocimiento de componentes léxicas (tokenizing), agrupa secuencias de
caracteres desde el programa fuente de entrada en unidades llamadas componentes léxicas o tokens.

Secuencia de caracteres Secuencia de tokens


Tokens
Los tokens (componentes léxicas) son las unidades léxicas básicas del mismo modo en que las palabras y los
signos de puntuación son las unidades básicas de una oración en inglés.
Los tokens varían de lenguaje de lenguaje, e incluso de compilador en compilador para el mismo lenguaje.
La elección de los tokens es una de las tareas del diseñador de compiladores.
Existen 3 unidades léxicas básicas o tokens como secuencias especiales de caracteres, las cuales comprenden
las “palabras” de nuestro lenguaje. Un token es la unidad más pequeña de lenguaje que tiene significado.
En el análisis lexicográfico, la secuencia de caracteres se rastrea hasta que se encuentra una secuencia
permitida, luego se filtra para clasificarla por medio de un tipo como entero o palabra clave o identificador, etc.
Ejemplos:
La palabra clave: SI o IF
La constante: 12
El identificador: X1
El operador < ó +
Puntuación ( ó ;
Del ejemplo:
X1= a + bb*12;
X2= a/2 + bb*12;
Los tokens son:
“X1” “=“ “a” “+” “bb” “*” “12”
Los tokens se describen en 2 partes: tipo o clase y un valor.
a[index] = 4 + 2
Este código contiene 12 caracteres diferentes de un espacio en blanco pero sólo 8 tokens:
a identificador identificador
[ corchete izquierdo Puntuación
index identificador identificador
] corchete derecho Puntuación
= asignación Operador
4 Número Literales
+ signo más Operador
2 Número Literales
ANALISIS SINTACTICO o GRAMATICAL (parsing)
Análisis Análisis Preparación para
Análisis
lexicográfico sintáctico Optimización la generación del
semántico
(rastreo) (gramatical) código

ARBOL DE ANALISIS
TOKENS GRAMATICAL
Generación del
código
Manejo de tabla
• Tabla de símbolos
Manejo de
• Tabla de literales
errores
E/S
• Tabla de ciclos iterativos
• Tabla de representación
intermedia

El análisis sintáctico es más complejo que el análisis lexicográfico. El análisis sintáctico o fase gramatical de un
compilador, agrupa los tokens en estructuras sintácticas en forma muy similar a como teníamos que
estructurar las oraciones (prim.)
bb * 12 consta de 3 tokens “bb” “*” “12” se agrupa en la estructura: ”expresión”
X1= a + bb * 12 consta de ? Tokens “…..” se agrupa en “sentencia de asignación”
que existe una “expresión”
En el proceso de encontrar la estructura sintáctica, la fase de sintaxis también determina si la secuencia de
tokens es sintácticamente correcta, de acuerdo con la definición del lenguaje.

Las estructura reconocida por el análisis sintáctico se describe en forma semejante a un árbol conocido como
árbol sintáctico, árbol gramatical o árbol de estructura.

X1= a + bb*12;
X2= a/2 + bb*12;
ANALISIS SEMANTICO
Análisis Análisis Preparación para
Análisis
lexicográfico sintáctico Optimización la generación del
semántico
(rastreo) (gramatical) código

ARBOL DE ANALISIS
TOKENS GRAMATICAL
RI
Generación del
código
Manejo de tabla
• Tabla de símbolos
Manejo de
• Tabla de literales
errores
E/S
• Tabla de ciclos iterativos
• Tabla de representación
intermedia

El análisis semántico toma como entrada el árbol del análisis gramatical, determinando el significado
(semántica) del programa mediante la creación de tablas de símbolos, verificando cuáles de las variables
utilizadas han sido definidas.
2 tareas principales: Verificación estática / generación de una representación intermedia (RI)
Verificación estática
Completa el análisis iniciado por el analizador gramatical y efectúa actividades como la afirmación de que una
variable con valor de carácter no haya sido asignada a una variable declarada con valor entero. Verificación
de tipos.
Ejemplo: ¿Es correcta la expresión a*b + c?
Rpta: ????
Otra verificación estática es la dimensión de un arreglo (o vector): en un arreglo declarado como bidimensional
no puede utilizarse con 3 índices.

Ejemplo: es correcto lo siguiente:


int x=0;
for(int i=0;i<=10; i++) { r += x*i;
}
Representación Intermedia (RI)
El lenguaje intermedio o código Intermedio (RI, LI o CI), es una forma alternativa para un árbol de análisis
gramatical. A veces el analizador gramatical crear su representación intermedia en forma directa y en
ocasiones el árbol de éste se convierte a la representación.
X=X+1 SI (A < B) ENTONCES X=X+1
= SI

X + < =

X 1 A B X +

X 1
EJERCICIO: Construir el árbol abstracto

X1= a + bb*12;
X2= a/2 + bb*12;
RESULTADO
- Las expresiones se unen en un punto. (;)
- La prioridad basada en los operadores según las expresiones.
- Constantes (literales como operadores pueden estar en el mismo
Nivel, pero con diferente expresión.
OPTIMIZACION
Análisis Análisis Preparación para
Análisis
lexicográfico sintáctico Optimización la generación del
semántico
(rastreo) (gramatical) código

ARBOL DE ANALISIS
RI -
TOKENS GRAMATICAL
RI AlteradaGeneración del
código
Manejo de tabla
• Tabla de símbolos
Manejo de
• Tabla de literales
errores
E/S
• Tabla de ciclos iterativos
• Tabla de representación
intermedia

La fase de optimización cambia la representación intermedia de modo que la fase final de generación de
código producirá código que se ejecutará más rápido u ocupará menos espacio (o ambas cosas).
Tipos de Optimización:
- Optimizaciones locales que realizan dentro de una sentencia o grupos de sentencia
- Optimizaciones de ciclos iterativos que se realizan dentro de los ciclos.
- Optimizaciones globales que son efectuadas sobre todo un programa o procedimiento
- Optimizaciones “de mirilla” (aquellas que se realizan después de que el código es seleccionado “atisbando”
por una pequeña secuencia de código)
Propagación constante (Optimización local)
X=3; ………. A = B + X; En ensamblador es:

.
Mueve #3, X; Mueve la constante 3 a X.
= = .
. Acarreo de memoria
X 3 A + .
Suma X,B,A; Suma X a B y se almacena en A
B X

Reemplazo de contenido a 3
Eliminación de sub-expresiones comunes (Op. Local)
A = B * C; …… D = B * C;
Suponga que un algoritmo ha determinado que la segunda sentencia se ejecuta siempre si la primera está
presente y que no se ha hecho ningún cambio a B y C entre las 2 sentencias.
Un algoritmo para eliminación de sub-expresiones comunes debe cambiar a:

T = B * C; A = T; ………… D = T;

Aunque el código resultante requiere más espacio, se ejecutará más


rápidamente debido a puede copiar información de forma más rápida que
multiplicar la expresión.
EJERCICIO

X1= a + bb*12;
X2= a/2 + bb*12;

EL RI mejorado?
Optimización
PREPARACION PARA LA GENERACION DE CODIGO
Análisis Análisis Preparación para
Análisis
lexicográfico sintáctico Optimización la generación del
(rastreo) (gramatical)
semántico
código
Asignación
de
memoria y
Generación del registros
código
Manejo de tabla
• Tabla de símbolos
Manejo de
• Tabla de literales
errores
E/S
• Tabla de ciclos iterativos
• Tabla de representación
intermedia

Cuando se ejecuta un programa, los valores para sus variables y expresiones se almacenan en la memoria y los
registros.
El compilador decide muchas de las cuestiones acerca de dónde residirán estos valores. 2 de las cuestiones en
la preparación de la generación del código son, entonces, la asignación de memoria y la asignación de
registros.
Asignación de memoria / registros (P. Gen. de código)
La asignación y el mantenimiento de espacio en memoria para conversar los valores de las variables y
expresiones se conoce como asignación de memoria.

Uno de los dilemas en la asignación de memoria es si la memoria debe ser asignada en forma estática, esto es,
fijada en tiempo de compilación o si el almacenamiento puede estar en una pila cuyo tamaño cambia a medida
que se ejecuta el programa.

Los registros se utilizan para conversar los valores de las variables y expresiones. Los programas se ejecutan
más rápido cuando las operaciones se efectúan sobre datos en registros que sí están en la memoria.
Por tanto el compilador tratará de conversar los valores que son accesados con mayor frecuencia en registros.
Determinar cuáles valores conservar en registros es una tarea tediosa.
EJEMPLO

Memoria de pila

a a
Preparación para Tope bb
la generación del de Pila Direccion de X1
código Direccion de X2

Registros

Registro 1 bb*12

Registro 2 a, a/2

Registro “S” Tope de la pila


Generación de código
La generación de código significa la traducción de la representación intermedia a lenguaje ensamblador,
después de optimización y asignaciones de memoria / registros.

En la generación de código la selección de secuencias de instrucciones “ingeniosas”. Aunque las secuencias de


código misteriosas pero eficientes deberían ser documentadas, obtener código “legible” no es el objetivo de la
generación de código.

También podría gustarte