Está en la página 1de 50

Compiladores e

Intérpretes
Conceptos Generales

1
Problema: ¿Cómo ejecutamos un programa?

prog1
if(id1>10) TEXT:
if(id1>10)var
var= “hola”; =_“hola”;else
else Ejecutar! print_“chau”;
//fin
print “chau”;
//fin

3
Problema: ¿Cómo ejecutamos un programa?

• Dos principales estrategias


>chau
011010
prog1
100110 Ejecutar!
if(id1>10) 101010
var= “hola”;
else
print “chau”; Traducción de prog1
//fin
a código de una
máquina destino

4
Problema: ¿Cómo ejecutamos un programa?

• Dos principales estrategias


>chau
011010
prog1
100110 Ejecutar!
if(id1>10) 101010
var= “hola”;
else
print “chau”;
//fin >chau

Programa actualmente corriendo


en la máquina destino recibe y va
Compiladores e Intérpretes 2019
ejecutando prog1
Universidad Nacional del Sur 5
Problema: ¿Cómo ejecutamos un programa?

• Dos principales estrategias


>chau
011010
prog1
Compilador 100110 Ejecutar!
if(id1>10) 101010
var= “hola”;
else
print “chau”;
//fin >chau

Intérprete

6
Características de un
Compilador

7
Características de un Compilador

• Un Compilador es un software que traduce automáticamente


un programa de un lenguaje fuente a un programa equivalente
de un lenguaje destino.
Usualmente
Usualmente Compilador Bajo Nivel
Alto Nivel

011010
Programa 100110
fuente 101010

8
Características de un Compilador

• Un Compilador es un software que traduce automáticamente


un programa de un lenguaje fuente a un programa equivalente
Lenguaje Alto Nivel de un lenguaje destino. Lenguaje Bajo Nivel
• Independiente Usualmente
Usualmente de la Compilador • Específico
máquina Bajo Nivel
Alto Nivel • Sintaxis simple
• Sintaxis compleja
• Semántica compleja • Semántica011010
simple
Programa
• Anidamiento • Manejo de100110
Memoria
fuente
• Subprogramas • Registros 101010
Gran brecha entre el fuente • Alcance simple
• Objetos

y el destino… ¿Cómo y por …
dónde comenzamos?
¡Dividir y Conquistar!
9
Características de un Compilador

• Las tareas del compilador se dividen en fases, las cuales se


agrupan de la siguiente manera:

Compilador

011010
Programa 100110
fuente Fases de Fases de 101010
Análisis Síntesis

10
Características de un Compilador

• Las tareas del compilador se dividen en fases, las cuales se


agrupan de la siguiente manera: Mapear lo
upan de l analizado al
Analizar el código destino
programa fuente Compilador

011010
Programa 100110
fuente Fases de Fases de 101010
Análisis Síntesis

11
Fases de Análisis

12
Analizar y recopilar Fases de Análisis
la información de
la estructura y el
significado del
fuente

Programa
fuente Fases de
Análisis

13
Analizar y recopilar Fases de Análisis
la información de
la estructura y el
significado del
fuente

Programa
fuente Fases de
Análisis
Construir una representación
interna del fuente que capture la
estructura del programa
Árbol Sintáctico Abstracto (AST)

14
Analizar y recopilar Fases de Análisis
la información de
la estructura y el
significado del
fuente

Programa Nombre Retorno Params


fuente Fases de m1 void -

Análisis Nombre
x
tipo
float …
y float

Construir una estructura con


toda la información recolectada
de las entidades del programa
Tabla de Símbolos
15
Analizar y recopilar Fases de Análisis
la información de
la estructura y el
significado del
fuente

Programa Nombre Retorno Params


fuente Fases de m1 void -

Análisis Nombre
x
tipo
float …
y float

Verificar la correctitud sintáctica y semántica Programa


del programa; en caso de no ser correcto, fuente
reportar el error con la información
adecuada.

16
Analizar y recopilar Fases de Análisis
la información de
la estructura y el
significado del
fuente

Programa Nombre Retorno Params


fuente Fases de m1 void -

Análisis Nombre tipo



El compilador debe x
y
float
float

valerse de la
especificación del Programa
lenguaje fuente - de Especificación del fuente
sus reglas de
Lenguaje fuente
Sintaxis y Semántica

17
Fases de Análisis

Fases de Análisis

Analizador Analizador Analizador


Léxico Sintáctico Semántico

¡Dividir y Conquistar!
Compiladores e Intérpretes 2019

18
Fases de Análisis

Fases de Análisis

Analizador Analizador Analizador


Léxico Sintáctico Semántico

¡Dividir y Conquistar!
Compiladores e Intérpretes 2019

19
Fase de Análisis Léxico

• Las reglas de sintaxis están expresadas en términos de los


tipos de palabras válidas (tokens) del lenguaje.
• Estas reglas determinan el orden en que pueden aparecer los
tokens en un programa válido.
• Problema: el programa fuente es una secuencia de
caracteres, no de tokens. TEXT:
//cuenta //cuentavar˽=˽
var = x * (y +10) ; x˽*˽˽(y˽+10)˽;
//fin˽cuenta
//fin cuenta

20
Fase de Análisis Léxico

• Para atacar este problema está la fase de análisis léxico.


• El analizador léxico toma como entrada el fuente y lo transforma en
una secuencia de tokens.
• Para esto irá agrupando caracteres contiguos del fuente que formen tokens.
• Además es el encargado omitir blancos, separadores y comentarios.

//cuenta //cuentava
r˽=˽x˽*˽˽(y Analizador Secuencia tokens
var = x * (y +10) ; ˽+10)˽;//f
//fin cuenta in˽cuenta Léxico

21
Fase de Análisis Léxico

• Además, el analizador léxico será el encargado de detectar y


reportar errores léxicos.
• Por ejemplo:
• Identificadores mal formados: 4varible me%todo
• Símbolos inválidos: € ☺ ~
• Comentarios multi-línea no cerrados: /*comentario…

22
Fase de Análisis Léxico

Secuencia de Tokens

Secuencia de
Caracteres Analizador
Fuente
Léxico

Reporte de Errores
Léxicos

23
Fase de Análisis Sintáctico

• A partir de la secuencia de tokens el compilador debe usar


las reglas de sintaxis de la especificación del lenguaje para:
• Controlar que la secuencia no viola ninguna de las reglas.
• Organizar los tokens en una representación arbórea que refleje la
estructura impuesta por estas reglas.
• Recolectar información de las entidades declaradas.
• El Analizador Sintáctico es el encargado de realizar estas
tareas.

24
Fase de Análisis Sintáctico

• La implementación del analizador sintáctico se vale de las


teorías de lenguajes formales.
• Las reglas de sintaxis del lenguaje están expresadas en
términos de una gramática libre de contexto.
<A>::= id = <E> ;
<E>::= id Describen cómo generar
Derivación: partiendo del
Sintaxis

las cadenas del lenguaje


Reglas

<E>::= intval símbolo inicial aplicamos


<E>::= <E> + <E> Cómo generar los producciones y llegamos a
<E>::= <E> * <E> programas la cadena
<E>::=(<E>) sintácticamente
validos del lenguaje
Compiladores e Intérpretes 2019

25
Fase de Análisis Sintáctico

• En esta fase ya tenemos la cadena (secuencia de tokens) y


queremos analizar su pertenencia al lenguaje.
• La estrategia general del analizador sintáctico será simular la
derivación (inteligentemente) buscando llegar a la secuencia
de tokens.
• En caso de no ser posible quiere decir que el programa fuente tiene
un error sintáctico, el cual deberá ser reportado.

26
Fase de Análisis Sintáctico

• Las derivaciones tienen asociado un árbol de derivación.


• Este árbol refleja cómo se aplicaron las reglas de manera
jerárquica.
• Contiene información redundante o irrelevante para las próximas
fases.
• El analizador sintáctico generará una versión más abstracta de
ese árbol conocida como Árbol Sintáctico Abstracto (AST).

27
Fase de Análisis Sintáctico

• Usualmente el analizador sintáctico recopila información de


las entidades declaradas.
• Esta información se almacena en la tabla de símbolos:
• Estructura jerárquica de tablas, que respeta los
ambientes de declaración del lenguaje.
• Para cada entidad se almacena información útil para las
siguientes fases (tipo, posición, tamaño, etc.).

28
Fase de Análisis Sintáctico

Árbol Sintáctico Abstracto

Tabla de Símbolos

Secuencia Analizador
de Tokens
Sintáctico

Reporte de Errores
Sintácticos

29
Fase de Análisis Semántico

• En las fases anteriores obtuvimos información y controlamos la


forma del programa fuente.
• Esta fase concierne su significado.
• Intuitivamente, se busca:
• Descubrir cómo son utilizadas las entidades y los valores
del programa, y
• analizar si su uso es correcto.

30
Fase de Análisis Semántico

• El analizador semántico tiene dos actividades principales:


• Resolución de Nombres: Identificar adecuadamente a qué entidad
declarada hace referencia un identificador utilizado.
Por ejemplo (en un lenguaje al estilo Java): ¿Está declarada
la clase A?
void m1(A x){
¿Es w una variable local? Sino …
¿es un parámetro? Sino ¿es w = x.m2() + r;
una variable de instancia? …
} ¿Es m2 un método de la
clase A o de un ancestro?

31
Fase de Análisis Semántico

• El analizador semántico tiene dos actividades principales:


• Chequeo de Tipos: Controlar que cuando un elemento tipado
(variable, función, valor, expresión) es utilizado en un contexto su
tipo sea el adecuado.
Por ejemplo (en un lenguaje al estilo Java):
void m1(A x){
¿Es compatible el

tipo del resultado del
w = x.m2() + r;
+ con el tipo de w?

¿
} Puedo operar con + los
tipos de las sub-expresiones
(retorno de m2 y r)? 32
Fase de Análisis Semántico

• En cada una de estas actividades se pueden detectar errores:


• Cuando en la resolución de nombres no se encuentra una entidad
asociada al identificador analizado.
• Cuando en el chequeo tipos se produce una incompatibilidad de
tipos.
• De manera similar a las fases anteriores, el compilador deberá
reportar los errores semánticos detectados.

33
Fase de Análisis Semántico

Árbol Sintáctico Abstracto*

Tabla de Símbolos*
Árbol Sintáctico
Abstracto Analizador
Tabla de Semántico
Símbolos
Reporte de Errores
Semánticos

34
Fases de Síntesis

35
Fases de Síntesis
Toman la información
recopilada por las Buscan que el
fases de análisis y resultado sea un
traducen a código del código eficiente
lenguaje destino

Árbol Sintáctico
011010
Abstracto*
Fases de 100110
Tabla de 101010
Símbolos* Síntesis

36
Fases de Síntesis

Fases de Síntesis

Analizador Analizador Analizador


Léxico Sintáctico Semántico

¡Dividir y Conquistar!
37
Fases de Síntesis

Fases de Síntesis

Generador Optimizador Generador Optimizador


de Código (Código de Código (Código
Intermedio Intermedio) Destino Destino)

¡Dividir y Conquistar!
38
Fase de Generación de Código Intermedio

• Objetivo: traducir el programa a una representación que sea


útil para las siguientes fases.
• La representación intermedia debe ser tal que:
• Sea fácil de generar a partir del AST y de la Tabla de Símbolos.
• Sea fácil de traducir al lenguaje destino.
• Sea útil para aplicar técnicas de optimización.

39
Fase de Generación de Código Intermedio

• En esta fase se traduce a una representación intermedia de


bajo nivel similar al lenguaje destino pero más abstracto.

• Para esto, el generador de código intermedio:


• Genera instrucciones a medida que recorre el AST.
• Utiliza la Tabla de Símbolos para obtener información.

40
Fase de Generación de Código Intermedio

Árbol Sintáctico Código Intermedio


Abstracto* Generador
de Bajo Nivel
Tabla de de Código Tabla de Símbolos*
Símbolos* Intermedio

41
Fase de Optimización de Código Intermedio

• Esta fase reconstruye partes del código intermedio buscando


mejorar su calidad (abstrayéndose de la máquina destino).
• Sin alterar el resultado esperado de la computación.
• En general buscará hacer un código más eficiente, minimizando,
por ejemplo:
• Cantidad de instrucciones.
• Accesos a memoria.
• Uso de temporales.

42
Fase de Optimización de Código Intermedio

Código Intermedio Código Intermedio de


de Bajo Nivel Optimizador
Bajo Nivel Mejorado
(Código Tabla de Símbolos*
Tabla de Símbolos*
Intermedio)

43
Fases de Síntesis
Es posible tener varias fases
de generación de código
intermedio y optimización
Fases de Síntesis

Generador Optimizador Generador Optimizador


de Código (Código de Código (Código
Intermedio Intermedio) Destino Destino)

44
Fases de Generación y Optimización de Código Destino

• En estas fases se traduce la representación intermedia de


bajo nivel del programa fuente a código del lenguaje destino.
• Si elegimos una representación intermedia adecuada, una
estrategia básica de traduccion implicará:
• Tomar una instrucción de la representación intermedia, y
• traducirla a una secuencia de instrucciones del lenguaje destino que
realicen la misma tarea.
• Esta tarea se denomina selección de instrucciones.

45
Fases de Generación y Optimización de Código Destino

• Si el destino es código máquina se asociarán registros y


locaciones de memoria para las variables del programa.
• Optimizaciones sobre el código destino requieren considerar
características de la arquitectura de la máquina destino.
• Por ejemplo: la máquina tiene un número limitado de registros.
• La clave es optimizar el uso de los registros reales, reutilizándolos
cuanto más sea posible.

46
fuente
Programa
Analizador
Léxico

Analizador
Sintáctico

Analizador
Fases de Análisis

Semántico

Gen. Código
Intermedio

Optimizador
Intermedio
Compilador Estándar

Gen. Código
Destino
Estructura de un Compilador

Fases de Síntesis

Optimizador
Destino
47
100110
011010

101010
Estructura de un Compilador
En uno no Estándar
algunas etapas pueden
Compilador Estándar no existir
Fases de Análisis Fases de Síntesis

Gen. Código
Gen. Código

Optimizador
Optimizador
Analizador
Semántico

Intermedio

Intermedio
Analizador
Analizador

Programa Sintáctico 011010

Destino

Destino
Léxico

fuente 100110
101010

No toda etapa necesita que la/s


anteriores terminen para Cuanto más “secuenciales” son las etapas
realizar su tarea más pasadas tendrá el compilador 48
¿Por qué estudiamos Compiladores?

• Los compiladores son piezas fundamentales en computación:


preparan el problema para que sea resuelto por una computadora
• Nos permiten tener lenguajes y herramientas de más alto nivel
adecuados a las necesidades de problemáticas más específicas
• Un compilador es un software complejo → Desafío de ingeniería
de software
• Los compiladores son un ejemplo de cómo aplicar técnicas
formales para asegurar resultados en la práctica

49
¿Por qué estudiamos Compiladores?

• En la actualidad hay muchas herramientas que utilizan


conceptos o son prácticamente compiladores, intérpretes o
traductores
• Por Ejemplo:
• Web Browser
• Librerías de desarrollo web (JSX en React, GWT, etc.)
• Refactoring de código
• Parseo de datos en formatos específicos (JSON, XML, etc.)
• Procesadores de Lenguajes no estructurados

50
Bibliografía

• A. Aho, M. Lam, R. Sethi, J. Ullman - Compilers: Principles


Techniques and Tools.
• K. Cooper, L. Torczon - Engineering a Compiler
• T. A. Mogensen - Basics of Compiler Design
• M. Scott - Programming Languages Pragmatics

51

También podría gustarte