P. 1
codigo intermedio

codigo intermedio

|Views: 338|Likes:

More info:

Published by: Adrian Martinez Perez on Sep 04, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

01/10/2013

pdf

text

original

Sections

  • Introducci´on
  • 2.1. Lenguajes y Gram´aticas
  • 2.1.1. Definiciones
  • 2.1.2. Gram´aticas. Tipos
  • 2.1.3. Lenguajes
  • 2.2. Gram´aticas y Aut´omatas
  • 2.2.1. Aut´omatas
  • 2.3. Traductores
  • 2.3.1. Esquemas de traducci´on
  • An´alisis L´exico. Scanners
  • 3.1. Construcci´on de scanners mediante AFs
  • 3.1.1. Expresiones Regulares. Propiedades
  • 3.1.2. Algoritmo (m´etodo) de Thompson
  • 3.1.3. Transformaci´on de un AFND con λ-transiciones en AFD
  • An´alisis Sint´actico. Parsers
  • 4.1. Tipos de parsing
  • 4.2. An´alisis por precedencia
  • 4.2.1. Precedencia Simple
  • 4.2.2. Precedencia Operador
  • 4.3. An´alisis sint´actico LL(K)
  • 4.3.1. An´alisis LL(1)
  • 4.4. An´alisis sint´actico LR(K)
  • 4.4.1. An´alisis LR(1)
  • An´alisis Sem´antico
  • 5.1. Notaci´on
  • 5.2. Sistemas de Tipos
  • 5.2.1. Tipos b´asicos
  • 5.2.2. Equivalencia de expresiones de tipo
  • 5.2.3. Conversores de tipo
  • 5.2.4. Sobrecarga
  • 6.1. Notaciones
  • 6.1.1. Notaci´on Polaca Inversa (RPN)
  • 6.1.2. Cuartetos
  • 6.1.3. Tercetos
  • 6.1.4. C´odigo a tres direcciones
  • 6.2. M´aquina Objeto
  • 6.2.1. M´etodo de las Cajas
  • 6.2.2. Generaci´on y Representaci´on de saltos
  • 6.2.3. Acceso a elementos de matrices
  • 6.2.4. Representaci´on de strings
  • Optimizaci´on de C´odigo
  • 7.1. T´ecnicas de optimizaci´on en c´odigo fuente
  • 7.1.1. Reducci´on simple o Reducci´on de operaciones
  • 7.1.2. Reacondicionamiento o Reordenamiento de instrucciones
  • 7.1.3. Eliminaci´on de redundancias
  • 7.1.4. Reducci´on de potencias
  • 7.1.5. Reordenaci´on de expresiones: Algoritmo de Nakata
  • 7.1.6. Extracci´on de invariantes
  • 7.2. An´alisis Global del Flujo de Datos
  • 7.2.1. Detecci´on de lazos en los grafos de flujo
  • 7.3. An´alisis de Flujo
  • 7.3.1. Definiciones de Alcance
  • 7.3.2. Notaci´on Vectorial
  • 7.3.3. Soluci´on Iterativa para las ecuaciones de Flujo de Datos
  • 7.3.4. An´alisis de Expresiones Disponibles
  • 7.3.5. An´alisis de Variables Activas
  • 8.1. Tipos de errores
  • 8.2. Recuperaci´on de errores
  • 8.2.1. Correcci´on de errores de cambio
  • 8.2.2. Correcci´on de errores de borrado
  • 8.2.3. Correcci´on de errores de inclusi´on
  • 8.3. Modo p´anico
  • La Tabla de S´ımbolos
  • 9.1. Tipos
  • 9.1.1. TDS lineal
  • 9.1.2. TDS ordenada
  • 9.1.3. TDS ´arbol binario
  • 9.1.4. TDS con hashing
  • 9.1.5. TDS enlazadas
  • Representaci´on de la Informaci´on
  • 10.1. Representaci´on de la Informaci´on
  • 10.1.1. Representaci´on de arrays y matrices
  • 10.1.2. Representaci´on de cadenas y tiras de caracteres
  • 10.1.3. Representaci´on de registros
  • 10.2.1. Registro de activaci´on
  • 10.2.2. Secuencia de llamada y retorno
  • 10.2.3. Subprogramas
  • 10.2.4. Estructuras COMMON y EQUIVALENCE en FORTRAN
  • 10.3. Montadores y Cargadores
  • 10.4. Ficheros objeto
  • 10.5. Int´erpretes

Compiladores

Curso: 2001/2002
Alumna: Laura M. Castro Souto
Profesores: Bernardino Arcay Varela
Jos´e Carlos Dafonte V´azquez
´
Indice general
1. Introducci´on 7
2. Conceptos B´asicos 9
2.1. Lenguajes y Gram´aticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.1. Definiciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.2. Gram´aticas. Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.1.3. Lenguajes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Gram´aticas y Aut´omatas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2.1. Aut´omatas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3. Traductores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.3.1. Esquemas de traducci´on . . . . . . . . . . . . . . . . . . . . . . . . 20
3. An´alisis L´exico. Scanners 21
3.1. Construcci´on de scanners mediante AFs . . . . . . . . . . . . . . . . . . . 23
3.1.1. Expresiones Regulares. Propiedades . . . . . . . . . . . . . . . . . . 23
3.1.2. Algoritmo (m´etodo) de Thompson . . . . . . . . . . . . . . . . . . . 23
3.1.3. Transformaci´on de un AFND con λ-transiciones en AFD . . . . . . 23
4. An´alisis Sint´actico. Parsers 27
4.1. Tipos de parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2. An´alisis por precedencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.2.1. Precedencia Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.2.2. Precedencia Operador . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.3. An´alisis sint´actico LL(K) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.3.1. An´alisis LL(1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.4. An´alisis sint´actico LR(K) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.4.1. An´alisis LR(1) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5. An´alisis Sem´antico 43
5.1. Notaci´on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.2. Sistemas de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.2.1. Tipos b´asicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.2.2. Equivalencia de expresiones de tipo . . . . . . . . . . . . . . . . . . 48
5.2.3. Conversores de tipo . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.2.4. Sobrecarga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3
4
´
INDICE GENERAL
6. C´odigo Intermedio 51
6.1. Notaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.1.1. Notaci´on Polaca Inversa (RPN) . . . . . . . . . . . . . . . . . . . . 52
6.1.2. Cuartetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.1.3. Tercetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.1.4. C´odigo a tres direcciones . . . . . . . . . . . . . . . . . . . . . . . . 54
6.2. M´aquina Objeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.2.1. M´etodo de las Cajas . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.2.2. Generaci´on y Representaci´ on de saltos . . . . . . . . . . . . . . . . 56
6.2.3. Acceso a elementos de matrices . . . . . . . . . . . . . . . . . . . . 56
6.2.4. Representaci´ on de strings . . . . . . . . . . . . . . . . . . . . . . . 57
7. Optimizaci´on de C´odigo 59
7.1. T´ecnicas de optimizaci´on en c´odigo fuente . . . . . . . . . . . . . . . . . . 59
7.1.1. Reducci´on simple o Reducci´on de operaciones . . . . . . . . . . . . 59
7.1.2. Reacondicionamiento o Reordenamiento de instrucciones . . . . . . 60
7.1.3. Eliminaci´on de redundancias . . . . . . . . . . . . . . . . . . . . . . 60
7.1.4. Reducci´on de potencias . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.1.5. Reordenaci´on de expresiones: Algoritmo de Nakata . . . . . . . . . 60
7.1.6. Extracci´on de invariantes . . . . . . . . . . . . . . . . . . . . . . . . 61
7.2. An´alisis Global del Flujo de Datos . . . . . . . . . . . . . . . . . . . . . . . 61
7.2.1. Detecci´on de lazos en los grafos de flujo . . . . . . . . . . . . . . . . 61
7.3. An´alisis de Flujo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
7.3.1. Definiciones de Alcance . . . . . . . . . . . . . . . . . . . . . . . . . 63
7.3.2. Notaci´on Vectorial . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
7.3.3. Soluci´on Iterativa para las ecuaciones de Flujo de Datos . . . . . . 67
7.3.4. An´alisis de Expresiones Disponibles . . . . . . . . . . . . . . . . . . 67
7.3.5. An´alisis de Variables Activas . . . . . . . . . . . . . . . . . . . . . . 68
8. Errores 71
8.1. Tipos de errores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.2. Recuperaci´on de errores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8.2.1. Correcci´on de errores de cambio . . . . . . . . . . . . . . . . . . . . 72
8.2.2. Correcci´on de errores de borrado . . . . . . . . . . . . . . . . . . . 72
8.2.3. Correcci´on de errores de inclusi´on . . . . . . . . . . . . . . . . . . . 73
8.3. Modo p´anico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
9. La Tabla de S´ımbolos 75
9.1. Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.1.1. TDS lineal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.1.2. TDS ordenada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.1.3. TDS ´arbol binario . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.1.4. TDS con hashing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
9.1.5. TDS enlazadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
´
INDICE GENERAL 5
10.Rep. de Informaci´on y Gesti´on de Memoria 79
10.1. Representaci´ on de la Informaci´on . . . . . . . . . . . . . . . . . . . . . . . 79
10.1.1. Representaci´on de arrays y matrices . . . . . . . . . . . . . . . . . . 79
10.1.2. Representaci´on de cadenas y tiras de caracteres . . . . . . . . . . . 81
10.1.3. Representaci´on de registros . . . . . . . . . . . . . . . . . . . . . . 81
10.2. Gesti´on de memoria proporcionada por el compilador . . . . . . . . . . . . 81
10.2.1. Registro de activaci´ on . . . . . . . . . . . . . . . . . . . . . . . . . 82
10.2.2. Secuencia de llamada y retorno . . . . . . . . . . . . . . . . . . . . 82
10.2.3. Subprogramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
10.2.4. Estructuras COMMON y EQUIVALENCE en FORTRAN . . . . . . . . . . . 84
10.3. Montadores y Cargadores . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
10.4. Ficheros objeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.5. Int´erpretes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6
´
INDICE GENERAL
Cap´ıtulo 1
Introducci´on
La asignatura de Compiladores se divide en dos grandes bloques: an´alisis y s´ınte-
sis
1
, cada uno de los cuales se estructura en diferentes partes, que veremos:
Figura 1.1: Esquema de las tareas de un compilador.
1
Entre ambas tendr´a lugar un parcial.
7
8 CAP
´
ITULO 1. INTRODUCCI
´
ON
Cap´ıtulo 2
Lenguajes, Gram´aticas, Aut´omatas y
Traductores
2.1. Lenguajes y Gram´aticas
2.1.1. Definiciones
Sea / = ¦a, b, c, d, e¦ un alfabeto (conjunto de caracteres). Llamamos:

Tira de caracteres o palabra a cualquier concatenaci´on de caracteres del alfabeto:
α = abc.

Distancia o longitud de una tira al n´ umero de elementos (caracteres) de la tira:
|α| = 3. La tira nula es la tira de distancia 0 y suele representarse por ε o λ.

Potencia de una tira a la tira que resulta de yuxtaponer una consigo misma n
veces: para α = ab se tiene α
0
= λ, α
1
= ab, λ
2
= abab, α
n
= ab . . . ab
. ¸¸ .
nveces
. Es decir:
A
n
= A
n−1
A
con A
0
= λ.
La potencia deriva del producto cartesiano: A B = ¦xy/x ∈ A ∧ y ∈ B¦.

Cierre transitivo a: A
+
=
_
i>0
A
i

Cierre reflexivo a: A

=
_
i0
A
i
De lo anterior se deduce que A

= A
+
∪ ¦λ¦.
demostraci
´
on:
A

=
_
i0
A
i
= A
0

_
_
i>0
A
i
_
= ¦λ¦ ∪
_
_
i>0
A
i
_
= A
+
∪ ¦λ¦
9
10 CAP
´
ITULO 2. CONCEPTOS B
´
ASICOS
2.1.2. Gram´aticas. Tipos
Una gram´atica es una upla ( = (^, T , T, o), donde
N conjunto de s´ımbolos no terminales
T conjunto de s´ımbolos terminales
P conjunto de producciones
S axioma de la gram´atica
Seg´ un la forma de sus reglas de producci´on, Chomsky clasific´o las gram´aticas en cuatro
tipos :
Gram´aticas Tipo 0: con estructura de frase, se caracterizan porque los elementos de
T son de la forma α → β con α ∈ (^ ∪ T )
+
y β ∈ (^ ∪ T )

. Son las gram´aticas
m´as generales (admiten producciones de cualquier tipo) y se asocian con aut´omatas
bidireccionales.
Gram´aticas Tipo 1 o sensibles al contexto: sus producciones son de la forma αAβ →
αγβ con α, β ∈ (^ ∪ T )

; A ∈ ^; γ ∈ (^ ∪ T )
+
. En estas gram´aticas, la sustitu-
ci´on de un no terminal por una cadena depende de los s´ımbolos que tenga alrededor
(contexto).
Gram´aticas Tipo 2 o de contexto libre: los elementos de T son de la forma A → α
con A ∈ ^ y α ∈ (^ ∪ T )

. Son las que se usan para lenguajes de programaci´on.
Gram´aticas Tipo 3 o regulares: sus producciones son siempre A → αB o A → α, con
A, B ∈ ^ y α ∈ T . Se asocian con aut´omatas finitos.
Las m´as importantes para nosotros ser´an las gram´aticas de tipo 3 o gram´aticas regu-
lares, ya que derivan conjuntos regulares que representaremos por medio de aut´omatas
finitos y nos ayudar´ an a construir analizadores l´exicos (scanners). Las gram´aticas de tipo
2 o gram´aticas independientes del contexto har´an lo propio cuando nos ocupemos del
an´alisis sint´ actico (parsers).
Definici´on
Llamamos derivaci´on α ⇒ β al conjunto de producciones que nos llevan de α a β:
α = δAµ
β = δγµ
y ∃A → γ ∈ T
Tambi´en se puede usar la notaci´on α ⇒

β o bien α ⇒
+
β para indicar que hay al
menos una derivaci´ on.
2.1. LENGUAJES Y GRAM
´
ATICAS 11
2.1.3. Lenguajes
Dada una gram´atica ( = (^, T , T, o), definimos el lenguaje generado por ( ,
L((), como:
L(() = ¦x/S ⇒

x ∧ x ∈ T

¦
Llamamos formas sentenciales, D((), a:
D(() = ¦x/S ⇒

x ∧ x ∈ (^ ∪ T )

¦
Claramente, se verifica que L(() ⊂ D(().
demostraci
´
on:
Sea x ∈ L((), entonces se cumple que x ∈ T

y S ⇒

x. Equivalentemente,
(S ⇒

x) ∧ (x ∈ (T ∪ ¦λ¦)

) ⇔
(S ⇒

x) ∧
_
x ∈
_
T ∪ ^
0
_

_
De aqu´ı se deduce que
(S ⇒

x) ∧ (x ∈ (T ∪ ^

)

) ⇔
(S ⇒

x) ∧ (x ∈ (T

∪ ^

)

) ⇔
(S ⇒

x) ∧ (x ∈ (T ∪ ^)

)
Por tanto, x ∈ D(() ⇒ L(() ⊆ D(().
La representaci´ on gr´afica de las distintas derivaciones posibles para generar una tira
se denomina ´arbol sint´actico :
Figura 2.1: Ejemplo de ´arbol sint´ actico.
Una gram´atica se dice ambigua si para alguna palabra del lenguaje que genera existe
m´as de un ´arbol sint´actico. No existe el concepto de lenguaje ambiguo, lo que es ambiguo
es la gram´atica.
12 CAP
´
ITULO 2. CONCEPTOS B
´
ASICOS
Figura 2.2: Ejemplo de gram´atica ambigua.
En este ´ ultimo caso, el compilador deber´ıa elegir uno de los dos ´arboles posibles.
´
Esta
ser´a una situaci´on que deber´a evitarse, puesto que ello ralentizar´ıa la compilaci´on, adem´as
de obligar a que el compilador conozca la precedencia de los operadores. La forma de so-
lucionarlo es definir gram´aticas m´as complejas (con m´as restricciones).
Otros problemas de las gram´aticas de contexto libre que conducen a situaciones si-
milares son la recursividad por la izquierda y la existencia de reglas con factores
repetidos por la izquierda.
Cuando construyamos un compilador, buscaremos, pues, mecanismos deterministas
y de poco coste computacional. Usaremos gram´aticas de contexto libre y una serie de
algoritmos que detectan las anomal´ıas que pueden producir ambig¨ uedad (es decir, que las
transforman en gram´aticas regulares):
1. Generaci´on del lenguaje vac´ıo, L(() = ∅.
2. S´ımbolos in´ utiles (no accesibles o no terminables).
3. Reglas unitarias.
4. Reglas ε o λ.
5. Ciclos.
A continuaci´ on veremos una serie de algoritmos que realizan estos objetivos. Obten-
dremos de este modo gram´aticas limpias, esto es, sin reglas-λ y sin ciclos, es decir, sin
reglas unitarias (o reglas cadena) ni s´ımbolos in´ utiles.
Su orden de aplicaci´on sobre una gram´atica es importante, as´ı que debe respetarse el
que seguiremos.
2.1. LENGUAJES Y GRAM
´
ATICAS 13
Algoritmo que detecta L(() = ∅
begin
viejo=0
nuevo={A / (A->t) e P, t e T*}
vhile (nuevo<>viejo) do begin
viejo=nuevo
nuevo=viejo U {B / (B->a) e P, a e (T U viejo)*}
end
if (S e nuevo) then
vacio=‘‘NO’’
else
vacio=‘‘SI’’
end
Algoritmo que elimina s´ımbolos in´ utiles
Dado x, si S ⇒

αxβ ⇒

t, t ∈ T

, entonces x no es in´ util (es accesible, puesto que
S ⇒

αx, y es terminable, ya que xβ ⇒

t).
/* PRIMERA FASE, ELIMINACION DE NO TERMINABLES */
begin
viejo=0
nuevo={A / (A->t) e P, t e T*}
while (nuevo<>viejo) do begin
viejo=nuevo
nuevo=viejo U {B / (B->a), a e (T U viejo)*}
end
N’=nuevo
P’={p e P / p:(A->b), b e (T* U N’)}
end
/* SEGUNDA FASE, ELIMINACION DE NO DERIVABLES */
begin
viejo={S}
nuevo=viejo U {x / (S->axb) e P}
while (nuevo<>viejo) do begin
viejo=nuevo
nuevo=viejo U {Y / (A->aYb) e P, A e viejo}
end
N’=N V nuevo
T’=T V nuevo
end
14 CAP
´
ITULO 2. CONCEPTOS B
´
ASICOS
Como ya hemos dicho, el orden en que aplicamos estos algoritmos es importante. V´ease
sino el siguiente ejemplo:
Figura 2.3: Relevancia en el orden de los algoritmos de simplificaci´on.
Algoritmo que elimina reglas λ
Una regla lambda es aqu´ella que es del tipo A → λ; en ese caso se dice tambi´en
que A es anulable. Intentaremos evitar las gram´aticas que contengan reglas de este tipo,
eliminando sus λ-producciones si las tienen, salvo la metanoci´on (regla S → λ), de la
que no se puede prescindir porque λ forma parte del lenguaje.
begin
viejo=0
nuevo={A / (A->l) e P}
while (nuevo<>viejo) do begin
viejo=nuevo
nuevo=viejo U {B / (B->a), a e viejo*}
end
N’=N-nuevo
P’=Para cada prod. A->a0B0a1B1...anBn e P donde ai no
anulable y Bi anulable, se a~nade a P’A->a0X0a1X1...anXn
con Xi=Bi o l sin a~nadir A->l. Si S es anulable se a~nade
S’->S|l y se a~nade S’ a N
end
Algoritmo que elimina reglas unitarias
Una regla unitaria es de la forma A → B con A, B ∈ ^. No aportan nada y por
ello deben eliminarse.
2.1. LENGUAJES Y GRAM
´
ATICAS 15
begin
viejo=0
nuevo=A; /* debe hacerse para cada A de N */
while (nuevo<>viejo) do begin
viejo=nuevo
nuevo=viejo U {C / (B->C) e P, B e viejo}
end
NA=nuevo
end
P’=Si (B->a) e P y no es regla unitaria, a~nadir (A->a) a P’
para todas las A para las que B no est´e en NA
Eliminaci´on de ciclos
En los casos en los que la aplicaci´on de los algoritmos anteriores no haya solucionado
este problema, se aplican conversiones a forma normal (Chomsky, Greibach).
Recursividad
Dada una regla de producci´on A → αAβ, hay varios tipos de recursividad posibles:
Por la izquierda Se da cuando α = λ, A ∈ ^ y β ∈ (^

T )

. Es el tipo
de recursividad no deseable y que querremos eliminar
1
.
Por la derecha Se da cuando β = λ, A ∈ ^ y α ∈ (^

T )

. Este tipo de
recursividad es usual y no da problemas.
Autoimbricada Se da cuando α, β ,= λ y A ∈ ^. Tampoco da problemas.
Para eliminar la recursividad por la izquierda lo que haremos ser´a:
Si tenemos A->Aa1|Aa2|...|Aap|b1|b2|...|bq
podemos escribirlo como
A->Aai 1<=i<=p
A->bj 1<=j<=q
Para quitar la recursividad por la izquierda escribimos
A->biA’ 1<=i<=q, A’ nuevo simbolo e Te
A’->ajA’|l 1<=j<=p
Reglas con factores repetidos por la izquierda
Las reglas del tipo A → αB[αC tambi´en pueden darnos problemas a la hora de
enfrentar un an´alisis, de modo que intentaremos reescribirlas. Hacerlo es tan sencillo
como sustituirlas por: A → αA

y A

→ B[C con A

un nuevo s´ımbolo no terminal que se
a˜ nade a T
e
.
1
La raz´on es que el an´alisis lo hacemos de izquierda a derecha.
16 CAP
´
ITULO 2. CONCEPTOS B
´
ASICOS
2.2. Gram´aticas y Aut´omatas
Se establece la siguiente correspondencia:
Gram´aticas tipo 0 ⇔ M´aquinas de Turing
Gram´aticas tipo 1 ⇔ Aut´omatas bidireccionales
Gram´aticas tipo 2 ⇔ Aut´omatas con pila
Gram´aticas tipo 3 ⇔ Aut´omatas finitos
Cuadro 2.1: Correspondencia gram´aticas-aut´ omatas.
2.2.1. Aut´omatas
Aut´omatas finitos
Un aut´omata finito queda definido por AF = (Q, T
e
, δ, q
0
, T), donde
Q conjunto de estados
T
e
alfabeto de entrada
δ funci´on de transici´on
q
0
estado inicial
F conjunto de estados finales
y donde la funci´on de transici´on δ es de la forma
δ : QT
e
−→ P(Q)
(q
i
, x
j
) −→ ¦q
k
¦
Llamamos configuraci´on de un aut´omata al par (estado actual, conjunto de caracteres
que quedan por leer): (q,w).
configuraci
´
on inicial: (q
0
, t)
configuraci
´
on final u objetivo: (q
f
, λ), q
f
∈ T
Distinguimos dos tipos de aut´omatas finitos:
AFD (deterministas)
AFND (no deterministas)
2.2. GRAM
´
ATICAS Y AUT
´
OMATAS 17
Llamamos transici´on a (q
i
, aw) ¬ (q
k
, w) , q
f
∈ δ (q
i
, a), esto es, a leer un car´acter
de la tira (cinta) de entrada y modificar el estado interno de la m´aquina. Se puede usar
la notaci´on ¬

para indicar una transici´on con n pasos, n 0, o bien ¬
+
para indicar n > 0.
El lenguaje generado por el AF se define:
L(AF) = ¦t/t ∈ T
e

, (q
0
, t) ¬

(q
i
, λ) , q
i
∈ T¦
En cuanto a la representaci´on gr´afica:
Figura 2.4: Representaciones de un aut´omata.
Aut´omatas con pila
Un aut´omata con pila se define AP = (Q, T
e
, T
p
, δ, q
0
, z
0
, T), con
Q conjunto de estados
T
e
alfabeto de entrada
2
T
p
alfabeto de la pila
δ funci´on de transici´on
q
0
estado inicial
z
0
configuraci´on inicial de la pila
F estados finales
donde la funci´on de transici´on es
δ : Q(T
e

¦λ¦) T
p
−→ P(QT
p

)
(q
i
, a
j
, β) −→ ¦(q
k
, β


2
Equivale al conjunto de terminales en las gram´aticas.
18 CAP
´
ITULO 2. CONCEPTOS B
´
ASICOS
Se incluye incluye λ en el conjunto origen de la funci´on para poder hacer transiciones
sin leer, simplemente con el contenido de la pila, y de nuevo el conjunto destino es un
partes de, contemplando la posibilidad de que sea determinista (APD) o no determinista
(APND).
La configuraci´on: (q, w, α) con q ∈ Q (estado actual), w ∈ T
e

(lo que queda por
leer) y α ∈ T
p

(contenido actual de la pila).
configuraci
´
on inicial: (q
0
, t, z
0
)
configuraci
´
on final u objetivo: (q
f
, λ, α), q
f
∈ T
3
Definimos movimiento o transici´on: (q
i
, aw, zα) ¬ (q
k
, w, βα); tambi´en se admite
la notaci´on ¬

y ¬
+
.
El lenguaje que determina un AP:
L(AP) = ¦t/t ∈ T
e

, (q
0
, t, z
0
) ¬

(q
f
, λ, α) , q
f
∈ T¦
Otra definici´on puede ser:
L(AP) = ¦t/t ∈ T
e

, (q
0
, t, z
0
) ¬

(q
f
, λ, λ) , q
f
∈ T¦
Los que cumplen esta ´ ultima restricci´on a˜ nadida se denominan aut´omatas recono-
cedores por agotamiento de pila.
2.3. Traductores
Traductores finitos
Un traductor finito se define TF = (Q, T
e
, T
s
, δ, q
0
, T), con:
Q conjunto de estados
T
e
alfabeto de entrada
T
s
alfabeto de salida
δ funci´on de transici´on
q
0
estado inicial
F conjunto de estados finales
donde la funci´on de transici´on es
δ : Q¦T
e

¦λ¦¦ −→ P(QT
s

)
(q
i
, a
j
) −→ ¦(q
j
, β)¦
3
La pila puede quedar con caracteres esp´ ureos.
2.3. TRADUCTORES 19
La configuraci´on (estado del aut´omata en un punto determinado de la ejecuci´on) se
representa (q, t, s) con q ∈ Q (estado actual), t ∈ T
e

(lo que queda por leer) y s ∈ T
s

(lo que ha salido hasta el momento).
Un movimiento es (q, aw, s) ¬ (q

, w, sz) cuando δ (q, a) = (q

, z), con q, q

∈ Q,
w ∈ T
e

y z ∈ T
s

.
Y llamamos conjunto de traducci´on a:
Tr (TF) = ¦(t, s); t ∈ T
e

, s ∈ T
s

/ (q
0
, t, λ) ¬

(q
t
, λ, s) , q
t
∈ T¦
Traductores con pila
Un traductor con pila es generado por un APD (del mismo modo que un AF genera
un TF) y queda definido por TP = (Q, T
e
, T
s
, T
p
, δ, q
0
, z
0
, T), con
Q conjunto de estados
T
e
alfabeto de entrada
T
s
alfabeto de salida
T
p
alfabeto de pila
δ funci´on de transici´on
q
0
estado inicial
z
0
configuraci´on inicial de la pila
F conjunto de estados finales
donde la funci´on de transici´on es
δ : Q(T
e

¦λ¦) T
p
−→ P(QT
p

T
s

)
(q
j
, α
i
, β
k
) −→ ¦(q
j
, β
k
, s
p

Su configuraci´on: (q, t, α, s) con q ∈ Q (estado actual), t ∈ T
e

(lo que queda por
leer de la tira de entrada), α ∈ T
p

(contenido de la pila) y s ∈ T
s

(lo que ha salido hasta
ahora).
configuraci
´
on inicial: (q
0
, t, z
0
, λ)
configuraci
´
on final u objetivo: (q
f
, λ, z
0
, s), q
f
∈ T
Un movimiento (transici´on entre dos configuraciones): (q
i
, ax, Zγ, y) ¬ (q
j
, x, αγ, yz)
si (q
j
, α, z) ∈ (q
i
, a, Z)
4
, admiti´endose tambi´en la notaci´on ¬

y ¬
+
.
No tiene por qu´e haber relaci´on en tama˜ no entre la entrada y el string de salida.
4
En lugar de ∈ se pondr´ıa un = en el caso determinista.
20 CAP
´
ITULO 2. CONCEPTOS B
´
ASICOS
Conjunto de traducci´on:
Tr (TP) = ¦(t, s) ((q
0
, t, z
0
, λ) ¬

(q
f
, λ, α, s) sii q
f
∈ T¦
Por agotamiento de pila:
Tr (TP) = ¦(t, s) ((q
0
, t, z
0
, λ) ¬

(q
f
, λ, λ, s) sii q
f
∈ T¦
2.3.1. Esquemas de traducci´on
Los esquemas de traducci´on son una notaci´on. Tienen la siguiente estructura:
EDT = (^, T
e
, T
s
, 1, o), con
N conjunto de s´ımbolos no terminales
T
e
alfabeto de entrada
T
s
alfabeto de salida
R reglas de traducci´on
S axioma
donde las reglas de traducci´on son de la forma
1 : A −→ αβ con
_
_
_
A ∈ ^
α ∈ (^

T
e
)

β ∈ (^

T
s
)

Los esquemas de traducci´on son una extensi´on del concepto de gram´atica. Cumplen
que ^

(T
e

T
s
) = ∅.
Formas de traducci´on
Sean un par de tiras de caracteres (t, s) con t ∈ T
e

y s ∈ T
s

; entonces:
1. (S, S) es una forma de traducci´on, donde S es el axioma
2. Si (γAw, ρAψ) es una forma de traducci´on y existe A → α, β ∈ 1, entonces
(γAw, ρAψ) → (γαw, ρβψ) es una forma de traducci´on. Puede usarse la notaci´on


o →
+
.
El conjunto de traducci´on de un EDT se escribe:
Tr (EDT) = ¦(t, s) / (S, S) →

(t, s) , t ∈ T
e

, s ∈ T
s

¦
Cap´ıtulo 3
An´alisis L´exico. Scanners
Un analizador l´exico o scanner es una entidad cuya tarea consiste en:
Figura 3.1: Objetivo de un scanner.
Ahora bien, los scanners no s´olo hacen esto, sino que, por ejemplo, reformatean texto
(eliminan espacios y l´ıneas en blanco, comentarios, n´ umeros de sentencia, n´ umeros de
l´ınea, etc.) e incluso llevan a cabo tareas sem´anticas mediante el manejo de tablas como
las que ya conocemos para la representaci´ on de aut´omatas. El problema que hay en el
manejo de las tablas es un problema de memoria debido al espacio que ocupan. Para
paliar esto, se usan t´ecnicas de hashing y algoritmos como el de la tabla compacta, que
intenta guardar s´olo las casillas con informaci´on y no las vac´ıas
1
.
Los analizadores l´exicos identifican con los AFD y, por tanto, con las gram´aticas
regulares. Se puden expresar o describir por medio de una expresi´on regular.
Existen diferentes formas de construir un analizador l´exico o scanner (ver figura
3.2, p´agina 22).
El primer m´etodo, se˜ nalado en la mencionada figura como m´etodo manual y que
veremos en ejercicios, es f´acil, pero tambi´en laborioso cuando la gram´atica se complica
m´ınimamente. El tercer m´etodo, que veremos en pr´acticas, es sencillo y c´omodo de utilizar.
A continuaci´on, nos centraremos en el segundo de los m´etodos, el que ser´a exigido en
ejercicios en el examen de la asignatura.
1
Esto puede repercutir en la complicaci´on de la parte sem´antica.
21
22 CAP
´
ITULO 3. AN
´
ALISIS L
´
EXICO. SCANNERS
Figura 3.2: Maneras de construir un scanner.
3.1. CONSTRUCCI
´
ON DE SCANNERS MEDIANTE AFS 23
3.1. Construcci´on de scanners mediante AFs
3.1.1. Expresiones Regulares. Propiedades
En primer lugar, haremos un recordatorio de las propiedades de las expresiones regu-
lares, ya conocidas por nosotros:
Dadas s, t dos expresiones regulares:
Distributiva
s(r[t) = sr[st
(s[r)t = st[rt
Idempotencia
s
∗∗
= s

Conmutativa
r[t = t[r
Asociativa
(sr)t = s(rt)
Elemento Neutro
εr = rε = r
(r[ε)

= r

3.1.2. Algoritmo (m´etodo) de Thompson
El algoritmo que describiremos en esta secci´on permite el paso de una expresi´on regular
a un AFDN. Es un m´etodo gr´afico que se basa en la concatenaci´on de cajas (componentes)
a partir de la definici´on de elementos b´asicos de dichas cajas. Dichos elementos son los
que se muestran en la figura 3.3 (p´agina 24); para ejemplos, v´eanse los ejercicios del tema.
3.1.3. Transformaci´ on de un AFND con λ-transiciones en AFD
Antes de ver los pasos que hemos de seguir para llevar a cabo esta transformaci´on,
necesitamos manejar algunos conceptos:
Si s es un estado del AFND, se define su cerradura:
Cerradura −Σ(s) =
_
s
k
∈ AFND/s →
λ
s
k
_
esto es, el conjunto de estados a los que se puede llegar desde s s´olo mediante
λ-transiciones.
Si T es un conjunto de estados del AFND, se define a su vez su cerradura:
Cerradura −Σ(T) =
_
s
k
∈ AFND/∃s
j
∈ T, s
j

λ
s
k
_
24 CAP
´
ITULO 3. AN
´
ALISIS L
´
EXICO. SCANNERS
Figura 3.3: Componentes b´asicos del m´etodo de Thompson.
3.1. CONSTRUCCI
´
ON DE SCANNERS MEDIANTE AFS 25
Si T es un conjunto de estados del AFND y a es uno de sus s´ımbolos terminales, se
define una funci´on de movimiento:
Mueve (T, a) = ¦s
k
∈ AFND/∃sj ∈ T, s
j

a
s
k
¦
A grandes rasgos, los pasos que se siguen son los siguientes:
1. Se calcula un nuevo estado A, la cerradura-Σ del estado inicial del AFND.
2. Se calcula la funci´on de movimiento para A y todo a
i
s´ımbolo terminal del AFND.
3. Se calcula la cerradura-Σ del resultado del paso anterior, para todos los terminales,
origin´andose nuevos estados B, C, . . .
4. Calculamos la funci´on de movimiento para todo a
i
s´ımbolo terminal del AFND y
los diferentes estados generados en el paso anterior.
El proceso contin´ ua y termina cuando ya no se generan m´as nuevos estados. El algo-
ritmo se formalizar´ıa:
calcular cerradura-E(0)=Estado A
incluir A en NuevosEstados /* estados del AFD */
mientras (no estan todos los T de NuevosEstados marcados) hacer
marcar T
para cada a_i e T_e hacer
U=cerradura-E(Mueve(T,a_i))
si (U no esta en el conjunto T)
se a~nade U a T
transicion[T,a_i]=U
fin-para
fin-mientras
26 CAP
´
ITULO 3. AN
´
ALISIS L
´
EXICO. SCANNERS
Cap´ıtulo 4
An´alisis Sint´actico. Parsers
El an´alisis sint´actico consiste en encontrar u obtener el ´arbol de derivaci´on que
tenga como ra´ız el axioma de una gram´atica dada.
4.1. Tipos de parsing
Hay diferentes tipos de parsing, como se indica en la siguiente figura:
Figura 4.1: Tipos de parsing.
27
28 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
Otra clasificaci´on:
Figura 4.2: Tipos de parsing, otra clasificaci´on.
El parsing descendente intenta construir el ´arbol sint´ actico partiendo del axioma
(ra´ız) desplegando hojas hasta llegar a la frase que tengamos. Por su parte, el parsing
ascendente parte de los tokens (hojas, palabras que ha detectado el scanner) para in-
tentar llegar al axioma (ra´ız).
La gran mayor´ıa de los compiladores modernos son analizadores sint´acticos ascenden-
tes, que suelen basarse en pivotes
1
. De ellos, los m´as potentes son los tipo LR(K), donde
la K representa el n´ umero de tokens que el analizador necesita para saber qu´e pivote apli-
car a cada paso. Por supuesto, lo m´as interesante son los LR(1), de los cuales se conocen
los tres tipos que se mencionan: SLR (el m´as sencillo pero menos potente, impone m´as
restricciones a sus gram´aticas), LR can´onico (el m´as potente pero tambi´en m´as complejo)
y el LALR (un punto intermedio entre los dos anteriores y en el que se basan herramientas
como yacc o bison). Como siempre, el objetivo ser´a la consecuci´on de la tabla.
Otro tipo de analizadores sint´acticos ascendentes son los que utilizan la filosof´ıa de
an´alisis por precedencia. Hist´oricamente fueron los que primero se usaron, aunque hoy
no tengan demasiada utilidad.
Los analizadores sint´acticos descendentes, por su parte, se clasifican en analizadores
con retroceso, en los que se parte del axioma, se hace una exploraci´on y si resulta fa-
llida se vuelve hacia atr´as (backtracking) y se reintenta hasta que se consigue o bien se
agotan todas las posibilidades, y sin retroceso, en los que el algoritmo es m´as predictivo
y conoce con certeza en cada caso qu´e rama del ´arbol expandir. Entre estos ´ ultimos se
encuentran los LL(K), donde de nuevo la K indica el n´ umero de tokens que el parser
1
Conjunto de tokens que forma la parte derecha de una regla de traducci´on.
4.2. AN
´
ALISIS POR PRECEDENCIA 29
necesita conocer para saber por d´onde ir; tambi´en aqu´ı lo interesante es que K=1, de
modo que estudiaremos los LL(1) y c´omo obtener la tabla a partir de ellos.
Por ´ ultimo, mencionar que tanto entre los parsers descendentes como entre los as-
cendentes encontramos aut´omatas de pila y esquemas de traducci´on, pero son m´as bien
m´aquinas te´oricas que aplicaciones reales.
Para cada m´etodo de los que estudiaremos, veremos:

Condiciones que impone.

Definici´on de las gram´aticas que admite
2
.

Construcci´on de las tablas.

Funcionamiento.
4.2. An´alisis por precedencia
4.2.1. Precedencia Simple
Es un m´etodo de an´alisis sint´ actico ascendente.
Definici´on:
Entre dos tokens dados T
1
y T
2
, se establece una relaci´on de precedencia
mediante la cual uno de ellos tendr´a mayor, igual o menor precedencia que el
otro:
T
1
> T
2
T
1
= T
2
T
1
< T
2
Dada una gram´atica, una tabla de precedencia (donde se indiquen las precedencias
relativas entre cada par de s´ımbolos) y una expresi´on, todos los s´ımbolos que queden entre
dos signos “<” y “>” con signos de igualdad entre ellos se dice que forman un pivote.
En la gram´atica ha de existir, entonces, alguna regla del tipo A → pivote
3
. Renombrando
trozos de la expresi´on de esta manera, se puede construir desde la base hacia la ra´ız el
´arbol de derivaci´on correspondiente
4
.
Las casillas en blanco de la tabla de precedencia son errores e indican que los dos
s´ımbolos no pueden relacionarse (no hay una relaci´on de precendencia definida entre ellos)
por medio de la gram´atica en cuesti´on.
2
Que ser´an siempre de contexto libre, las adecuadas para manejar estructuras de frase y ya no palabras.
3
Recu´erdese que ahora los terminales y no terminales no representan s´ımbolos, sino palabras, tokens.
4
V´eanse ejemplos del tema.
30 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
M´etodo derivativo o del ´arbol
Es un m´etodo manual aplicable en caso de gram´aticas sencillas, pero no recomendable
en cuanto ´estas se complican un poco, puesto que es sencillo olvidarse de alg´ un caso. Ello
es as´ı porque consiste simplemente en intentar extraer la tabla de precedencia a partir
simplemente de analizar “a ojo” las producciones de la gram´atica, hasta agotar todas las
posibles derivaciones
5
.
M´etodo matricial
Para ver c´omo obtener la tabla de precedencia mediante este m´etodo necesitamos
previamente definir:
Relaci´on de equivalencia (R) Cumple lo siguiente:
1. Reflexividad, xRx, ∀x ∈ R.
2. Simetr´ıa, xRy ⇒ yRx, ∀x, y ∈ R.
3. Transitividad, xRy, yRz ⇒ xRz, ∀x, y, z ∈ R.
Relaci´on universal Se define:
U = A A = ¦(x, y) /x ∈ A, y ∈ A¦
Relaci´on traspuesta (de una dada) Se representa R

o R
T
:
R
T
= ¦(y, x) /xRy¦
Relaci´on complementaria (a una relaci´on dada):
R

= ¦(x, y) /

(xRy)¦
Relaciones binarias Dadas dos relaciones R y S:
R+S = ¦(x, y)/(xRy) ∨ (xSy)¦
RS = ¦(x, y)/(xRy) ∧ (xSy)¦
R S = ¦(x, y)/∃z, (xRz) ∧ (zSy)¦
El m´etodo se describe de la siguiente manera:

Dada una gram´atica ( = ¦^, T , T, o¦:
1. Se dice que x < y si y s´olo si A → αxBβ ∈ T y B ⇒
+
yγ.
2. Se dice que x ±y si y s´olo si A → αxy ∈ T.
3. Se dice que x > y si y s´olo si A → AαCyβ ∈ T y C ⇒
+
γx.
Dada una misma tabla de precedencia simple, pueden obtenerse diferentes gram´aticas
6
.
5
Ver ejemplos del tema.
6
Una pregunta de examen puede ser, dada una tabla de precedencia simple, intentar obtener su
gram´atica.
4.2. AN
´
ALISIS POR PRECEDENCIA 31
M´as definiciones:
Relaci´on Primero Diremos que A primero X si y s´olo si ∃A ⇒ Xαβ.
Relaci´on Primero
+
Diremos que A primero
+
X si y s´olo si ∃A ⇒
+
Xαβ.
Relaci´on
´
Ultimo Diremos que A ultimo X si y s´olo si ∃A ⇒ αβX.
Relaci´on
´
Ultimo
+
Diremos que A ultimo
+
X si y s´olo si ∃A ⇒
+
αβX.
Relaci´on Dentro Diremos que A dentro X si y s´olo si ∃A ⇒ αXβ.
Relaci´on Dentro
+
Diremos que A dentro
+
X si y s´olo si ∃A ⇒
+
αXβ.
Algoritmo de Warshall
/* permite hallar PRIMERO+ a partir de PRIMERO */
B=A; // copia de la matriz de partida
I=1;
3: repeat
if (B(I,J)=1) then
for K=1 to N do
if (A(J,K)=1) then
A(I,K)=1;
until todos los valores de J;
I=I+1;
if (I<=N) then
goto 3;
else
stop;
Cuadro 4.1: Algoritmo de Warshall.
Las relaciones se obtienen:

(±), observando las reglas de la gram´atica.

(<) = (±)(primero
+
).

(>) = (ultimo
+
)
T
(±)(I +primero
+
), donde I es la matriz identidad (todo ceros con
unos en la diagonal).
4.2.2. Precedencia Operador
Puede considerarse un caso particular de precedencia simple (podr´ıa, por tanto, re-
solverse utilizando matrices o el m´etodo del ´arbol); es un m´etodo de an´alisis sint´ actico
ascendente en el que se buscan relaciones entre los s´ımbolos.
32 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
La diferencia es que, dado que la precedencia se define entre los operadores, no es
necesario tener en cuenta los identificadores (que no tienen precedencia, son indistinguibles
entre s´ı), no son necesarios para determinar si la expresi´on est´a bien escrita.
Construcci´on de la tabla
Los pasos son los siguientes:
i) Si el operador θ
1
tiene mayor precedencia que el operador θ
2
, escribiremos
θ
1
> θ
2
θ
2
< θ
1
ii) Si θ
1
y θ
2
son operadores de igual precedencia, anotaremos
θ
1
> θ
2
θ
2
> θ
1
_
si son asociativos por la izquierda
θ
1
< θ
2
θ
2
< θ
1
_
si son asociativos por la derecha
iii) Adem´as de todo ello, se cumple siempre que:
a) Los identificadores tienen mayor precedencia que cualquier operador.
b) Los par´entesis tienen mayor precedencia que cualquier otro s´ımbolo.
c) El s´ımbolo $ (indicador de principio/fin de cadena) tiene menor precedencia
que cualquier otro s´ımbolo.
Mayor precedencia ˆE asociatividad por la derecha
* / asociatividad por la izquierda
Menor precedencia + - asociatividad por la izquierda
Cuadro 4.2: Precedencia usual entre los operadores matem´aticos.
4.3. An´alisis sint´actico LL(K)
4.3.1. An´alisis LL(1)
Es un m´etodo predictivo, no recursivo. Suele dar buenos resultados en aplicacio-
nes peque˜ nas (shells, compiladores de peque˜ nos lenguajes, etc) donde precedencia simple
no resulta suficiente.
El m´etodo de funcionamiento es independiente del lenguaje. Al variar ´este s´olo va-
riar´a la tabla. Como ya hemos comentado alguna vez, las casillas en blanco de la tabla
suponen acciones sem´anticas, errores. Veremos en seguida su estructura y c´omo se cons-
truye.
4.3. AN
´
ALISIS SINT
´
ACTICO LL(K) 33
Figura 4.3: Estructura de un parser LL(1).
Funcionamiento
Los pasos que sigue un analizador sint´ actico de este tipo son:
Se lee la entrada y la cima de la pila. Puede ocurrir:
1. Si X = a = $ (donde X es el elemento de la cima de la pila, a el primer elemento
del buffer de entrada y $ el car´acter nulo), se llega al fin del an
´
alisis.
2. Si X = a ,= $, el parser saca X de la pila y mueve el apuntador de entrada al
siguiente elemento del buffer.
3. Si X es no terminal, el parser consulta la tabla de an´alisis (que llamaremos M) en
la posici´on (X, a). Hay dos posibilidades:
a) Si M (X, a) = ∅, entonces se ha producido un error.
b) Si M (X, a) = (X → uwz), se contin´ ua el an´alisis.
El pseudoc´odigo de la tabla 4.3.1 (p´agina 34) realiza lo que acabamos de explicar
7
.
Construcci´on de la tabla de an´alisis
Definiremos antes de nada dos operaciones:
1. Primero(X), que calcula el primer terminal de una cadena de caracteres,
de la siguiente manera:
a) Si X ∈ T
8
, entonces Primero(X)=¦X¦.
b) Si X → ε, entonces ε ∈ Primero(X).
7
Ver ejemplos en los ejercicios del tema.
8
Hablamos siempre refiri´endonos a la gram´atica que acepta el parser, ( = (^, T , T, o).
34 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
entrada: cadena w y tabla de analisis sintactico M
salida: si w pertenece al lenguaje que acepta el parser,
una derivacion por la izquierda de w, si no error
{
apuntar æ al primer s´ımbolo de w;
do
{
sea X el simbolo de la cima de la pila y
a el simbolo apuntado por æ;
if (X es terminal o $)
if (X=a)
extraer X de la pila y avanzar æ;
else
return (error);
else
if (M[X,a]=X->Y1Y2...Yk)
{
extraer X de la pila;
meter Yk,Yk-1...Y1 en la pila;
emitir la produccion X->Y1Y2...Yk;
}
else
return (error);
} while (X no sea $); /* pila vacia */
}
Cuadro 4.3: Algoritmo de an´alisis LL(1).
4.4. AN
´
ALISIS SINT
´
ACTICO LR(K) 35
c) Si X ∈ ^ y X → Y
1
Y
2
. . . Y
n
, entonces a ∈ Primero(X) y ∃i/a ∈
Primero(Y
i
) y ε ∈ Primero(Y
j
) ∀j < i.
Las tres reglas se aplican sobre la cadena en cada caso.
2. Siguiente(A) –con A ∈ ^–, que calcula, dado un no terminal A, el
primer terminal que est´a a continuaci´ on de A:
a) Se cumple que $ ∈ Siguiente(S), donde S es el s´ımbolo inicial, la
metanoci´on, el axioma.
b) Si A → αBβ, entonces ¦Primero(β)−¦ε¦¦ ⊂ Siguiente(B).
c) Si A → αBβ y β →

ε o A → αB, entonces Siguiente(A) ⊂
Siguiente(B).
De nuevo, esas tres reglas no son excluyentes.
Una vez que se han calculado los conjuntos Primero y Siguiente, las reglas para
construir la tabla son:
1. Para toda producci´on A → α ∈ T, aplicar los dos pasos siguientes.
2. ∀a ∈ Primero(α), M[A, a] = A → α.
3. Si ε ∈ Primero(α), entonces M[A, b] = A → α∀b ∈ Siguiente(A).
Como ya ha sido comentado, las casillas en blanco supondr´an errores y dar´an lugar
a tratamientos sem´anticos, mientras que si en una casilla aparece m´as de una regla, la
conclusi´on es que la gram´atica no es LL(1) (no es determinista).
Comprobaci´on de si una gram´atica es LL(1)
Dada una gram´atica libre del contexto ( = ¦^, T , T, o¦, ¿c´omo podemos saber si es
una gram´atica LL(1) o no sin tener que construir la tabla? La cuesti´on es tan sencilla
como realizar las siguientes comprobaciones ∀A → α[β:
1. primero(α)∩ primero(β) = ∅.
2. S´olo α ´o β pueden derivar ε (nunca ambos).
3. Si β ⇒

ε, debe darse que primero(α)∩ siguiente(A) = ∅.
4.4. An´alisis sint´actico LR(K)
En esta secci´on analizaremos una t´ecnica eficiente de an´alisis sint´actico ascendente
que se puede utilizar para analizar una clase m´as amplia de gram´aticas independientes
del contexto, denominada an´alisis sint´actico LR(K). Este tipo de analizadores recibe
este nombre por lo siguiente: la L hace referencia a qe el examen de la entrada se realiza
de izquierda a derecha; la R se debe a que la reconstrucciones en orden inverso nos llevan
a derivaciones por la derecha y la K, como ya imaginamos, es por el n´ umero de s´ımbolos
36 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
de anticipaci´ on que se necesitan para una correcta toma de decisiones.
Despu´es de estudiar el modo de operar de un analizador sint´ actico LR, introduciremos
tres t´ecnicas para construir la tabla de an´alisis sint´actico LR para una gram´atica dada:

SLR (LR Sencillo), el m´as f´acil pero tambi´en el menos potente (puede que no
consiga construir la tabla para algunas gram´aticas).

LALR (LR con examen por anticipado), un m´etodo “intermedio”, que funciona
con la mayor´ıa de las gram´aticas de los lenguajes de programaci´on y que usan
herramientas como yacc, que veremos.

LR can´onico, el m´as poderoso y costoso de los tres. Veremos modos de simplificarlo
para obtener alguno de los dos anteriores.
4.4.1. An´alisis LR(1)
Figura 4.4: Modelo de un analizador sint´ actico LR(1).
Este es el esquema de un analizador sint´actico LR(1): se apoya en una tabla de an´alisis
sint´actico con dos partes, acci´on e ir a. De un tipo de LR(1) a otro s´olo cambian las tablas.
El programa analizador lee caracteres del buffer de entrada de uno en uno, utiliza una
pila para almacenar una cadena donde X
i
son s´ımbolos gramaticales y S
i
son estados.
Cada s´ımbolo de estado resume la informaci´on contenida debajo de ´el en la pila, y se
usan la combinaci´on del s´ımbolo de estado en la cima de la pila y el s´ımbolo en curso
de la entrada para indexar la tabla de an´alisis sint´ actico y determinar la decisi´on de
desplazamiento a reducci´on del analizador.
La tabla de an´alisis sint´ actico, como decimos, consta de dos partes: la funci´on acci´on,
que indica una acci´on del analizador (indica qu´e hacer), y la funci´on ir a, que indica las
transiciones entre estados. La primera se usa siempre, en cada uno de los pasos, mientras
que la segunda se usa s´olo si tiene lugar una reducci´on.
4.4. AN
´
ALISIS SINT
´
ACTICO LR(K) 37
Funcionamiento
1. Tomamos S
m
de la cima de la pila y a
i
de la entrada actual.
2. Se consulta la entrada accion[S
m
, a
i
] de la tabla de acciones del analizador, pudiendo
obtenerse uno de los siguientes valores:
a) Desplazar S
p
, donde S
p
es un estado.
b) Reducir por una producci´on gramatical A → β. En este caso se consulta tam-
bi´en la entrada ir a[S
m−r
, A] (donde r es la longitud de β) de la tabla de
transiciones para obtener un nuevo estado S
q
que se a˜ nade a la cima de la pila.
c) Aceptar.
d) Error.
3. Repetir hasta terminar la tira de entrada, aceptarla o llegar a un error.
Una configuraci´on de un analizador sint´ actico LR(1) es un par cuyo primer compo-
nente es el contenido de la pila y el segundo la entrada que a´ un est´a sin procesar:
(S
0
X
1
S
1
X
2
S
2
. . . X
m
S
m
, a
i
a
i+1
. . . a
n
$)
El siguiente movimiento del analizador se determina leyendo a
i
, el s´ımbolo de la en-
trada en curso, y S
m
, el estado del tope de la pila, y consultado despu´es la entrada
accion[S
m
, a
i
] de la tabla de acciones del analizador. Las configuraciones obtenidas des-
pu´es de cada uno de los cuatro tipos de movimiento son las siguientes:
◦ Si accion[S
m
, a
i
] =desplazar S
p
, el analizador ejecuta un movimiento de desplaza-
miento entrando en la configuraci´on
(S
0
X
1
S
1
X
2
S
2
. . . X
m
S
m
a
i
S
p
, a
i+1
. . . a
n
¸)
(el analizador ha desplazado a la pila el s´ımbolo de la entrada en curso y el siguiente
estado, y a
i+1
se convierte en el s´ımbolo de entrada actual).
◦ Si accion[S
m
, a
i
] =reducir A → β, entonces el analizador ejecuta un movimiento de
reducci´on, entrando en la configuraci´on
(S
0
X
1
S
1
X
2
S
2
. . . X
m−r
S
m−r
AS
q
, a
i
a
i+1
. . . a
n
$)
donde S
q
= ir a[S
m−r
, A] y r es la longitud de β, el lado derecho de la producci´on
(el analizador ha extra´ıdo 2r s´ımbolos de la pila, r de estados y r de s´ımbolos de
la gram´atica, exponiendo el estado S
m−r
, luego ha introducido A, el lado izquierdo
de la producci´on, y S
q
, la entrada de ir a[S
m−r
, A], en la pila; no se ha modificado
la entrada en curso). La secuencia de s´ımbolos gramaticales extra´ıdos de la pila,
X
m−r+1
. . . X
m
, concuerda siempre con β, el lado derecho de la producci´on con que
se efect´ ua la reducci´on.
◦ Si accion[S
m
, a
i
] =aceptar, el an´alisis sint´ actico ha terminado con ´exito.
◦ Si accion[S
m
, a
i
] =error, el analizador sint´actico ha descubierto un error.
38 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
Construcci´on de tablas de an´alisis sint´actico SLR
Se llama elemento de an´alisis sint´actico LR(0) (o, simplemente, elemento) de
una gram´atica ( a una producci´on de dicha gram´atica que contiene un punto en algu-
na posici´on del lado derecho. Por tanto, la producci´on A → XY Z produce los cuatro
elementos:
A → .XY Z
A → X.Y Z
A → XY.Z
A → XY Z.
La producci´on A → ε s´olo genera el elemento A → .
Una serie de conjuntos de elementos LR(0) se denomina colecci´on can´onica LR(0)
y proporciona la base para construir analizadores sint´ acticos SLR. Para construir la co-
lecci´on can´onica LR(0) para una gram´atica se define una gram´atica aumentada y dos
funciones, cerradura e ir a:
Gram´atica aumentada Dada una gram´atica (, la gram´atica aumentada (

resulta de
a˜ nadir a ( la regla S

→ S, donde S es el axioma de la gram´atica.
Cerradura Dado un subconjunto I de elementos LR(0):
∗ Todo elemento de I est´a en cerradura(I).
∗ ∀A → αBβ ∈ cerradura(I), si ∃B → γ ∈ T, entonces B → .γ ∈ cerradura(I).
∗ Se aplica lo anterior hasta que cerradura(I) no var´ıa.
Intuitivamente, si A → α Bβ est´a en cerradura(I) indica que, en alg´ un momento
del proceso de an´alisis sint´actico, se cree posible ver a continuaci´on una cadena
derivable de B como entrada. Si B → γ es una producci´on, tambi´en se espera ver
una subcadena derivable de γ en este punto. Por esta raz´on, se incluye B → γ en
cerradura(I).
Se puede calcular la funci´on cerradura como se muestra en la tabla 4.4.1.
Obs´ervese que si se a˜ nade una producci´on de B a la cerradura de I con el punto
en el extremo izquierdo, entonces todas las producciones de B se a˜ nadir´ an de ma-
nera similar a la cerradura. De hecho, se pueden dividir todos los conjuntos de los
elementos que interesan en dos clases:
1. Elementos nucleares, todos los elementos cuyos puntos no est´en en el extremo
izquierdo, y el elemento inicial S

→ S.
2. Elementos no nucleares, todos los elementos cuyos puntos est´an en el extremo
izquierdo.
Operaci´on ir a La segunda funci´on ´ util es ir a(I, X), donde I es un conjunto de elemen-
tos y X es un s´ımbolo de la gram´atica (X ∈ (^ ∪T )). Se define como la cerradura
del conjunto de todos los elementos A → αX β tales que A → α Xβ est´e en I.
4.4. AN
´
ALISIS SINT
´
ACTICO LR(K) 39
funcion cerradura(I)
begin
J=I;
repeat
for cada elemento A->a.Bb en J y cada produccion
B->l de G tal que B->.l no este en J do
a~nadir B->.l a J;
until no se puedan a~nadir mas elementos a J;
return J;
end
Cuadro 4.4: Algoritmo de c´alculo de cerradura.
Definidos estos conceptos, podemos ver el algoritmo para la obtenci´on de la co-
lecci´on can´onica LR(0) de un conjunto de elementos LR(0) para una gram´atica au-
mentada (

. Esta colecci´on nos permitir´a obtener el aut´omata a partir de la gram´atica.
procedimiento elementos_LR0 (G)
begin
C={cerradura(S’->.S)}; /* gram´atica aumentada */
repeat
for cada conjunto de elementos I en C y cada simbolo
gramatical X de G tal que ir_a(I,X) no est´e vac´ıo y
no est´e en C do
a~nadir ir_a(I,X) a C;
until no se puedan a~nadir m´as conjuntos de elementos a C;
end
Cuadro 4.5: Construcci´on de la colecci´on can´onica LR(0).
Diremos que un elemento A → β
1
β
2
es un elemento v´alido para un prefijo variable
αβ
1
si existe una derivaci´on S

⇒ αAω⇒

αβ
1
β
2
ω. En general, un elemento ser´a v´alido
para muchos prefijos.
Vistos estos conceptos, los pasos de construcci´on de la tabla son:
1. Dada una gram´atica G, se aumenta para producir G

.
2. Se construye la colecci´on can´onica LR(0):
C = ¦I
0
, I
1
, . . . , I
n
¦
3. Los estados se obtienen a partir de los I
i
(siendo I
k
el estado k).
40 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
4. Las casillas se rellenan:
a) Si A → α.aβ ∈ I
i
, e Ir a(I
i
, a) = I
j
, entonces se hace accion[i, a] =
desplazar j.
b) Si A → α. ∈ I
i
, entonces se hace accion[i, a] = reducir A →
α ∀a ∈ siguiente(A).
c) Si S

→ S. ∈ I
i
, entonces se hace accion[i, $] = aceptar.
Si las acciones anteriores generan acciones contradictorias (aparece m´as
de una acci´on en alguna casilla de alguna de las tablas) se dice que la
gram´atica no es SLR.
5. Si Ir a(I
i
, A) = I
j
, siendo A un no terminal, entonces se hace Ir a[i, A] =
j.
6. Todas las entradas no definidas por las reglas anteriores son consideradas
error.
Aunque no veremos los criterios de decisi´on, es importante saber que el m´etodo SLR
no funciona para cualquier gram´atica. El problema es que, como hemos visto, SLR no
tiene en cuenta m´as que aqu´ella parte de la cadena de entrada que ya ha le´ıdo para tomar
decisiones, es decir, no es capaz de mirar un elemento m´as all´a. A continuaci´ on veremos
el m´etodo LR-can´onico, que s´ı lo hace.
Construcci´on de tablas de an´alisis sint´actico LR-can´onico
El m´etodo LR-can´onico es un m´etodo de construcci´on de tablas de an´alisis sint´ acti-
co m´as general, m´as potente, pero tambi´en m´as costoso desde el punto de vista del dise˜ no.
El LR-can´onico a˜ nade informaci´on adicional al estado redefiniendo los elementos de
an´alisis para incluir un s´ımbolo terminal como segundo componente, de forma que pasan
a ser de la forma [A → α.β, a] en lugar de [A → α.β] como en SLR. Este nuevo elemento
que se tiene en cuenta para la predicci´on, recibe el nombre de s´ımbolo de anticipaci´ on,
y:
no tiene efecto si β ,= ε
si β = ε, el elemento [A → α., a] pide una reducci´on por A → α s´olo si el siguiente
s´ımbolo de la entrada es a
De este modo, podemos tener varios casos, varias reducciones con diferentes no termi-
nales a, algo que proporciona su potencia al LR-can´onico, frente al SLR.
El m´etodo para construir la colecci´on de conjuntos de elementos v´alidos ahora es
fundamentalmente el mismo que la forma en que se construye la colecci´on can´onica de
conjuntos de elementos del an´alisis sint´actico LR(0); s´olo hay que modificar los dos pro-
cedimientos Cerradura e Ir a.
4.4. AN
´
ALISIS SINT
´
ACTICO LR(K) 41
function cerradura(I)
begin
repeat
for cada elemento [A->s.Bb, a] en I,
cada produccion B->r en G’
y cada terminal b de Primero(ba) tal que
[B->.r,b] no esta en I, do
a~nadir [B->.r, b] a I;
until no se puedan a~nadir mas elementos a I;
return (I);
end
Cuadro 4.6: Algoritmo de c´alculo de cerradura para LR-can´onico.
function Ir_a(I,X)
begin
J=conjunto de los elementos [A->sX.b,a] tal que
[A->s.Xb,a] esta en I;
return (cerradura(J));
end
Cuadro 4.7: Algoritmo de c´alculo de Ir a para LR-can´onico.
procedure elementos(G’) /* gramatica aumentada */
begin
C=cerradura([S’->.S,$]);
repeat
for cada conjunto de elementos I en C
y cada simbolo X tal que Ir_a(I,X) no sea vacio
y no este en C, do
a~nadir Ir_a(I,X) a C;
until no se puedan a~nadir mas conjuntos de elementos a C;
end
Cuadro 4.8: Construcci´on del conjunto de los elementos de an´alisis LR-can´onico.
42 CAP
´
ITULO 4. AN
´
ALISIS SINT
´
ACTICO. PARSERS
Una vez que tenemos el aut´omata finito (su diagrama de transici´on de estados), los
pasos para la construcci´on de la tabla de an´alisis sint´actico son:
1. Dada una gram´atica G, se aumenta para producir G

.
2. Se construye C = ¦I
0
, I
1
, . . . , I
n
¦, la colecci´on de conjuntos de elementos
LR(1) para G

.
3. El estado i se obtiene a partir de I
i
.
4. Las casillas se rellenan:
a) Si [A → α.aβ, b] ∈ I
i
e Ir a(I
i
, a) = I
j
, entonces se hace accion[i, a] =
desplazar j, para todo terminal a..
b) Si [A → α., a] ∈ I
i
, entonces se hace accion[i, a] = reducir A → α
(con A ,= S

).
c) Si [S

→ S., $] ∈ I
i
, entonces se hace accion[i, $] = aceptar.
Si las reglas anteriores producen un conflicto, se dice que la gram´atica no
es LR(1).
5. Si Ir a(I
i
, A) = I
j
, entonces se hace Ir a[i, A] = j.
6. Todas las entradas no definidas por las reglas anteriores se consideran
error.
Construcci´on de tablas de an´alisis sint´actico LALR
Veremos el m´etodo LALR como una “consecuencia” del LR-can´onico, como una
simplificaci´on. Es decir, dada una gram´atica, aplicado el m´etodo LR-can´onico y obtenida
la tabla de an´alisis sint´actico (o simplemente el aut´omata finito), construiremos a partir
de ello un LALR realizando una compresi´on de estados.
El LR-can´onico es un m´etodo de an´alisis muy potente, pero que produce muchos
estados, de los cuales, en gran mayor´ıa de ocasiones podemos hacer una compresi´on de
la siguiente manera: analizando los estados del aut´omata generado por el m´etodo LR-
can´onico, comprobaremos que el coraz´on (core, producci´on) de los elementos LR(1) es
el mismo en varios estados, generalmente dos (aunque pueden ser m´as), que s´olo var´ıan
en el elemento de anticipaci´on (lookahead). El m´etodo LALR lo ´ unico que hace es reunir
esos pares (conjuntos) de estados en uno solo, agrupando los elementos de anticipaci´on a
la derecha.
Evidentemente, la fusi´on de los estados debe ir acompa˜ nada por la compatibilidad de
transiciones entre los estados que se fusionan, es decir, para fusionar dos estados no s´olo
es necesario que el coraz´on de todas las reglas de ambos sean iguales (no vale tampoco
que uno sea subconjunto del otro), sino que adem´as estados fusionados deben transicionar
a estados fusionados. Si ello no ocurriera as´ı, dir´ıamos que la gram´atica no es LALR.
La obtenci´on de la tabla de an´alisis sint´actico LALR a partir del nuevo aut´omata
simplificado (comprimido) es sencilla, consiste ´ unicamente en traducir las modificaciones
a las celdas de la misma. Si la gram´atica realmente es LALR, no deber´ıa haber problema
alguno.
Cap´ıtulo 5
An´alisis Sem´antico
Traducci´ on dirigida por la sintaxis
En el presente tema veremos el ´ ultimo de los tipos de an´alisis que mencionamos en la
introducci´on de la asignatura (figura 1.1, p´agina 7): el an´alisis sem´antico.
Ya hemos visto el an´alisis l´exico (scanners, que detectaban las palabras y comprobaban
si estaban bien formadas), el an´alisis sint´actico (parsers, que estudiaban la correcci´on en
la estructuras de las frases) y nos falta, por tanto, la parte del an´alisis que juzga el sentido
de las construcciones que han sido previamente validadas por scanners y parsers.
La encarnaci´on m´as simple de esta tarea es la comprobaci´on de tipos. Veremos,
pues, c´omo se a˜ naden reglas sem´anticas de este tipo a las estructuras que ya hemos
estudiado (ser´a, al fin y al cabo, a˜ nadir m´as informaci´on a las reglas que ya manejamos).
El mecanismo t´ıpico es trasladar las comprobaciones pertinentes a los nodos del ´arbol
sint´actico que hemos aprendido a construir en el cap´ıtulo anterior (asignando un conjunto
de rutinas a los mismos, que se ocupar´an, entre otras cosas, de la comprobaci´on de tipos,
gesti´on de memoria, generaci´on de c´odigo objeto. . . ). Al situar en este punto la clave de
la acci´on tambi´en ser´a m´as f´acil, como veremos, la generaci´on de c´odigo. Adem´as, la
tarea se ver´ a simplificada tambi´en porque usaremos la misma sintaxis para la sem´antica
que para la generaci´on de c´odigo.
En la figura 5.1 (p´agina 44) se muestra un esquema que relaciona los temas principales
que veremos en breve en el seno de la traducci´on dirigida por la sintaxis. Esta parte
de la disciplina del an´alisis sem´antico se apoya en conceptos de grafos, particularmente
de grafos ac´ıclicos dirigidos, y es una alternativa al dise˜ no m´as formal de esquemas de
traducci´on. En an´alisis de tipos haremos referencia tanto a los tipos b´asicos (integer,
real, char,. . . ) como a los constructores de tipos, operadores que, trabajando con tipos
b´asicos, construyen otros tipos (records, arrays, pointers,. . . ). En cuanto a la gene-
raci´on de c´odigo, veremos c´omo la definici´on de reglas en este caso estar´a ´ıntimamente
relacionado con la arquitectura subyacente y definiremos nuestra “m´aquina te´orica”, para
trabajar sobre ella.
43
44 CAP
´
ITULO 5. AN
´
ALISIS SEM
´
ANTICO
Notaciones
EDT
Grafos
G.D.A.
Reglas
Gramatica
Notaciones
Tipos basicos
Polimorfismo
Sobrecarga
Semantico
Analisis
Traduccion dirigida
por la sintaxis
Generacion de
codigo intermedio
Arquitectura:
− tercetos
− cuartetos
− codigo 3
direcciones
− RPN
Definicion
de reglas
Maquina
teorica
Implementacion:
− estructuras de control
− expresiones
− asignaciones
− ...
Analisis de
tipos
Sistemas de
tipos
Constructores
de tipos
Conversion
de tipos
Equivalencia
de tipos
Comprobacion
de tipos
sintesis semantica
Figura 5.1: Esquema de an´alisis sem´antico.
5.1. Notaci´on
Para describir acciones sem´anticas utilizaremos dos elementos:
reglas
atributos
de tal manera que, en la traducci´on dirigida por la sintaxis, dada una producci´on
A → α tendremos un conjunto de reglas sem´anticas b = f(c
1
, c
2
, . . . , c
n
) donde c
i
son los
atributos.
5.2. SISTEMAS DE TIPOS 45
Cada nodo de evaluaci´on en un ´arbol sint´ actico (nodos correspondientes a partes
izquierdas de reglas de producci´on de la gram´atica) tendr´a asociada una f (funci´on de
evaluaci´ on) que aplicar´a sobre sus propios c
i
y sobre c
j
relativos o pertenecientes a sus
hijos directos. Este proceso, que se da t´ıpicamente en la evaluaci´on ascendente de izquierda
a derecha, se denomina arrastre de informaci´on.
5.2. Sistemas de Tipos
5.2.1. Tipos b´asicos
Un sistema de tipos es el conjunto de expresiones de tipos que tenemos a disposi-
ci´on en el lenguaje. A su vez, una expresi´on de tipo es, bien un tipo b´asico, o bien el
resultado de aplicar un constructor de tipos a un tipo b´asico.
Nosotros consideraremos:
Tipos b´asicos los siguientes:

boolean

char

integer

real
como en la mayor´ıa de los lenguajes, y adem´as:

error tipo

void
Constructores de tipos los siguientes:

Matrices, que representaremos array(I,T) donde I es el tipo de los
´ındices y T el de las variables que contendr´ a el array.

Productos, que se definen: si T
1
y T
2
son expresiones de tipos, entonces
T
1
T
2
es otra expresi´on de tipo y se denomina producto.

Registros, consecuencia de la definici´on de productos, pues no son
m´as que “productos con nombres”.

Apuntadores o punteros, que representaremos pointer(T) donde T es
el tipo a que apuntan.

Funciones, que representaremos T
1
T
2
. . . T
n
→ T
p
, donde
T
1
T
2
. . . T
n
es el dominio de la funci´on (de modo que los
argumentos de una funci´on son un producto) y T
p
el tipo del rango.
Adem´as, claro est´a, pueden construirse “constructores de constructores”
(punteros a punteros, punteros a funciones, arrays, de punteros,. . . ). Esto
dar´a lugar a los problemas de equivalencia que veremos m´as adelante.
46 CAP
´
ITULO 5. AN
´
ALISIS SEM
´
ANTICO
Existen dos tipos de atributos:
heredados, cuyo valor se calcula a partir de los valores de los atributos de los her-
manos y del padre del nodo al que pertenecen
sintetizados, cuyo valor se calcula a partir de los valores de los atributos de los hijos
del nodo al que pertenecen
En traducci´on dirigida por la sintaxis usaremos ´ unicamente atributos sintetizados,
raz´on por la que en alguna bibliograf´ıa puede encontrarse la denominaci´on traducci´on
(definici´on) dirigida por la sintaxis con atributos sintetizados.
En adelante, usaremos la siguiente gram´atica como referencia en explicaciones, ejem-
plos y ejercicios:
P -> D;E
D -> D;D | id:T
T -> char | integer | array[num] of T | ^T
E -> literal | numero | id | E mod E | E[E] | ^E
S -> id:=E
S -> if E then S1
S -> while E do S1
S -> S1;S2
Cuadro 5.1: Gram´atica de referencia.
Veamos a continuaci´ on algunas reglas sem´anticas :
→ La comprobaci´on de tipos matriciales:
E → E
1
[E
2
]
requerir´a comprobar que E
2
es de tipo entero
1
y asignar al tipo de E (no terminal
de arrastre de informaci´on) el tipo de los elementos del array:
E.tipo = if (E2.tipo=integer) and
(E1.tipo=array[S,T]) then T
else
error_tipo;
1
Supondremos que el lenguaje s´olo permite que los ´ındices de los arrays sean enteros.
5.2. SISTEMAS DE TIPOS 47
→ La comprobaci´on de operaciones
E → E
1
mod E
2
(donde mod juega el mismo papel que cualquier otra operaci´on),
E.tipo = if (E1.tipo=integer) and
(E2.tipo=integer) then integer
else
error_tipo;
→ La comprobaci´on de tipos en proposiciones del lenguaje como
S → if E then S
1
S → while E do S
1
es tan sencilla como
S.tipo = if (E.tipo=boolean) then S1.tipo
else error_tipo;
→ La comprobaci´on de la concatenaci´on de proposiciones,
S → S1; S2
se har´ıa:
S.tipo = if (S1.tipo=void) and
(S2.tipo=void) then void
else
error_tipo;
→ La comprobaci´on de tipos asociada a la asignaci´on
S → id = E
es de las m´as simples:
S.tipo = if (id.tipo=E.tipo) then void
else error_tipo;
48 CAP
´
ITULO 5. AN
´
ALISIS SEM
´
ANTICO
→ La comprobaci´on de tipos en expresiones o variables en s´ı
E → literal
E → numero
E → int
E → real
E → . . .
no tiene ning´ un secreto,
E.tipo = literal | numero | integer | real | ...
→ La comprobaci´on de tipos relativa a funciones, por ´ ultimo,
E → E
1
(E
2
)
se resuelve
E.tipo = if (E2.tipo=S) and
(E1.tipo=(fun S->T)) then T
else
error_tipo;
5.2.2. Equivalencia de expresiones de tipo
Se consideran dos tipos de equivalencia para las expresiones de tipo:
Equivalencia estructural Se dice que dos expresiones de tipo tienen equi-
valencia estructural cuando son del mismo tipo b´asico o son resultado de
aplicar los mismos constructores en el mismo orden a los mismos tipos
b´asicos (o incluso expresiones de tipo).
Equivalencia por nombre Se dice que dos expresiones de tipo tienen equi-
valencia por nombre cuando son del mismo “nombre” de tipo, es decir,
son expresiones de tipo declarado id´entico.
Una forma de realizar la comprobaci´on de equivalencia de tipos es mediante la codi-
ficaci´on de expresiones de tipo, esto es, asignar un c´odigo binario a cada constructor
de tipo y cada tipo b´asico, de suerte que cada expresi´on pueda codificarse mediante una
secuencia de ceros y unos que represente los c´odigos de los constructores y tipos b´asicos
que se han utilizado para su composici´on. La comprobaci´on de la equivalencia de dos
expresiones de tipo es tan trivial como comparar bit a bit sus respectivas codificaciones.
Esta estrategia tiene la ventaja de que ahorra memoria (no se necesita tanto arrastre
de informaci´on) y, puesto que la comparaci´on binaria puede realizarse en la propia ALU, es
m´as r´apida. Sin embargo, podr´ıa suceder que dos tipos compuestos distintos tuviesen como
representaci´on la misma secuencia de bits (ya que no se reflejan, por ejemplo, tama˜ nos de
matrices o argumentos de funciones).
5.2. SISTEMAS DE TIPOS 49
function equivest(s,t):boolean;
begin
if (s y t son del mismo tipo basico) then
return true
else if (s=array(s1,s2) and t=array(t1,t2)) then
return (equivest(s1,t1) and equivest(s2,t2))
else if (s=s1xs2 and t=t1xt2) then
return (equivest(s1,t1) and equivest(s2,t2))
else if (s=pointer(s1) and t=pointer(t1)) then
return equivest(s1,t1)
else if ...
...
else
return false
end
Cuadro 5.2: Algoritmo de comprobaci´on de equivalencia estructural.
5.2.3. Conversores de tipo
Sup´ongase la situaci´on:
a = b c
donde a y c son reales mientras que b es un entero. Restringi´endonos a lo que hemos visto
hasta ahora, est´a claro que esto fallar´ıa, mas nuestra experiencia nos dice que es algo
perfectamente viable ¿c´omo es posible, entonces? Mediante una conversi´ on de tipo.
Esta conversi´on, cuando es impl´ıcita, hecha autom´aticamente por el compilador se
denomina coerci´on, mientras que cuando es expl´ıcitamente indicada por el programador
es lo que conocemos como cast.
5.2.4. Sobrecarga
Se dice que un operador est´a sobrecargado cuando en funci´on de las variables con las
que trabaja tiene un significado u otro. La sobrecarga puede afectar tambi´en a los s´ımbo-
los, en cuyo caso puede crear problemas de ambig¨ uedad (por ejemplo, si se sobrecargan
los par´entesis para referenciar matrices), motivo por el que se recomienda evitarlo.
Asimismo, tambi´en podemos enfrentarnos a la sobrecarga de funciones, que recibe el
nombre de polimorfismo.
En ese caso, ante una construcci´on
E → E
1
(E
2
)
50 CAP
´
ITULO 5. AN
´
ALISIS SEM
´
ANTICO
Producci´on Regla Sem´antica
E → numero E.tipo = integer
E → numero numero E.tipo = real
E → id E.tipo = buscaTDS(id.entrada)
E → E
1
opE
2
E.tipo = if ((E1.tipo=integer) and
(E2.tipo=integer)) then integer
else if ((E1.tipo=integer) and
(E2.tipo=real)) then real
else if ((E1.tipo=real) and
(E2.tipo=integer)) then real
else if ((E1.tipo=real) and
(E2.tipo=real)) then real
else error tipo
Cuadro 5.3: Comprobaci´on de tipos para coerci´on de entero a real.
se admite que la expresi´on de tipo E
2
no sea ´ unica. Se trabaja entonces con un conjunto
de expresiones de tipo posibles (E
2
pasa a ser un conjunto) con la repercusi´on y modifi-
caciones que ello introduce en las reglas sem´anticas que hemos visto:
E.tipo = { t / existen s en E2.tipos, s->t en E1.tipos }
Cap´ıtulo 6
Generaci´on de C´odigo Intermedio
Tras el an´alisis sem´antico llega el momento de generar lo que denominamos c´odigo
intermedio, que posteriormente ser´a optimizado antes de dar lugar al definitivo c´odigo
objeto.
El motivo por el que se realiza este paso intermedio, la raz´on por la que se genera
c´odigo intermedio es evitar tener que construir un compilador desde cero para todas y
cada una de las diferentes arquitecturas. Adem´as, ello va a reportar otros beneficios, ya
que nos permitir´a optimizar mejor, ya que el proceso de optimizaci´on trabajar´a sobre este
mismo c´odigo intermedio. Por ´ ultimo, tambi´en favorece la reutilizaci´on.
6.1. Notaciones
No existe un “lenguaje intermedio universal”. Los m´as conocidos y usados, que vere-
mos, son:
Notaci´on Polaca Inversa (RPN)
Cuartetos
Tercetos, Tercetos indirectos
Lenguajes a tres direcciones
P-c´odigo
Interesa tener c´odigo basado en 3 direcciones, del estilo
a = b op c
(dos operandos y el resultado) ya que facilitar´a la generaci´on de c´odigo objeto y tambi´en
su depuraci´on.
51
52 CAP
´
ITULO 6. C
´
ODIGO INTERMEDIO
6.1.1. Notaci´on Polaca Inversa (RPN)
Es la primera notaci´on de c´odigo intermedio que se utiliz´o. Con una pila es posible
construir un generador de c´odigo muy sencillo, y es en lo que se bas´o esta idea.
La notaci´on polaca inversa, tambi´en llamada postfija representa las jerarqu´ıas en
forma de ´arbol de modo que cada nodo aparece inmediatamente despu´es de sus hijos. El
formato postfijo es f´acil de traducir y pasar a c´odigo m´aquina con ayuda de una pila: se
colocan los operandos y despu´es los operadores.
OPERADORES + - / * mod div
FUNCIONES sqrt sin cos tan abs ord char
BLOQUES DE CODIGO bloque ... finbloque
ENTRADA/SALIDA read write
MATRICES decl sub
ASIGNACION :=
BIFURCACIONES
SALTO INCONDICIONAL b
SALTO SI POSITIVO bp
SALTO SI NEGATIVO bn
SALTO SI CERO bc
Cuadro 6.1: Notaci´on Polaca Inversa (RPN).
En RPN los par´entesis se ignoran y la traducci´on de una expresi´on a esta notaci´on
sigue las directrices que se muestran a continuaci´ on:
Producci´on Reglas Sem´anticas
S → E
E → T
E → E +T P(i) =

+

i = i + 1
E → E −T P(i) =

i = i −1
E → −T P(i) = @ i = i + 1
a
T → F
T → T ∗ F P(i) =

i = i −1
T → T/F P(i) =

/

i = i −1
F → id P(i) = buscarTDS(i) i = i −1
F → (E)
a
Arrastre de informaci´on, @ es un s´ımbolo de control.
Cuadro 6.2: Traducci´ on a RPN.
6.1. NOTACIONES 53
donde la sem´antica se asocia a cada nodo.
Hay dos formas de evaluar un ´arbol sint´ actico de una expresi´on: mediante esquemas de
traducci´on (no lo veremos) o mediante traducci´on dirigida por la sintaxis (lo que estamos
viendo). Se hace de abajo a arriba y de izquierda a derecha, de manera determinista,
obteniendo, por diferentes t´ecnicas que veremos en este tema, el resultado en c´odigo
intermedio.
6.1.2. Cuartetos
La notaci´on de cuartetos (tambi´en llamados cu´adruplos en alguna bibliograf´ıa, como
[4]) tiene la siguiente forma:
(< operador >, < operando1 >, < operando2 >, < resultado >)
es decir, A/B, por ejemplo, ser´ıa representado como (/, A, B, T
1
) donde T
1
es un re-
gistro temporal.
Los s´ımbolos usados en esta notaci´on son:
OPERACIONES ARITMETICAS + - * / ^
mod abs sqrt sin cos
ASIGNACION X:=E (:=, E, , X)
ENTRADA/SALIDA (read, , , X) (write, , , X)
SALTO ABSOLUTO INCONDICIONAL (JP, n, , )
n = posicion absoluta a saltar
SALTO RELATIVO INCONDICIONAL (JR, n, , )
n = posicion relativa actual
SALTO INCONDICIONAL
SALTO SI IGUAL A CERO (JZ, n, E, )
SALTO SI MAYOR QUE CERO (JGZ, n, E, )
SALTO SI MENOR QUE CERO (JLZ, n, E, )
SALTO SI IGUALES (JE, n, X1, X2)
SALTO SI MAYOR (JG, n, X1, X2)
SALTO SI MENOR (JL, n, X1, X2)
Cuadro 6.3: Notaci´on de cuartetos.
6.1.3. Tercetos
La notaci´on de tercetos (tambi´en llamados triples en alguna bibliograf´ıa, como [4])
se diferencia de la de cuartetos en que el resultado queda impl´ıcito en el propio terceto,
siendo su formato:
54 CAP
´
ITULO 6. C
´
ODIGO INTERMEDIO
(< operador >, < operando1 >, < operando2 >)
de manera que para hacer a + b + c tendr´ıamos en primer lugar el terceto (+, a, b)
etiquetado como [x] y seguidamente el terceto (+, [x], c), referenciando al anterior.
La ventaja de los tercetos es que ocupan mucha menos memoria en variables tempo-
rales. Por otra parte, la recolocaci´on del c´odigo en optimizaci´on es m´as compleja porque
hay que mantener las referencias correctamente. Para enfrentar este problema surgen los
tercetos indirectos, que son tercetos junto con los que se guarda un vector secuen-
cia que marca el orden de ejecuci´on tras la recolocaci´on, de manera que no es necesario
reescribir los tercetos -sus referencias- en caso de reordenamiento. Adem´as, si los tercetos
se repiten s´olo es necesario repetirlos en el vector secuencia y no “f´ısicamente”.
Por su estructura, los tercetos carecen de instrucciones JE, JG y JL, aunque pueden
ser “simuladas”; el resto de la notaci´on es gemela a la de cuartetos (tabla 6.3).
6.1.4. C´odigo a tres direcciones
Esta ´ ultima notaci´on que veremos, llamada c´odigo a tres direcciones, es en cierto
modo una generalizaci´on de todas las anteriores. Es una notaci´on m´as, que recibe su
nombre por razones obvias debidas a su estructura,
ti = tj op tk
y que, quiz´as por su mayor claridad (recuerda al pseudoc´odigo), se usa con mayor fre-
cuencia en los lenguajes intermedios y tambi´en, como haremos nosotros, en optimizaci´on
de c´odigo.
Los s´ımbolos que utiliza son los mismos que en cuartetos y tercetos, con la salvedad
de que para los saltos se utiliza la palabra reservada goto.
6.2. M´aquina Objeto
Para seguir concretando el el proceso de generaci´on de c´odigo objeto, describiremos
a continuaci´on una m´aquina secuencial Von Neumann, que utilizaremos como base de
aqu´ı en adelante. Supondremos una CPU con una serie de operaciones (instrucciones) y
una forma de mover datos entre la memoria y los registros.
Esta m´aquina objeto tendr´a:
n registros R
0
, R
1
, . . . R
n−1
instrucciones de la forma
operacion fuente, destino
con las palabras reservadas cl´asicas
6.2. M
´
AQUINA OBJETO 55
ADD
SUB
MUL
DIV
CALL (llamada a funciones)
GOTO (saltos)
MOVE (accesos a memoria: cargas/almacenamientos)
Los modos de direccionamiento que consideraremos ser´an los presentes en la tabla 6.4.
Modo Forma Direcci´on Coste
absoluto M M
a
1
registro R R
b
0
indexado C(R) C+contenido(R)
c
1
registro indirecto ∗R contenido(R) 1
indexado indirecto ∗C(R) contenido(C+contenido(R)) 2
literal #C C 1
a
M es una posici´on de memoria principal.
b
R es un registro de la CPU.
c
C es una constante.
Cuadro 6.4: Modos de direccionamiento
6.2.1. M´etodo de las Cajas
Es una manera de modelizar las operaciones entre dos operandos. Si analizamos de
manera sencilla
1
las posibles instrucciones que manejamos, veremos que casi todas ellas
son muy similares. Todas siguen el siguiente esquema:
MOV operandoA, registroI
MOV operandoB, registroJ
OPERACION_X registroI, registroJ
MOV registroJ, temporalK
De manera que si tomamos esta estructura como “construcci´on base” a la que deno-
minamos caja, el c´odigo al final es un conjunto de cajas
2
.
1
Sin tener en cuenta cuestiones como si los registros est´an previamente ocupados, etc.
2
El paso de este “ensamblador” despu´es de “encajonado” a c´odigo m´aquina es trivial: la operaci´on se
codifica seg´ un un convenio, se buscan las constantes en la TDS,. . .
56 CAP
´
ITULO 6. C
´
ODIGO INTERMEDIO
El problema es que el c´odigo resultante de aplicar al pie de la letra estas traducciones
es un c´odigo muy malo, entendiendo por bondad del c´odigo una combinaci´ on entre su ra-
pidez y la memoria que ocupa y/o utiliza, puesto que es un c´odigo en absoluto optimizado.
El c´odigo que genera un cuarteto
(< operacion >, < operando1 >, < operando2 >, < destino >)
(y, por supuesto, tambi´en un terceto) es tambi´en una caja:
MOV operandoA, registroI
MOV operandoB, registroJ
OPERACION_X registroI, registroJ
MOV registroJ, destino
La generaci´on de c´odigo a tres direcciones tambi´en se hace por sem´antica. Los int´erpre-
tes cl´asicos (puros) usaban RPN ya que es m´as intuitivo (ya contamos con una pila).
Una forma sencilla de optimizaci´on que se puede hacer en tiempo de compilaci´on es
mantener una tabla de localizaci´on del almacenamiento de los operandos, para evitar
la carga sucesiva del mismo operador varias veces, igual que la generaci´on de variables
temporales l´ogicamente innecesarias.
6.2.2. Generaci´on y Representaci´ on de saltos
Si sabemos generar saltos, sabemos generar todas las instrucciones de control (if, for,
do, while). Son necesarias dos “pasadas” por el c´odigo para hacer eso: en la primera se
generan etiquetas relativas, que se sustituyen en la segunda, una vez que ya se conoce la
direcci´on base.
6.2.3. Acceso a elementos de matrices
Se puede acceder r´apidamente a los elementos de una matriz si se guardan en un bloque
de posiciones consecutivas. Si el ancho de cada elemento de la matriz es a, entonces el
i-´esimo elemento de la matriz A comienza en la posici´on
base + (i −inf) a
donde inf es el l´ımite inferior de los sub´ındices y base es la direcci´on relativa de la posici´on
de memoria asignada a la matriz (es decir, es A[inf]).
La expresi´on anterior se puede evaluar parcialmente durante la compilaci´on si se escribe
como
i a + (base −inf a)
ya que la subexpresi´on base −inf a se puede evaluar cuando aparece la declaraci´on de
la matriz y ser guardada en entrada de la TDS de A.
6.2. M
´
AQUINA OBJETO 57
Esto se puede extender a los c´alculos de direcciones de elementos de matrices multidi-
mensionales. Una matriz bidimensional se almacena generalmente en una de dos formas,
bien en forma de filas (fila a fila), bien en forma de columnas (columna a columna). En
el caso de una matriz bidimensional almacenada por filas, la direcci´on relativa de A[i, j]
se puede calcular mediante
base + ((i −inf
i
) n
j
+ j −inf
j
) a
donde inf
i
e inf
j
son los l´ımites inferiores de los valores de i y j, y n
j
es el n´ umero de
valores que puede tomar j. Es decir, si sup
j
fuese el l´ımite superior para el valor de j,
entonces n
j
= sup
j
−inf
j
+ 1.
Suponiendo que i y j son los ´ unicos valores que no se conocen durante la compilaci´on,
la expresi´on anterior se puede reescribir como
((i n
j
) + j) a + (base −(inf
i
n
j
) + inf
j
) a)
donde el ´ ultimo t´ermino puede determinarse durante la misma.
Generalizando, si tenemos una matriz de n dimensiones
M[inf
1
. . . sup
1
, inf
2
. . . sup
2
, . . . , inf
n
. . . sup
n
]
donde inf
1
, inf
2
, . . . , inf
n
son los l´ımites inferiores de cada dimensi´on, sup
1
, sup
2
, . . . , sup
n
son los l´ımites superiores de cada dimensi´on y n es el n´ umero de dimensiones de la matriz,
dando por sentado que sup
i
≥ inf
i
el n´ umero de elementos de cada dimensi´on es de nuevo
e
i
= sup
i
−inf
i
+1 y el acceso a un elemento cualquiera M[j
1
, j
2
, . . . , j
n
] tendr´a la direcci´on
base + (j
1
−i
1
) e
2
e
3
. . . e
n
+
+ (j
2
−i
2
) e
3
e
4
. . . e
n
+
+ . . . +
+ (j
n−1
−i
n−1
) e
n
+
+ (j
n
−i
n
)
Por ´ ultimo, en caso de tener una matriz triangular de la que se almacenen s´olo los ele-
mentos por debajo de la diagonal, el acceso a cada uno de ellos [i, j] ser´ıa
i + (j −1) j
2
.
6.2.4. Representaci´on de strings
Pero no s´olo la representaci´on de matrices es un problema, sino que tambi´en lo es la
de las cadenas de caracteres. Las soluciones hist´oricas que se han adoptado al respecto
son:
Definici´on de un tama˜ no m´aximo para cualquier string y reservar un banco de
memoria “troceado” al efecto. Un ejemplo de uso de esta estrategia es Fortran.
Mantenimiento de un registro con el par (nombre, longitud del string) y un puntero
a la direcci´on de inicio, todo ello almacenado en la TDS. Esta estrategia se debe
a McKeeman, Horning y Wortman, data de 1970 y es usada por lenguajes como
Pascal.
58 CAP
´
ITULO 6. C
´
ODIGO INTERMEDIO
Cap´ıtulo 7
Optimizaci´on de C´odigo
T´ecnicas de generaci´on de c´odigo como el m´etodo de las cajas que hemos visto son,
como ya se coment´o en su momento, extremadamente ineficientes. Por ello, la optimiza-
ci´on de c´odigo puede verse incluso como parte de la propia generaci´on.
Las t´ecnicas de optimizaci´on se aplican a 3 niveles:
1. Optimizaci´on en c´odigo fuente, realizada normalmente por el pro-
gramador, cada vez se usa menos debido al gran desarrollo hardware
actual.
2. Optimizaci´on en c´odigo intermedio, la m´as importante de las tres,
es la que realizan los compiladores gracias a la aplicaci´on de t´ecnicas de
an´alisis de flujo de datos.
3. Optimizaci´on en c´odigo objeto, muy orientada a la m´aquina y muy
dependiente de ´esta, tiene problemas de portabilidad.
7.1. T´ecnicas de optimizaci´on en c´odigo fuente
7.1.1. Reducci´on simple o Reducci´on de operaciones
Consiste en evitar incluir en el c´odigo fuente operaciones que pueden ser realizadas
previamente, por ejemplo, en lugar de poner
s = 2 * PI
se pondr´ıa
s = 6.283185
Esto es importante sobre todo si expresiones como la anterior se incluyen en lazos,
subrutinas, etc. En ocasiones, incluso es preferible generar previamente varias variables
que se utilicen en diferentes iteraciones que operar en cada interaci´on.
59
60 CAP
´
ITULO 7. OPTIMIZACI
´
ON DE C
´
ODIGO
7.1.2. Reacondicionamiento o Reordenamiento de instrucciones
Consiste en alterar el orden de secuenciaci´on de las instrucciones (sin que var´ıe su
sem´antica, claro est´a) a fin de conseguir tanto la generaci´on de menos instrucciones de
c´odigo intermedio como de c´odigo objeto, como el uso de un menor n´ umero de registros
y variables temporales.
7.1.3. Eliminaci´on de redundancias
Debe evitarse siempre la realizaci´on de c´alculos repetitivos. La optimizaci´on siempre
centra su especial atenci´on en cuerpos cr´ıticos como los lazos, donde es frecuente encontrar
expresiones similares a:
M[i][j][k] = M[i x bi x di][j x bj x dj][k x bk x dk] + incremento
donde toda la primera parte
1
supone una redundancia y podr´ıa extraerse.
7.1.4. Reducci´on de potencias
Ante una operaci´on como
s = a**2
siempre es preferible utilizar
s = a*a
ya que no hay ning´ un ensamblador que contenga instrucciones de potenciaci´on, mien-
tras que todos incluyen el producto puesto que es una operaci´on que ya las propias ALUs
realizan.
7.1.5. Reordenaci´on de expresiones: Algoritmo de Nakata
El algoritmo de Nakata y Anderson data de 1964 y su objetivo es marcar una
pauta para la reordenaci´on de expresiones:
PASO-1. Construir el ´arbol de la expresi´on a reordenar.
PASO-2. Etiquetado del ´arbol:
PASO-2.1. IF n es hoja THEN
IF n es hijo m´as a la derecha de su padre THEN
etiqueta(n) = 1
ELSE
1
En lenguajes que manejen las matrices como punteros, como C y algunos bloques de Fortran.
7.2. AN
´
ALISIS GLOBAL DEL FLUJO DE DATOS 61
etiqueta(n) = 0
ELSE BEGIN
SEAN n1, n2,..., nk hijos ordenados
/* por etiqueta */
THEN
etiqueta(n) = max(etiqueta(ni) + i - 1)
END
PASO-3. Una vez etiquetado el ´arbol, para generar la expresi´on
se parte de la ra´ız y se desciende por la rama del sub´arbol
cuya etiqueta contenga el valor m´aximo.
En caso de igualdad, se opta por la subrama de la derecha,
salvo si la operaci´on no es conmutativa.
7.1.6. Extracci´on de invariantes
Llamamos expresiones invariantes de lazo a aqu´ellas que pueden sacarse fuera de los
bucles ya que su valor no sufre variaci´on durante las iteraciones. As´ı, en lugar de
i = 1..N
a[i] = f(c1,c2,...,cn)
otro i
se persigue construir preferiblemente
t = f(c1,c2,...,cn)
i = 1..N
a[i] = t
otro i
7.2. An´alisis Global del Flujo de Datos
7.2.1. Detecci´on de lazos en los grafos de flujo
Decimos que un nodo d domina a un nodo n si todo camino desde el nodo inicial a
n pasa obligatoriamente por d.
As´ı, por ejemplo, seg´ un la figura 7.1 (p´agina 62):
1 domina TODOS
2 domina 2
3 domina TODOS - {1,2}
4 domina TODOS - {1,2,3}
62 CAP
´
ITULO 7. OPTIMIZACI
´
ON DE C
´
ODIGO
10 9
8
7
6 5
4
1
3 2
(a) Grafo de Flujo
6 5
10 9
8
7
4
1
3 2
(b)
´
Arbol de Dominaci´on
Figura 7.1: Grafo de Flujo y
´
Arbol de Dominaci´on.
5 domina 5
6 domina 6
7 domina 7,8,9,10
8 domina 8,9,10
9 domina 9
10 domina 10
En el an´alisis de c´odigo, los nodos se identifican con bloques de instrucciones.
Propiedades de los lazos
Los lazos tienen una serie de propiedades que debemos considerar:
Un lazo tendr´a un s´olo punto de entrada, que domina a todos los nodos
del lazo.
7.3. AN
´
ALISIS DE FLUJO 63
Debe existir al menos una forma de iterar, es decir, hay al menos un
camino hacia el encabezamiento.
Para localizar lazos el m´etodo es buscar aristas cuyas cabezas dominen a
las colas.
7.3. An´alisis de Flujo
El an´alisis de flujo consiste en recopilar informaci´on de variables, expresiones, etc.,
por ejemplo d´onde se definen, hasta d´onde llegan, d´onde se modifican,. . . a trav´es del
´arbol de an´alisis sint´actico.
Para ello se usan ecuaciones, y la ecuaci´on base es:
sal[S] = gen[S] ∪ (ent[S] −desact[S])
donde
S es un bloque de c´odigo
sal[S] representa las variables que
salen activas tras la ejecuci´on de S
gen[S] las variables que toman valor en S
ent[S] las variables que llegan activas a S
desact[S] las variables que son redefinidas en S
Claro est´a que, cuando hablamos de variables, tambi´en podemos hablar de expresiones
e incluso punteros y llamadas a funciones. Sin embargo, nos ce˜ niremos a las primeras por
simplicidad.
El tipo de an´alisis de flujo que se realice (hay varias estrategias diferentes) marcan su
diferencia en la definici´on del c´alculo de los conjuntos sal, gen, ent y desact.
En el an´alisis de bloques de c´odigo, se establecen puntos entre sentencias y tambi´en
entre cada par de bloques. Un camino de un punto p
1
a un punto p
n
es una secuencia de
puntos p
1
, p
2
, p
3
, . . . , p
n
de forma que p
i
es el punto que precede a una proposici´on y p
i+1
es el que la sigue, o bien p
i
es el final de un bloque y p
i+1
es el comienzo del siguiente.
7.3.1. Definiciones de Alcance
Llamamos definici´on de una variable x a una proposici´on que asigna un valor a x
´o que puede asignarlo. En el primer caso se concreta y se habla de definici´on no ambigua.
Llamamos alcance de una definici´on d a un punto p si existe un camino desde el
siguiente punto a d hasta p sin que la definici´on se desactive. Una definici´on se desactiva
si durante el camino a otro punto se define de nuevo.
64 CAP
´
ITULO 7. OPTIMIZACI
´
ON DE C
´
ODIGO
Veremos a continuaci´on los valores que pueden tomar en un bloque de c´odigo los
conjuntos sal, gen, ent y desact.
Bloque ´ unico
Para el caso m´as sencillo, el de un bloque ´ unico de c´odigo, tenemos que:
Punto entrada
Punto salida
S d: a:=b+c
gen[S] = ¦d¦
desact[S] = D
a
−¦d¦
sal[S] = gen[S] ∪ (ent[S] −desact[S])
donde D
a
representa todas las definiciones de la variable a del programa.
Secuencia
Dada una secuencia de bloques de instrucciones:
S
S1
S2
gen[S] = gen[S
2
] ∪ (gen[S
1
] −desact[S
2
])
desact[S] = desact[S
2
] ∪ (desact[S
1
] −gen[S
2
])
ent[S
1
] = ent[S]
ent[S
2
] = sal[S
1
]
sal[S] = sal[S
2
]
7.3. AN
´
ALISIS DE FLUJO 65
Bifurcaci´on
El an´alisis de sentencias de control tipo if y algunos saltos es dependiente del tipo de
an´alisis que se est´e realizando. Nosotros consideraremos que ambas ramas se activan.
S S2 S1
gen[S] = gen[S
1
] ∪ gen[S
2
]
desact[S] = desact[S
1
] ∩ desact[S
2
]
ent[S
1
] = ent[S]
ent[S
2
] = ent[S]
sal[S] = sal[S
1
] ∪ sal[S
2
]
Bucle
Por ´ ultimo, el an´alisis de bucles o lazos, no encierra ning´ un secreto:
S1
S
gen[S] = gen[S
1
]
desact[S] = desact[S
1
]
ent[S
1
] = ent[S] ∪ sal[S
1
] = ent[S] ∪ gen[S
1
]
sal[S] = sal[S
1
]
66 CAP
´
ITULO 7. OPTIMIZACI
´
ON DE C
´
ODIGO
Demostraci
´
on.-
Partimos de
ent[S
1
] = ent[S] ∪ sal[S
1
]
sal[S
1
] = gen[S
1
] ∪ (ent[S
1
] −desact[S
1
])
que escribiremos, por comodidad,
E
1
= E ∪ X
1
X
1
= G
1
∪ (E
1
−D
1
)
donde E, G
1
y D
1
son “constantes”.
Procederemos por inducci´on:
Iteraci´on 1
E
0
1
= E
X
0
1
= G
1
∪ (E −D
1
)
Iteraci´on 2
E
1
1
= E ∪ X
0
1
= E ∪ [G
1
∪ (E −D
1
)] = E ∪ G
1
X
1
1
= G
1
∪ (E
1
1
−D
1
) = G
1
∪ [(E ∪ G
1
) −D
1
] = G
1
∪ (E −D
1
)
(y as´ı sucesivamente; no necesitamos seguir porque ya hemos obtenido
E = E ∪ G
1
, que es lo que pretend´ıamos)
Dado un ´arbol sint´actico, su recorrido hacia arriba arrastrando atributos sintetizados
permite obtener gen y desact, mientras que un posterior recorrido en profundidad hacia
abajo teniendo en cuenta atributos heredados (del padre y/o hermanos) permite obtener
ent y sal.
7.3.2. Notaci´on Vectorial
El an´alisis de flujo de datos, como ya hemos mencionado, suele acometerse por bloques
preferentemente a por instrucciones. Se definen entonces vectores que representan lo que
se genera/desactiva:
V = (a
1
a
2
. . . a
n
)
con n =n´ umero de definiciones del programa. En el bloque S
i
, la componente a
i
= 1
indica que se ha generado o desactivado (seg´ un el vector que se considere) la definici´on i.
Las ecuaciones que se aplican no var´ıan, de modo que simplemente recordemos que,
entre vectores binarios:
A − B = V
A
∧ V
B
A ∪ B = V
A
∨ V
B
A ∩ B = V
A
∧ V
B
7.3. AN
´
ALISIS DE FLUJO 67
7.3.3. Soluci´on Iterativa para las ecuaciones de Flujo de Datos
Definiciones de alcance (alcance de definiciones)
Definimos un bloque como una proposici´on de asignaci´on o una cascada de proposi-
ciones de asignaci´on.
Partimos de que se ha calculado genera y desactiva de cada bloque para todos los
bloques del programa, y de que:
ent[B] =

predecesores
sal[P] P ∈ predecesores
sal[B] = gen[B] ∪ (ent[B] −desact[B])
y bajo estas condiciones el algoritmo es:
Entrada: gen[B] y desact[B] para cada B
Salida : ent[B] y sal[B] para cada B
ent[Bi] := O;
para cada Bi hacemos
sal[Bi] := gen[Bi];
cambio := true;
mientras (cambio) hacemos
cambio := false;
para cada Bi hacemos
ent[Bi] := Up sal[P]; /* P predecesores */
salant := sal[Bi];
sal[Bi] := gen[Bi] U (ent[Bi] - desact[Bi]);
si (sal[Bi] <> salant) entonces
cambio := true;
fin-para
fin-mientras
fin-para
7.3.4. An´alisis de Expresiones Disponibles
Decimos que una expresi´on x + y
2
est´a disponible en un punto P si todo camino,
no necesariamente sin lazos, desde el nodo inicial hasta P eval´ ua x + y y despu´es de la
´ ultima evaluaci´ on antes de P no hay asignaci´on ni de x ni de y.
Decimos que un bloque B desactiva una expresi´on x +y si asigna un valor a x o a y.
Decimos que un bloque B genera una expresi´on x+y si eval´ ua x+y y no genera una
redefinici´on de x ´o de y.
2
El signo “+” no significa aqu´ı la operaci´on de suma, sino cualquier operaci´on en general.
68 CAP
´
ITULO 7. OPTIMIZACI
´
ON DE C
´
ODIGO
Expresaremos:
e gen[B
i
] = expresi´on que genera el bloque B
i
e desact[B
i
] = expresi´on que desactiva el bloque B
i
U = universal
∅ = vac´ıo
Y usaremos las ecuaciones:
sal[B
i
] = e gen[B
i
] ∪ (ent[B
i
] −e desact[B
i
])
ent[B
i
] =

p
sal[P
i
] B
i
,= B
inicial
ent[B
i
] = ∅ B
i
= B
inicial
Como se puede observar, el an´alisis anterior daba todo el alcance posible, sin embargo
ahora queremos ser muy conservadores para poder usar el valor de la expresi´on (en lugar
de etiquetar las asignaciones, como antes, ahora se etiquetan las expresiones). El algoritmo
es:
Entrada: e_gen[Bi] y e_desact[Bi] para todo Bi
Salida : ent[Bi] y sal[Bi] para todo Bi
ent[Bi] := O;
sal[Bi] := e_gen[Bi];
para todo Bi<>B1 hacemos
sal[Bi] := U - desact[Bi];
cambio := true;
mientras (cambio) hacemos
cambio := false;
para cada Bi<>B1 hacemos
ent[Bi] := ^p sal[P];
salant := sal[Bi];
sal[Bi] := e_gen[Bi] U (ent[Bi] - e_desact[Bi]);
si (salant <> sal[Bi]) entonces
cambio := true;
fin-para
fin-mientras
7.3.5. An´alisis de Variables Activas
Una variable a es activa en un punto P si se puede utilizar el valor de a en alg´ un
camino que comience en P.
Este an´alisis pretende liberar memoria, de modo que estar activo significa que se puede
(y de hecho, se hace) usar el valor; si no se vuelve a usar, entonces no se est´a activo. Esta
filosof´ıa obliga a hacer el an´alisis en el c´odigo al rev´es, de abajo hacia arriba.
7.3. AN
´
ALISIS DE FLUJO 69
Llamamos entrada al conjunto de variables activas al comienzo de un bloque. Llama-
mos salida al conjunto de variables activas a la salida de un bloque. Llamamos definidas
al conjunto de variables a las que se les asigna un valor en el bloque. Por ´ ultimo, se llama
uso al conjunto de variables cuyos valores se utilizan antes de cualquier definici´on de la
variable.
Las ecuaciones usadas en este tipo de an´alisis son:
ent[B
i
] = uso[B
i
] ∪ (sal[B
i
] −def[B
i
])
sal[B
i
] =

s
ent[S
i
] S
i
∈ sucesores
El algoritmo es el siguiente:
Entrada: grafo de flujo G y def[Bi], uso[Bi] para todo Bi
Salida : sal[Bi] para todo Bi
para todo Bi hacemos
sal[Bi] == O;
para todo Bi hacemos
ent[Bi] := uso[Bi];
mientras ocurren cambios en los conjuntos ent[Bi] hacemos
para cada Bi hacemos
sal[Bi] := Us ent[S]; /* S sucesores */
ent[Bi] := uso[Bi] U (sal[Bi] - def[Bi]);
fin-para
fin-mientras
70 CAP
´
ITULO 7. OPTIMIZACI
´
ON DE C
´
ODIGO
Cap´ıtulo 8
Errores
En este breve tema comentaremos algunas generalidades acerca de los errores en el
´ambito que nos ocupa.
8.1. Tipos de errores
Consideraremos la exitencia de varios tipos de errores:
Errores l´exicos, son aqu´ellos en los que donde se esperaba una palabra reservada del
lenguaje aparece otra (por ejemplo, poner far en lugar de for).
Errores sint´acticos, son aqu´ellos que provocan que no se encuentre un ´arbol sint´ acti-
co que analice el programa (por ejemplo, cuando falta un par´entesis).
Errores sem´anticos, aparecen cuando llevamos a cabo acciones inadecuadas sobre
elementos incorrectos (por ejemplo, hacer la ra´ız cuadrada de una variable de tipo
string).
Errores de compilaci´on, aparecen por limitaciones propias del compilador (algunos
no permiten m´as de 10 bucles anidados, otros no m´as de 30 procedimientos,. . . ).
Errores de ejecuci´on, se deben a descuidos del programados (situaciones como ac-
cesos a matrices fuera de rango, a ficheros no abiertos, . . . ).
8.2. Recuperaci´on de errores
Seg´ un el tipo de error ante el que nos encontremos, ser´an susceptibles de ser realizadas
diferentes medidas de correci´on. En particular, en compiladores puede ser interesante para
nosotros intentar subsanar errores lexicogr´aficos, tanto aqu´ellos que suponen la sustitu-
ci´on de unos elementos por otros, como la inclusi´on de elementos extra˜ nos entre elementos
correctos, o la desaparici´on de alg´ un elemento.
Afrontaremos, pues, la correcci´on de errores lexicogr´aficos desde estas perspectivas.
71
72 CAP
´
ITULO 8. ERRORES
8.2.1. Correcci´on de errores de cambio
Supone admitir palabras del lenguaje con uno o m´as errores. Se define el operador
de cambio
1
:
C(a) = T −¦a¦
de tal modo que
C
1
(x) = ¦y/y ∈ T

∧ y resultado de 1 cambio en x¦
C
2
(x) = ¦y/y ∈ T

∧ y resultado de 2 cambios en x¦
. . .
C
n
(x) = ¦y/y ∈ T

∧ y resultado de n cambios en x¦
Adem´as, por convenio, si [x[ < n, entonces C
n
(x) = ∅.
De modo que para corregir errores, es decir, para admitir palabras con alg´ un error
durante el proceso de compilaci´on, si tenemos una gram´atica G = (N, T, P, S), crearemos
una gram´atica G

= (N, T, P

, S) en la que las reglas ser´an
P

= P ∪ ¦reglas de las operaciones de cambio¦
de tal forma que el “nuevo lenguaje” aceptado puede expresarse como
L(G

) = ¦y/y ∈ T

∧ y ∈ C
n
(x) ∧ x ∈ L(G), n ≥ 0¦
La correcci´on de errores se implementa mediante un esquema de traducci´on, dado por
EDT(N, T
e
, T
s
, P, S), definido seg´ un la estructura:
A → α
i
, α
i
(no existen errores)
A → µ , α
i
(con µ = C
1

i
))
A → β , α
i
(con β = C
2

i
))
. . .
A → δ , α
i
(con δ = C
n

i
))
8.2.2. Correcci´on de errores de borrado
Del mismo modo, se define el operador de borrado:
B(a) = λ ´o ε ∀a ∈ T
de tal forma que
B
n
(x) = ¦ε si [x[ < n¦
= ¦y/y ∈ T

∧ y resultado de eliminar n caracteres en x¦
El error de borrado es muy f´acil de detectar en lenguajes donde se definan todas las
palabras de la misma longitud.
1
Que s´olo act´ ua sobre elementos terminales.
8.3. MODO P
´
ANICO 73
8.2.3. Correcci´on de errores de inclusi´on
El operador de inclusi´on se define:
I(a) = xa + ax ∀a ∈ T ∀x ∈ T
de tal forma que si T = ¦a
1
, a
2
, . . . , a
n
¦, entonces
I(a) = ¦aa
1
+ aa
2
+ . . . + aa
n
+ a
1
a + a
2
a + . . . a
n

8.3. Modo p´anico
Algunos compiladores, cuando encuentran un error, detienen el an´alisis. Otros, en
cambio, buscan el principio y final de “secci´on” o “bloque” entre los que se encuentra el
error, lo ignoran, y siguen analizando el resto del c´odigo. Este modo de comportarse es lo
que se conoce como modo p´anico.
74 CAP
´
ITULO 8. ERRORES
Cap´ıtulo 9
La Tabla de S´ımbolos
Ya hemos hablado en alguna ocasi´on de las tablas de s´ımbolos. Independiente-
mente del modo de almacenamiento, la tabla de s´ımbolos o TDS es una estructura
utilizada por los compiladores para almacenar informaci´on sobre variables (nombre, tipo,
´ambito,. . . ) y procedimientos (nombre, par´ametros de entrada y salida, car´acter de los
par´ametros de entrada —por valor o por referencia—,. . . ).
La mayor´ıa de los compiladores mantiene una TDS por tipo de objeto (una para
variables, otra para procedimientos,. . . ), y suelen ser de car´acter est´atico. Su utilidad es
patente al principio del proceso de compilaci´on, pues en el paso a c´odigo objeto ya dejan
de ser necesarias.
Veremos a continuaci´ on una serie de formas de implementar las TDS.
9.1. Tipos
9.1.1. TDS lineal
Consiste en ir almacenando la informaci´on sobre los objetos seg´ un se va obteniendo,
linealmente. La b´ usqueda se realiza, por tanto, de manera secuencial.
9.1.2. TDS ordenada
Se determina un ordenamiento, por ejemplo, el orden alfab´etido de identificadores.
Una vez definido, la inserci´on se realiza en el lugar adecuado, reestructurando la TDS en
caso necesario, y la b´ usqueda suele ser dicot´omica, r´apida y f´acil de implementar.
9.1.3. TDS ´arbol binario
La TDS ´arbol binario guarda una estructura en forma de ´arbol, tal como su nombre
indica y se puede observar en la figura 9.1 (p´agina 76). Pese a que se desperdicia un
poco m´as de espacio adicional en los punteros, es uno de los tipos m´as utilizados, pues
su implementaci´ on no es compleja y tanto inserci´on como b´ usqueda tienen la misma
complejidad.
75
76 CAP
´
ITULO 9. LA TABLA DE S
´
IMBOLOS
AB
AA BC
BA BD
Figura 9.1: TDS en forma de ´arbol binario.
9.1.4. TDS con hashing
Dado un identificador C con n caracteres, C = c
1
c
2
. . . c
n
, la funci´on de hash t´ıpica es:
Hashing(C) = (α
0
+
n

i=0
α
i
c
i
) modulo T
donde
α
0
es la direcci´on o posici´on inicial, donde empieza en memoria la TDS
α
i
es el valor num´erico asignado a c
i
T es el tama˜ no de la TDS
Para otro tipo de claves (identificadores) no s´olo compuestos por caracteres (como por
ejemplo i2), podr´ıa adoptarse:
Hashing(C) = (ord(id[i] ∗ 10) + ord(id[2])) modulo T
Hashing abierto
Con la mayor´ıa de las funciones de hash existe la posibilidad de colisiones. La t´ecnica
de hashing abierto establece que en caso de conflicto el valor se introduce en la siguien-
te posici´on libre, realizando la exploraci´on linealmente a partir del lugar original. En
b´ usqueda, si el valor que se pretende encontrar no se halla en la posici´on que le corres-
ponde, se sigue buscando secuencialmente a partir de la misma. En la mayor´ıa de las
ocasiones se mantienen punteros de enlace por comodidad y rapidez.
9.1. TIPOS 77
Hashing con overflow
El hashing con overflow es otra variante que pretende solucionar el problema de las
colisiones. En este caso, los valores conflictivos van a parar a una segunda tabla, donde
se almacenan linealmente enlazados.
Hashing con encadenamiento
El hashing con encadenamiento perfeciona la t´ecnica del hashing con overflow y esta-
blece que la primera TDS contenga s´olo punteros la TDS de segundo nivel.
9.1.5. TDS enlazadas
Como hemos mencionado al principio, en la tabla de s´ımbolos suelen almacenarse da-
tos relativos a variables y procedimientos. Por lo que respecta a las variables, hab´ıamos
comentado que puede incluirse el nombre, tipo,. . . y tambi´en el alcance (bloques del pro-
grama en los que la variable est´a activa). El m´etodo de las TDS enlazadas evita la inclusi´on
de este dato en la TDS definiendo una tabla por bloque del programa y relacion´andolas
entre s´ı.
Seg´ un este m´etodo, podemos definir un identificador (variable) en relaci´on a su am-
plitud:
Un identificador se declara al principio de un bloque
1
y se puede usar dentro de ´el.
Un identificador declarado en un bloque puede ser udaso dentro de los bloques
interiores a la definici´on, excepto cuando se hace otra definici´on de variable con el
mismo bloque (en dicho bloque interior).
Este es el m´etodo que se usa en la mayor´ıa de los compiladores actuales. La estrategia
de b´ usqueda consiste en comprobar si el identificador est´a en la tabla del bloque en que se
encuentra la referencia, y si no es as´ı, seguir el puntero a la tabla del bloque que contiene
al bloque actual y buscar all´ı. Se procede recursivamente hasta que se encuentra o se llega
al bloque principal.
1
En algunos lenguajes esto no es necesario que se cumpla estrictamente.
78 CAP
´
ITULO 9. LA TABLA DE S
´
IMBOLOS
Cap´ıtulo 10
Representaci´on de la Informaci´on
y Gesti´on de Memoria
10.1. Representaci´on de la Informaci´on
Aunque ya hemos dado pinceladas al respecto en temas anteriores, volveremos ahora a
hablar con un poco m´as de detalle de la representaci´on de las estructuras de informaci´on.
10.1.1. Representaci´on de arrays y matrices
La representaci´ on de un array es simple, pues no es m´as que una colecci´on de n objetos
iguales que se ubican contiguos en memoria.
En el caso de las matrices (arrays bidimensionales) M[b
1
. . . a
1
, b
2
. . . a
2
], tenemos dos
funciones de acceso seg´ un su almacenamiento:
Almacenamiento por filas:
Dir(M
ij
) = M + k [(i −b
1
) C + (j −b
2
)]
donde M es la direcci´on base, k es el n´ umero de bytes por elemento y C es el n´ umero
de elementos por fila o, lo que es lo mismo, el n´ umero de columnas.
Almacenamiento por columnas:
Dir(M
ij
) = M + k [(i −b
2
) F + (i −b
1
)]
donde M es la direcci´on base, k es el n´ umero de bytes por elemento y F es el n´ umero
de elementos por columna o, lo que es lo mismo, el n´ umero de filas.
Representaci´on con vectores enlazados
Otra forma de representar matrices es mediante vectores: se tiene un vector de punteros
(uno por fila) que apuntan a su vez a los vectores-fila que forman el array bidimensional.
Esta representaci´on ocupa un poco m´as de espacio (el vector de punteros), pero requiere
bastantes menos c´alculos para acceder:
79
80 CAP
´
ITULO 10. REP. DE INFORMACI
´
ON Y GESTI
´
ON DE MEMORIA
Dir(M
ij
) = (vector + i −1) + j −1
donde (vector +i −1) es el valor del puntero correspondiente (la direcci´on). Como se
puede ver, simplemente hay que hacer sumas y restas.
Representaci´on de matrices de n dimensiones
Dada una matriz:
M[i
1
. . . s
1
, i
2
. . . s
2
, . . . , i
n
. . . s
n
]
donde
i
i
= l´ımites inferiores
s
i
= l´ımites superiores
n = n´ umero de dimensiones
y, obviamente i
i
≤ s
i
. Si llamamos
e
1
= s
1
−i
1
+ 1
e
2
= s
2
−i
2
+ 1
. . .
e
n
= s
n
−i
n
+ 1
entonces para acceder a M[j
1
, j
2
, . . . , j
n
] debemos hacer
M + (j
1
−i
1
) ∗ e
2
∗ e
3
∗ . . . ∗ e
n
+
+ (j
2
−i
2
) ∗ e
3
∗ . . . ∗ e
n
+
+ . . . +
+ (j
n−1
+ i
n−1
) ∗ e
n
+
+ (j
n
+ i
n
)
Vector “Dope” o Vector de Informaci´on
Para representar este tipo de estructura, veremos por ´ ultimo un m´etodo que consiste
en almacenar un vector de informaci´on con la siguiente forma:
i1 s1 e1
i2 s2 e2
...
in sn en
Numero de dimensiones
Termino constante
Direccion de comienzo
10.2. GESTI
´
ON DE MEMORIA PROPORCIONADA POR EL COMPILADOR 81
La utilidad de esta estrategia reside en la recopilaci´on de la m´axima informaci´on posible
sobre las matrices, a fin de que no conlleve m´as c´alculos el acceso que la propia operaci´on
que se pretend´ıa realizar sobre ellas. Adem´as, esta estructura permite la implementaci´on
del dinamismo con arrays bidimensionales de manera sencilla.
10.1.2. Representaci´on de cadenas y tiras de caracteres
Las cadenas suelen almacenarse contiguas en memoria, determinando un car´acter que
se˜ nala el fin de las mismas. Los mayores problemas los presentan las operaciones de ma-
nejo de tiras de caracteres (copia, concatenaci´on), ya que las ubicaciones de las cadenas
originales en memoria pueden ser distantes y crear una nueva cadena en cada operaci´on
supone demasiado moviento de datos y reserva de espacio en el data block. Lo que se suele
hacer es asociar las cadenas mediante punteros, evitando de esta manera el mencionado
tr´afico de operacones en memoria. Claro que esto puede derivar en una situaci´on donde la
proliferaci´on de cadenas segmentadas y punteros sea demasiado costosa; en ese caso, algu-
nos compiladores incluyen rutinas de reagrupamiento que se disparan autom´aticamente.
10.1.3. Representaci´on de registros
Los registros (tambi´en conocidos como records) suelen almacenarse contiguos en me-
moria. En la TDS se guarda informaci´on acerca del n´ umero y tipo de sus campos, de
modo que el acceso a un determinado dato siempre es f´acilmente calculable.
10.2. Gesti´on de memoria
proporcionada por el compilador
Los compiladores suelen proporcinar una serie de rutinas que son incorporadas al
c´odigo del usuario y que se encargan de gestionar la detecci´on de errores de ejecuci´on (por
ejemplo, divisiones por cero), de la gesti´on de variables locales y globales, del control del
tama˜ no y situaci´on de los objetos en la memoria, etc.
Zona programas
S.O.
Dispositivos
Cod. IRQ
Pantalla
(a) M. principal.
Datos estaticos
Codigo
Pila
Monticulo
(b) M. proceso.
82 CAP
´
ITULO 10. REP. DE INFORMACI
´
ON Y GESTI
´
ON DE MEMORIA
Las variables locales de los procedimientos se colocan en la pila, de forma que meca-
nismos como la recursi´on puedan funcionar adecuadamente. De aqu´ı surge el concepto de
registro de activaci´on, que veremos.
Algunos lenguajes s´olo tienen gesti´on est´atica de memoria (por ejemplo, en F66 nada
puede crecer en tiempo de ejecuci´on y no existe la recursividad), mientras que la gran
mayor´ıa tiene asignaci´on din´amica.
10.2.1. Registro de activaci´ on
Los registros de activaci´on son la unidad estructural de la pila y almacenan:
Datos locales del procedimiento
Par´ ametros que se le pasan
Datos temporales introducidos por el compilador
Datos sobre el estado de la m´aquina antes de la ejecuci´on del procedimiento (estado
de la CPU: registros, flags,. . . )
Puntero al registro de activaci´on anterior
A
llama a
B
A B
llamador llamado
A
B
pila
Un procedimiento es recursivo si se puede activar antes de la finalizaci´on de la acti-
vaci´ on anterior.
Los registros de activaci´on se pueden organizar en forma de ´arbol, que recibe el nombre
de ´arbol de activaci´ on. En este ´arbol, se dice que un nodo A es padre de un nodo B si
el control fluye de A hacia B. Del mismo modo, se dice que un nodo A est´a a la izquierda
de un nodo B si se ejecuta A antes que B.
10.2.2. Secuencia de llamada y retorno
La secuencia de llamada consiste en guardar en el registro de activaci´ on el estado
de la m´aquina, asignar los valores a las variables locales y comenzar la ejecuci´on del
procedimiento.
Por su parte, la secuencia de retorno recupera los datos del campo estado del
registro de activaci´ on para restaurar la situaci´on anterior y borra el mencionado registro
para continuar la ejecuci´on.
Existen dos tipos de punteros implementados en la estructura de registros de activa-
ci´on: est´aticos y din´amicos. Los est´aticos permiten buscar variables a las que tiene acceso
10.2. GESTI
´
ON DE MEMORIA PROPORCIONADA POR EL COMPILADOR 83
procedimiento
llamado
procedimiento
llamador
valor devuelto y parametros
enlace de control
estado
datos temporales y locales
el procedimiento pero que no son locales y los din´amicos son referencias al procedimiento
llamador (son los que realmente permiten implementar la pila).
Las variables globales del programa se ubican en la parte de datos est´aticos del proceso,
de forma que se ahorra el tener que colocarlos repetidamente en los registros de activaci´ on
y se consigue que est´en accesibles para todos los subprocesos.
10.2.3. Subprogramas
Los argumentos con que se llama a un subprograma pueden ser:
Par´ametros o Par´ametros ficticios, variables o identificadores que solamente apare-
cen en el subprograma que es llamado.
Argumentos o Par´ametros efectivos, variables o expresiones que aparecen en el pro-
cedimiento llamador.
Adem´as, la llamada puede clasificarse:
S´olo lectura: al llamar a una funci´on f(a), en f se trabaja con una copia de a.
S´olo escritura: al llamar a f(a), en f se trabaja con una copia de a cuyo valor inicial
no est´a determinado (puede ser un valor por defecto) y al finalizar se copia su valor
al verdadero a, que act´ ua, por tanto, como un par´ametro de devoluci´on.
Lectura y escritura
• Por valor o resultado: al llamar a f(a), en f se lee de a y se escribe en una
copia de a, volc´andose su valor en el verdadero a al final del procedimiento.
84 CAP
´
ITULO 10. REP. DE INFORMACI
´
ON Y GESTI
´
ON DE MEMORIA
• Por direcci´on: al llamar a f(a), en f se trabaja directamente con a, tanto para
lectura como para escritura (se tiene la direcci´on).
• Por nombre: el procedimiento al que se llama no recibe una direcci´on o un
contenido, sino un “literal”, de forma que, seg´ un su contexto, le dar´a el valor
correspondiente.
10.2.4. Estructuras COMMON y EQUIVALENCE en FORTRAN
En FORTRAN se pueden establecer relaciones de equivalencia entre variables con res-
pecto a la posici´on f´ısica que ocupan en un bloque com´ un (bloque que puede crecer
din´amicamente). Esto se hace con sentencias del tipo:
EQUIVALENCE A, B+100
EQUIVALENCE C, D-40
EQUIVALENCE A, C+30
EQUIVALENCE E, F
Cada bloque tiene un l´ıder, que se utiliza como ra´ız para construir el ´arbol de equiva-
lencia.
D 0
B −110 C −40
A 100
Esta estructura viene del ensamblador, y los compiladores o lenguajes que la utilizan
(como FORTRAN) emplean en realidad una variante en la que, en el ´arbol de equivalencia,
el l´ıder est´a unido mediante enlaces directos a la hoja m´as a la izquierda y a la hoja m´as
a la derecha, que son respectivamente los extremos inferior y superior del bloque COMMON.
10.3. Montadores y Cargadores
Los montadores (linker) resuelven las referencias externas que existen en los ob-
jetos a montar, para lo que utilizan una tabla. Durante el proceso, se detectan errores
(“Unresolved external”) y si no aparecen enlazan todos los objetos en un ´ unico objeto
entendible por el cargador.
Los cargadores (loader) cargan en memoria un objeto, resolviendo el problema de
la reubicaci´on. En los programas, existen partes reubicables y partes no reubicables (como
el c´odigo de las interrupciones, por ejemplo). Tras cargarlo en memoria, el cargador da
el control al programa, tras establecer punteros con valor adecuado (puntero de inicio de
programa. . . ), valores de los registros de la CPU, flags, etc.
10.4. FICHEROS OBJETO 85
10.4. Ficheros objeto
Contienen una serie de registros de la forma:
<cabecera><texto><checksum>
donde la cabecera contiene, a su vez, <longitud><tipo> y donde el checksum repre-
senta la comprobaci´on de paridad para el control de errores.
Entre los tipos de registros que puede contener un fichero objeto podemos encontrar:
De definici´on de bloques Contienen:
<cabecera><datos_bloque><checksum>
donde
<cabecera> = <longitud><tipo_definicion_bloque>
<datos_bloque> = <longitud><nombre_bloque><tipo_bloque>
donde el tipo del bloque se refiere a si es reubicable o no, por ejemplo.
De referencias externas Contienen:
<cabecera><datos_externos><checksum>
donde
<datos_externos> = <direccion><nombre_bloque_externo>
De texto con iteraci´on Se usan para rellenar zonas de memoria con un
dato:
<cabecera><bloque_iteracion><checksum>
donde
<bloque_iteracion> = <direccion><contador><contenido>
donde se repetir´a contenido contador veces.
Otros Como registros de principio de bloque, final de bloque,. . .
10.5. Int´erpretes
Fueron muy usados en un principio debido a que los equipos ten´ıan poca memoria y era
preferible tener cargado siempre el int´erprete y el c´odigo fuente a tener un compilador y el
c´odigo objeto; con el avance de la tecnolog´ıa, no obstante, fue decayendo posteriormente
casi por completo su utilizaci´on, frente a la de los compiladores. Actualmente, desde la
aparici´on de VBASIC y sobre todo de java, est´an volviendo a resurgir.
86 CAP
´
ITULO 10. REP. DE INFORMACI
´
ON Y GESTI
´
ON DE MEMORIA
Distinguimos dos tipos de int´erpretes:
Cl´asicos Son int´erpretes que van ejecutando el c´odigo fuente l´ınea a l´ınea tal
y como est´a tecleado.
Modernos Son int´erpretes que realmente generan un c´odigo intermedio sin
errores, que es el que es interpretado l´ınea a l´ınea.
Programa
fuente
Analizador
lexico
Analizador
sintactico
RPN
TDS
Interprete
Etapa analisis Ejecucion/interpretacion
datos entrada
datos salida
Figura 10.1: Estructura y funcionamiento de un int´erprete moderno.
Un ejemplo:
/* CODIGO FUENTE */
A := 9;
B := 8;
B := B+A;
WRITE B;
GOTO X;
/* CODIGO RPN */
A 9 := ;;
B 8 := ;;
B B A + := ;;
B WRITE ;;
X GOTO ;;
/* INTERPRETE */
case v[pos] of
ident, entero : apilar(v[op]); p:=p+1;
’+’ : sumar PCP + PCP - 1 e introducir el resto en la pila
‘‘write’’ : representar en pantalla rep
‘‘:=’’ : evaluar elemento PCP y ponerlo en direccion PCP - 1
end
´
Indice alfab´etico
´arbol
de derivaci´on, 27
sint´actico, 11
core, 42
lookahead, 42
acciones sem´anticas, 44
alfabeto, 9
de entrada, 16
de pila, 17
de salida, 18
algoritmo
de Thompson, 23
de Warshall, 31
detecci´on lenguaje vac´ıo, 13
eliminaci´on
recursividad por la izquierda, 15
reglas lambda, 14
reglas unitarias, 14
s´ımbolos in´ utiles, 13
an´alisis
por precedencia, 29
m´etodo del ´arbol, 30
m´etodo derivativo, 30
m´etodo matricial, 30
operador, 31
simple, 29
sem´antico, 43
sint´actico, 27
LL(1), 32
LL(K), 32
LR(1), 36
LR(K), 35
an´alisis de flujo, 63
analizador
l´exico, 21
atributos
heredados, 46
sintetizados, 46
aut´omata
con pila, 17
configuraci´on, 16
final, 16
inicial, 16
objetivo, 16
finito, 16
determinista, 16
no determinista, 16
lenguaje generado, 17
reconocedor por agotamiento de pila,
18
representaci´on gr´afica, 17
transici´on, 17
axioma, 10
c´odigo
a 3 direcciones, 54
generaci´on, 43
intermedio, 51
objeto, 51
optimizaci´on, 59
en c´odigo fuente, 59
cierre
reflexivo, 9
transitivo, 9
conjunto de traducci´on, 19
cuartetos, 53
definiciones de alcance, 63
derivaci´ on, 10
representaci´on gr´afica, 11
errores
recuperaci´on, 71
tipos, 71
87
88
´
INDICE ALFAB
´
ETICO
esquemas de traducci´on, 20
estado, 16
cerradura, 23
final, 16
inicial, 16
expresion regular
propiedades, 23
forma de traducci´on, 20
forma normal, 15
de Chomsky, 15
de Greibach, 15
formas sentenciales, 11
funci´on de transici´on, 16
gram´atica, 10
ambigua, 11
de contexto libre, 10
independiente del contexto, 10
limpia, 12
regular, 10
sensible al contexto, 10
tipos, 10
lenguaje, 11
metanoci´on, 14
notaci´on
polaca inversa, 52
palabra, 9
parsing
ascendente, 28
descendente, 28
producciones, 10
reflexividad, 30
reglas
cadena, 12
de producci´on, 10
de traducci´on, 20
lambda, 14
recursivas, 15
autoimbricadas, 15
por la derecha, 15
por la izquierda, 15
sem´anticas, 46
unitarias, 14
relaci´on
binaria, 30
complementaria, 30
de equivalencia, 30
traspuesta, 30
universal, 30
RPN, 52
s´ımbolo
accesible, 13
anulable, 14
in´ util, 13
no terminal, 10
terminable, 13
terminal, 10
scanner, 21
construccion, 21
simetr´ıa, 30
tabla
de s´ımbolos, 75
tercetos, 53
indirectos, 54
tipos
b´asicos, 43, 45
coerci´on, 49
comprobaci´on, 43
constructores, 43, 45
conversi´ on, 49
equivalencia, 48
polimorfismo, 49
sobrecarga, 49
tira de caracteres, 9
longitud, 9
nula, 9
potencia, 9
traducci´on
dirigida por la sintaxis, 43, 44
traductor
con pila, 19
finito, 18
transitividad, 30
variantes
´
INDICE ALFAB
´
ETICO 89
LR(1)
LALR, 36, 42
LR can´onico, 36, 40
SLR, 36, 38
90
´
INDICE ALFAB
´
ETICO
´
Indice de figuras
1.1. Esquema de las tareas de un compilador. . . . . . . . . . . . . . . . . . . . 7
2.1. Ejemplo de ´arbol sint´actico. . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Ejemplo de gram´atica ambigua. . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3. Relevancia en el orden de los algoritmos de simplificaci´on. . . . . . . . . . . . . 14
2.4. Representaciones de un aut´omata. . . . . . . . . . . . . . . . . . . . . . . . 17
3.1. Objetivo de un scanner. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2. Maneras de construir un scanner. . . . . . . . . . . . . . . . . . . . . . . . 22
3.3. Componentes b´asicos del m´etodo de Thompson. . . . . . . . . . . . . . . . 24
4.1. Tipos de parsing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2. Tipos de parsing, otra clasificaci´on. . . . . . . . . . . . . . . . . . . . . . . 28
4.3. Estructura de un parser LL(1). . . . . . . . . . . . . . . . . . . . . . . . . 33
4.4. Modelo de un analizador sint´actico LR(1). . . . . . . . . . . . . . . . . . . 36
5.1. Esquema de an´alisis sem´antico. . . . . . . . . . . . . . . . . . . . . . . . . 44
7.1. Grafo de Flujo y
´
Arbol de Dominaci´on. . . . . . . . . . . . . . . . . . . . . 62
9.1. TDS en forma de ´arbol binario. . . . . . . . . . . . . . . . . . . . . . . . . 76
10.1. Estructura y funcionamiento de un int´erprete moderno. . . . . . . . . . . . 86
91
92
´
INDICE DE FIGURAS
´
Indice de cuadros
2.1. Correspondencia gram´aticas-aut´ omatas. . . . . . . . . . . . . . . . . . . . 16
4.1. Algoritmo de Warshall. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.2. Precedencia usual entre los operadores matem´aticos. . . . . . . . . . . . . . 32
4.3. Algoritmo de an´alisis LL(1). . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.4. Algoritmo de c´alculo de cerradura. . . . . . . . . . . . . . . . . . . . . . . 39
4.5. Construcci´on de la colecci´on can´onica LR(0). . . . . . . . . . . . . . . . . . 39
4.6. Algoritmo de c´alculo de cerradura para LR-can´onico. . . . . . . . . . . . . 41
4.7. Algoritmo de c´alculo de Ir a para LR-can´onico. . . . . . . . . . . . . . . . 41
4.8. Construcci´on del conjunto de los elementos de an´alisis LR-can´onico. . . . . 41
5.1. Gram´atica de referencia. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.2. Algoritmo de comprobaci´on de equivalencia estructural. . . . . . . . . . . . 49
5.3. Comprobaci´on de tipos para coerci´on de entero a real. . . . . . . . . . . . . 50
6.1. Notaci´on Polaca Inversa (RPN). . . . . . . . . . . . . . . . . . . . . . . . . 52
6.2. Traducci´on a RPN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.3. Notaci´on de cuartetos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.4. Modos de direccionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
93
94
´
INDICE DE CUADROS
Bibliograf´ıa
[1] Bennett, J.P.
Introduction to Compiling Techniques.
Mc-Graw Hill International, 1996.
2
a
edici´on, Series in Software Engineering.
[2] Gal´an Pascual, C. Sanch´ıs Llorca, F.J.
Compiladores. Teor´ıa y construcci´on.
Paraninfo S.A., 1988.
Madrid.
[3] Mason, Tony y Levine, John y Brown, Dough.
Lex & Yacc.
O’Reilly, 1992.
2
a
edici´on .
[4] Aho, Alfred V. y Sethi, Ravi y Ullman, Jeffrey D.
Compiladores. Principios, t´ecnicas y herramientas.
Addison Wesley Longman, 1998.
1
a
reimpresi´on .
95

´ Indice general
1. Introducci´n o 2. Conceptos B´sicos a 2.1. Lenguajes y Gram´ticas . . . . a 2.1.1. Definiciones . . . . . . . 2.1.2. Gram´ticas. Tipos . . . a 2.1.3. Lenguajes . . . . . . . . 2.2. Gram´ticas y Aut´matas . . . . a o 2.2.1. Aut´matas . . . . . . . . o 2.3. Traductores . . . . . . . . . . . 2.3.1. Esquemas de traducci´n o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 9 9 9 10 11 16 16 18 20 21 23 23 23 23 27 27 29 29 31 32 32 35 36 43 44 45 45 48 49 49

3. An´lisis L´xico. Scanners a e 3.1. Construcci´n de scanners mediante AFs . . . . . . . . . . . . . o 3.1.1. Expresiones Regulares. Propiedades . . . . . . . . . . . . 3.1.2. Algoritmo (m´todo) de Thompson . . . . . . . . . . . . . e 3.1.3. Transformaci´n de un AFND con λ-transiciones en AFD o 4. An´lisis Sint´ctico. Parsers a a 4.1. Tipos de parsing . . . . . . . 4.2. An´lisis por precedencia . . . a 4.2.1. Precedencia Simple . . 4.2.2. Precedencia Operador 4.3. An´lisis sint´ctico LL(K) . . . a a 4.3.1. An´lisis LL(1) . . . . . a 4.4. An´lisis sint´ctico LR(K) . . . a a 4.4.1. An´lisis LR(1) . . . . . a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5. An´lisis Sem´ntico a a 5.1. Notaci´n . . . . . . . . . . . . . . . . o 5.2. Sistemas de Tipos . . . . . . . . . . . 5.2.1. Tipos b´sicos . . . . . . . . . a 5.2.2. Equivalencia de expresiones de 5.2.3. Conversores de tipo . . . . . . 5.2.4. Sobrecarga . . . . . . . . . . . 3

. . . . . . . . . tipo . . . . . .

. . . . . . . .2. . Notaci´n Polaca Inversa (RPN) o 6. . . . . .2. . Definiciones de Alcance . o 7. . . . . . . . .4. . . . .1. . . . . . . . . TDS ´rbol binario a 9. . . . . . . . . 9. .1. . . . . . .1. . . . . e o o 7. . . . . o 6. M´quina Objeto . . . Notaciones . . .6. . . . .3. . . . . 6. . . . . . Correcci´n de errores o 8. a 9. . . . . . . . TDS enlazadas . . . . . o 7. . Reacondicionamiento o Reordenamiento de instrucciones 7. . . . .3. 7. . . . . . 8. . . . . . . . . . . . o 7. . . . . . . e 6. . . . . . . . . . . . . . . . . . La Tabla de S´ ımbolos 9. . . . . . . . . . . . Eliminaci´n de redundancias . An´lisis de Expresiones Disponibles . . . . . . . . . . . .1. . . . . . . . . Generaci´n y Representaci´n de o o 6. .2.1. . . . . . . . . . . . TDS ordenada . . . Reducci´n simple o Reducci´n de operaciones . . . . . . . . . . .1. . .1. . . .4. . . . . . . TDS con hashing . . . .1. .1.1. . . . . . . . . . . . . .3. . . Soluci´n Iterativa para las ecuaciones de Flujo de Datos o 7. . .2. . . . . . . . . . Errores 8. . Correcci´n de errores o 8. . . . Cuartetos . . . . .1. . . . . . . . . . 7. . . . . . . . . . . .2. . . . . . .1. . Tercetos . . . . . .3. Optimizaci´n de C´digo o o 7. . . . .2. . . . . . . . . . . .2. . .3. . . . . . 6. . . 9. . . . . . . . . .1. . . .3. . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . . 9. . . . .2. . . . . . . . . . . . . . . . . . . Extracci´n de invariantes . . .2.3. . . . . Detecci´n de lazos en los grafos de flujo . . . o 7. . . . . An´lisis Global del Flujo de Datos . .1. .3. . . . . a 7. Correcci´n de errores o 8. . . . . . . . . .1. Tipos . o ´ INDICE GENERAL 51 51 52 53 53 54 54 55 56 56 57 59 59 59 60 60 60 60 61 61 61 63 63 66 67 67 68 71 71 71 72 72 73 73 75 75 75 75 75 76 77 . . . . . . . . . . . . . . . . Reducci´n de potencias . . . . . . . . . . . . . . de cambio . . . . . . . . . . . . . . . . . . . .3. . . . . . . . . . . . . . . . . . . . o 7. . . . . . . . . . . . . . . . . C´digo Intermedio o 6. .2. . . . . . . . . . . . Tipos de errores . T´cnicas de optimizaci´n en c´digo fuente .1. . . . . . . . . . . . . . Recuperaci´n de errores . . . . . . . . . . . . . . . . . . . Acceso a elementos de matrices 6. . . . . . .1. . . Representaci´n de strings . . . . . . . . . .1. . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . .2. .3. . . . . . . . . . .2. . . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . .4 6. . . . . . . . . . . . . Reordenaci´n de expresiones: Algoritmo de Nakata . . . . . . . . a 6. . . An´lisis de Variables Activas . . . . . . . . . . . . . . . . . . .2. . . . . An´lisis de Flujo .5. . saltos . . . . . . . . . . .4. . .1. . . . . . . . . . . . .4. . . . . . . . . . . . . . .5.4. . . . . . . . . . . . . . . .2. . . . . . . .1.1. . o 8. . . . . . . . TDS lineal . .3. . . . . . . . o 7. . . . . . . . . . . . . a 8. . . . C´digo a tres direcciones . . . 9. . . . . . . . . . o o 7. . . .2.2. . .1. . . . . M´todo de las Cajas . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . . . . . . . . . 6. .5. . . . . .3. . de borrado de inclusi´n o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. Modo p´nico . . . . a 7. a 7. . Notaci´n Vectorial . . . . . . . . . . . .

. . .1. . . . . . . . . . . . . . . . 10. . . . . . .2. . . . . . . . . . . Subprogramas . . . . . . . Int´rpretes . . . . 10. o 10. . . . . . Estructuras COMMON y EQUIVALENCE en FORTRAN 10. . . . . . . . . . 10. o o 10. .1. . . . . . . . . . .1. . . .4. . . . . . . . . .5. . . . .´ INDICE GENERAL 10. . . . . . .2.2. . . . . . . . . . . . . . . . . . . . Registro de activaci´n . . . . Ficheros objeto . . . . . .3. . . . . . . . . . . . . Representaci´n de registros . . . . . . o 10. . . . . . . . . . . . . . . . . . e 5 79 79 79 81 81 81 82 82 83 84 84 85 85 . . . . . . . . . . o 10. . . Gesti´n de memoria proporcionada por el compilador .1. . . . . . . . . . . . . . Representaci´n de cadenas y tiras de caracteres o 10. . . . . .4. . . . . Secuencia de llamada y retorno . . . . . . . . . . . . . . . .1. . . . . . 10. . . . . . . . . . . . . Representaci´n de arrays y matrices . . . . . .1. . . . . . . . . . . . . . Representaci´n de la Informaci´n .3. de Informaci´n y Gesti´n de Memoria o o 10.2. . .3.2. . .2. . . . . . . . . .Rep. . . . . .2. . o 10. Montadores y Cargadores . . . . . .

6 ´ INDICE GENERAL .

1 Entre ambas tendr´ lugar un parcial.1: Esquema de las tareas de un compilador.Cap´ ıtulo 1 Introducci´n o La asignatura de Compiladores se divide en dos grandes bloques: an´lisis y s´ a ıntesis . cada uno de los cuales se estructura en diferentes partes. a 7 . que veremos: 1 Figura 1.

INTRODUCCION .8 ´ CAP´ ITULO 1.

αn = ab . d. 2. α1 = ab. . .1. Gram´ticas.1. Lenguajes y Gram´ticas a Definiciones Sea A = {a. n n−1 ·A La potencia deriva del producto cartesiano: A · B = {xy/x ∈ A ∧ y ∈ B}. c. ´ demostracion: A∗ = i 0 Ai = A0 ∪ i>0 Ai = {λ} ∪ i>0 Ai = A+ ∪ {λ} 9 . e} un alfabeto (conjunto de caracteres). La tira nula es la tira de distancia 0 y suele representarse por ε o λ. b.1. Aut´matas y a o Traductores 2. Llamamos: √ Tira de caracteres o palabra a cualquier concatenaci´n de caracteres del alfabeto: o α = abc.Cap´ ıtulo 2 Lenguajes. √ Distancia o longitud de una tira al n´mero de elementos (caracteres) de la tira: u α = 3. √ Potencia de una tira a la tira que resulta de yuxtaponer una consigo misma n veces: para α = ab se tiene α0 = λ. ab. Es decir: nveces A =A con A0 = λ. λ2 = abab. √ √ Cierre transitivo a: A+ = i>0 Ai Ai Cierre reflexivo a: A∗ = i 0 De lo anterior se deduce que A∗ = A+ ∪ {λ}.

o Gram´ticas Tipo 3 o regulares: sus producciones son siempre A → αB o A → α. CONCEPTOS BASICOS 2. se caracterizan porque los elementos de a P son de la forma α → β con α ∈ (N ∪ T )+ y β ∈ (N ∪ T )∗ . o . Gram´ticas Tipo 1 o sensibles al contexto: sus producciones son de la forma αAβ → a αγβ con α. S). Se asocian con aut´matas finitos. En estas gram´ticas. a a Definici´n o Llamamos derivaci´n α ⇒ β al conjunto de producciones que nos llevan de α a β: o α = δAµ β = δγµ y ∃A → γ ∈ P Tambi´n se puede usar la notaci´n α ⇒∗ β o bien α ⇒+ β para indicar que hay al e o menos una derivaci´n. γ ∈ (N ∪ T )+ . Gram´ticas Tipo 2 o de contexto libre: los elementos de P son de la forma A → α a con A ∈ N y α ∈ (N ∪ T )∗ . Tipos a Una gram´tica es una upla G = (N . Chomsky clasific´ las gram´ticas en cuatro u o o a tipos : Gram´ticas Tipo 0: con estructura de frase. β ∈ (N ∪ T )∗ . la sustitua ci´n de un no terminal por una cadena depende de los s´ o ımbolos que tenga alrededor (contexto). T .1. A ∈ N .2. Son las gram´ticas a m´s generales (admiten producciones de cualquier tipo) y se asocian con aut´matas a o bidireccionales. o Las m´s importantes para nosotros ser´n las gram´ticas de tipo 3 o gram´ticas regua a a a lares. Gram´ticas. B ∈ N y α ∈ T . con a A.10 ´ CAP´ ITULO 2. P. donde a N conjunto de s´ ımbolos no terminales T conjunto de s´ ımbolos terminales P conjunto de producciones S axioma de la gram´tica a Seg´n la forma de sus reglas de producci´n. Las gram´ticas de tipo a e a 2 o gram´ticas independientes del contexto har´n lo propio cuando nos ocupemos del a a an´lisis sint´ctico (parsers). ya que derivan conjuntos regulares que representaremos por medio de aut´matas o finitos y nos ayudar´n a construir analizadores l´xicos (scanners). Son las que se usan para lenguajes de programaci´n.

´ 2.3. a: D (G) = {x/S ⇒∗ x ∧ x ∈ (N ∪ T )∗ } Claramente. D (G). a a Una gram´tica se dice ambigua si para alguna palabra del lenguaje que genera existe a m´s de un ´rbol sint´ctico. No existe el concepto de lenguaje ambiguo. Equivalentemente. Lenguajes Dada una gram´tica G = (N .1: Ejemplo de ´rbol sint´ctico. S). entonces se cumple que x ∈ T ∗ y S ⇒∗ x. lo que es ambiguo a a a es la gram´tica. ⇔ La representaci´n gr´fica de las distintas derivaciones posibles para generar una tira o a se denomina ´rbol sint´ctico : a a Figura 2. ´ demostracion: Sea x ∈ L (G).1. (S ⇒∗ x) ∧ (x ∈ (T ∪ {λ})∗ ) ∗ (S ⇒∗ x) ∧ x ∈ T ∪ N 0 De aqu´ se deduce que ı (S ⇒∗ x) ∧ (x ∈ (T ∪ N ∗ )∗ ) ⇔ (S ⇒∗ x) ∧ (x ∈ (T ∗ ∪ N ∗ )∗ ) ⇔ (S ⇒∗ x) ∧ (x ∈ (T ∪ N )∗ ) Por tanto.1. P. se verifica que L (G) ⊂ D (G). T . a L (G). LENGUAJES Y GRAMATICAS 11 2. definimos el lenguaje generado por G . como: L (G) = {x/S ⇒∗ x ∧ x ∈ T ∗ } Llamamos formas sentenciales. x ∈ D (G) ⇒ L (G) ⊆ D (G). a .

La forma de solucionarlo es definir gram´ticas m´s complejas (con m´s restricciones). 4. pues.2: Ejemplo de gram´tica ambigua. Generaci´n del lenguaje vac´ L (G) = ∅. el compilador deber´ elegir uno de los dos ´rboles posibles. . buscaremos. u 3. que las ıas u transforman en gram´ticas regulares): a 1. puesto que ello ralentizar´ la compilaci´n. es decir. a ´ En este ultimo caso. u Su orden de aplicaci´n sobre una gram´tica es importante. 2. Ciclos.12 ´ CAP´ ITULO 2. o ıo. Usaremos gram´ticas de contexto libre y una serie de a algoritmos que detectan las anomal´ que pueden producir ambig¨edad (es decir. CONCEPTOS BASICOS Figura 2. sin reglas-λ y sin ciclos. S´ ımbolos in´ tiles (no accesibles o no terminables). mecanismos deterministas y de poco coste computacional. sin a reglas unitarias (o reglas cadena) ni s´ ımbolos in´tiles. Reglas unitarias. Reglas ε o λ. adem´s a o a ıa o a de obligar a que el compilador conozca la precedencia de los operadores. esto es. Obteno dremos de este modo gram´ticas limpias. as´ que debe respetarse el o a ı que seguiremos. Esta ´ ıa a ser´ una situaci´n que deber´ evitarse. 5. a a a Otros problemas de las gram´ticas de contexto libre que conducen a situaciones sia milares son la recursividad por la izquierda y la existencia de reglas con factores repetidos por la izquierda. Cuando construyamos un compilador. A continuaci´n veremos una serie de algoritmos que realizan estos objetivos.

A e viejo} end N’=N V nuevo T’=T V nuevo end . puesto que u S ⇒∗ αx. /* PRIMERA FASE. y es terminable. t e T*} vhile (nuevo<>viejo) do begin viejo=nuevo nuevo=viejo U {B / (B->a) e P. b e (T* U N’)} end /* SEGUNDA FASE. a e (T U viejo)*} end N’=nuevo P’={p e P / p:(A->b). ELIMINACION DE NO TERMINABLES */ begin viejo=0 nuevo={A / (A->t) e P. t ∈ T ∗ . LENGUAJES Y GRAMATICAS Algoritmo que detecta L (G) = ∅ begin viejo=0 nuevo={A / (A->t) e P. ya que xβ ⇒∗ t). a e (T U viejo)*} end if (S e nuevo) then vacio=‘‘NO’’ else vacio=‘‘SI’’ end 13 Algoritmo que elimina s´ ımbolos in´ tiles u Dado x. si S ⇒∗ αxβ ⇒∗ t. ELIMINACION DE NO DERIVABLES */ begin viejo={S} nuevo=viejo U {x / (S->axb) e P} while (nuevo<>viejo) do begin viejo=nuevo nuevo=viejo U {Y / (A->aYb) e P.1.´ 2. entonces x no es in´til (es accesible. t e T*} while (nuevo<>viejo) do begin viejo=nuevo nuevo=viejo U {B / (B->a).

de la o que no se puede prescindir porque λ forma parte del lenguaje. CONCEPTOS BASICOS Como ya hemos dicho. V´ase e sino el siguiente ejemplo: Figura 2.14 ´ CAP´ ITULO 2. el orden en que aplicamos estos algoritmos es importante. se a~ade a P’A->a0X0a1X1. a eliminando sus λ-producciones si las tienen. en ese caso se dice tambi´n e e que A es anulable. salvo la metanoci´n (regla S → λ).. begin viejo=0 nuevo={A / (A->l) e P} while (nuevo<>viejo) do begin viejo=nuevo nuevo=viejo U {B / (B->a).. B ∈ N .3: Relevancia en el orden de los algoritmos de simplificaci´n. A->a0B0a1B1. Si S es anulable se a~ade n n S’->S|l y se a~ade S’ a N n end Algoritmo que elimina reglas unitarias Una regla unitaria es de la forma A → B con A. .anBn e P donde ai no anulable y Bi anulable. Intentaremos evitar las gram´ticas que contengan reglas de este tipo... a e viejo*} end N’=N-nuevo P’=Para cada prod.anXn n con Xi=Bi o l sin a~adir A->l. No aportan nada y por ello deben eliminarse. o Algoritmo que elimina reglas λ Una regla lambda es aqu´lla que es del tipo A → λ.

|bq podemos escribirlo como A->Aai 1<=i<=p A->bj 1<=j<=q Para quitar la recursividad por la izquierda escribimos A->biA’ 1<=i<=q. Greibach).1. o a . /* debe hacerse para cada A de N */ while (nuevo<>viejo) do begin viejo=nuevo nuevo=viejo U {C / (B->C) e P. de modo que intentaremos reescribirlas. Tampoco da problemas. A ∈ N y α ∈ (N recursividad es usual y no da problemas. T )∗ .|Aap|b1|b2|.. A’ nuevo simbolo e Te A’->ajA’|l 1<=j<=p Reglas con factores repetidos por la izquierda Las reglas del tipo A → αB|αC tambi´n pueden darnos problemas a la hora de e enfrentar un an´lisis. se aplican conversiones a forma normal (Chomsky. A ∈ N y β ∈ (N T )∗ . n 1 La raz´n es que el an´lisis lo hacemos de izquierda a derecha. a~adir (A->a) a P’ n para todas las A para las que B no est´ en NA e 15 Eliminaci´n de ciclos o En los casos en los que la aplicaci´n de los algoritmos anteriores no haya solucionado o este problema. Hacerlo es tan sencillo a como sustituirlas por: A → αA y A → B|C con A un nuevo s´ ımbolo no terminal que se a˜ade a Te .´ 2. LENGUAJES Y GRAMATICAS begin viejo=0 nuevo=A.. hay varios tipos de recursividad posibles: o Por la izquierda Se da cuando α = λ. Es el tipo de recursividad no deseable y que querremos eliminar1 . β = λ y A ∈ N . Este tipo de Autoimbricada Se da cuando α.. Recursividad Dada una regla de producci´n A → αAβ. Por la derecha Se da cuando β = λ.. B e viejo} end NA=nuevo end P’=Si (B->a) e P y no es regla unitaria. Para eliminar la recursividad por la izquierda lo que haremos ser´: a Si tenemos A->Aa1|Aa2|.

qf ∈ F Distinguimos dos tipos de aut´matas finitos: o AFD (deterministas) AFND (no deterministas) . Aut´matas o Aut´matas finitos o Un aut´mata finito queda definido por AF = (Q. a o 2. F). q0 . t) ´ configuracion final u objetivo: (qf . CONCEPTOS BASICOS 2.2. conjunto de caracteres o o que quedan por leer): (q. δ.2.16 ´ CAP´ ITULO 2. ´ configuracion inicial: (q0 . xj ) −→ {qk } Llamamos configuraci´n de un aut´mata al par (estado actual. λ).1. Te .w). donde o Q conjunto de estados Te alfabeto de entrada δ funci´n de transici´n o o q0 estado inicial F conjunto de estados finales y donde la funci´n de transici´n δ es de la forma o o δ : Q × Te −→ P (Q) (qi .1: Correspondencia gram´ticas-aut´matas. Gram´ticas y Aut´matas a o Se establece la siguiente correspondencia: Gram´ticas a Gram´ticas a Gram´ticas a Gram´ticas a tipo tipo tipo tipo 0 1 2 3 ⇔ ⇔ ⇔ ⇔ M´quinas de Turing a Aut´matas bidireccionales o Aut´matas con pila o Aut´matas finitos o Cuadro 2.

a). o Aut´matas con pila o Un aut´mata con pila se define AP = (Q. con o Q conjunto de estados Te alfabeto de entrada2 Tp alfabeto de la pila δ funci´n de transici´n o o q0 estado inicial z0 configuraci´n inicial de la pila o F estados finales donde la funci´n de transici´n es o o δ : Q × (Te 2 {λ}) × Tp −→ P (Q × Tp ∗ ) (qi . qi ∈ F} Figura 2. β )} Equivale al conjunto de terminales en las gram´ticas. GRAMATICAS Y AUTOMATAS 17 Llamamos transici´n a (qi .2. t) En cuanto a la representaci´n gr´fica: o a ∗ (qi . a leer un car´cter o a de la tira (cinta) de entrada y modificar el estado interno de la m´quina. Se puede usar a la notaci´n ∗ para indicar una transici´n con n pasos. Tp . qf ∈ δ (qi . a . z0 . λ) . o o El lenguaje generado por el AF se define: L (AF) = {t/t ∈ Te ∗ . q0 . o bien + para indicar n > 0. (q0 . aw) (qk . w) . F).4: Representaciones de un aut´mata. δ. n 0.´ ´ 2. esto es. Te . β) −→ {(qk . aj .

La configuraci´n: (q. El lenguaje que determina un AP: L (AP) = {t/t ∈ Te ∗ . λ. δ. q0 . α). zα) o ∗ + la notaci´n o y . u . t. CONCEPTOS BASICOS Se incluye incluye λ en el conjunto origen de la funci´n para poder hacer transiciones o sin leer.18 ´ CAP´ ITULO 2. w. t. ´ configuracion inicial: (q0 . qf ∈ F} (qf . aj ) −→ {(qj . λ. (q0 . β)} La pila puede quedar con caracteres esp´reos. y de nuevo el conjunto destino es un partes de. aw. Definimos movimiento o transici´n: (qi . qf ∈ F} Los que cumplen esta ultima restricci´n a˜adida se denominan aut´matas recono´ o n o cedores por agotamiento de pila. contemplando la posibilidad de que sea determinista (APD) o no determinista (APND). α) . α) con q ∈ Q (estado actual). 2. βα). simplemente con el contenido de la pila. Traductores Traductores finitos Un traductor finito se define TF = (Q. λ) . F). Ts . z0 ) Otra definici´n puede ser: o L (AP) = {t/t ∈ Te ∗ . con: Q conjunto de estados Te alfabeto de entrada Ts alfabeto de salida δ funci´n de transici´n o o q0 estado inicial F conjunto de estados finales donde la funci´n de transici´n es o o δ : Q × {Te 3 {λ}} −→ P (Q × Ts ∗ ) (qi . λ. tambi´n se admite e (qf . w ∈ Te ∗ (lo que queda por o ∗ leer) y α ∈ Tp (contenido actual de la pila). z0 ) ∗ ∗ qf ∈ F 3 (qk . (q0 . z0 ) ´ configuracion final u objetivo: (qf .3. w. Te . t.

F). s) con q ∈ Q (estado actual). t ∈ Te ∗ (lo que queda por o leer de la tira de entrada). sp )} Su configuraci´n: (q. ax. s) (q . a) = (q . z0 . x. q0 . s). con Q conjunto de estados Te alfabeto de entrada Ts alfabeto de salida Tp alfabeto de pila δ funci´n de transici´n o o q0 estado inicial z0 configuraci´n inicial de la pila o F conjunto de estados finales donde la funci´n de transici´n es o o δ : Q × (Te {λ}) × Tp −→ P (Q × Tp ∗ × Ts ∗ ) (qj . a. λ. admiti´ndose tambi´n la notaci´n ∗ y + . t.2. λ) ∗ (qt . Tp . s) con q ∈ Q (estado actual). e e o No tiene por qu´ haber relaci´n en tama˜o entre la entrada y el string de salida. Y llamamos conjunto de traducci´n a: o Tr (TF) = {(t. t. s). t. t ∈ Te (lo que queda por leer) y s ∈ Ts ∗ (lo que ha salido hasta el momento). w. TRADUCTORES 19 La configuraci´n (estado del aut´mata en un punto determinado de la ejecuci´n) se o o o ∗ representa (q. βk . q ∈ Q. e o n 4 En lugar de ∈ se pondr´ un = en el caso determinista. con q. ´ configuracion inicial: (q0 . λ. w ∈ Te ∗ y z ∈ Ts ∗ . Te . αγ. y) (qj . z0 . qt ∈ F} Traductores con pila Un traductor con pila es generado por un APD (del mismo modo que un AF genera un TF) y queda definido por TP = (Q. δ. qf ∈ F Un movimiento (transici´n entre dos configuraciones): (qi . z). Un movimiento es (q. α ∈ Tp ∗ (contenido de la pila) y s ∈ Ts ∗ (lo que ha salido hasta ahora). z0 . s ∈ Ts ∗ / (q0 . s) . yz) o 4 si (qj . αi . Ts . α. Z) . z) ∈ (qi . Zγ. aw. α.3. t. λ) ´ configuracion final u objetivo: (qf . sz) cuando δ (q. t ∈ Te ∗ . βk ) −→ {(qj . ıa .

Te . λ) Por agotamiento de pila: Tr (TP) = {(t. s) sii qf ∈ F} ∗ (qf . β ∈ R. s) con t ∈ Te ∗ y s ∈ Ts ∗ . t. λ. S). Puede usarse la notaci´n o o ∗ + → o→ . CONCEPTOS BASICOS ∗ (qf . Formas de traducci´n o Sean un par de tiras de caracteres (t. t ∈ Te ∗ . λ) ´ CAP´ ITULO 2. ρAψ) es una forma de traducci´n y existe A → α.20 Conjunto de traducci´n: o Tr (TP) = {(t. R. s) sii qf ∈ F} 2. ρβψ) es una forma de traducci´n. s) ((q0 . donde S es el axioma o 2.1. Si (γAw. s) / (S. con N conjunto de s´ ımbolos no terminales Te alfabeto de entrada Ts alfabeto de salida R reglas de traducci´n o S axioma donde las reglas de traducci´n son de la forma o   A∈N α ∈ (N R : A −→ αβ con  β ∈ (N Te )∗ Ts )∗ Los esquemas de traducci´n son una extensi´n del concepto de gram´tica. s ∈ Ts ∗ } . S) es una forma de traducci´n. λ. λ. z0 . entonces o (γAw. ρAψ) → (γαw. (S.3. Ts . Esquemas de traducci´n o Los esquemas de traducci´n son una notaci´n. entonces: 1. α. z0 . Tienen la siguiente estructura: o o EDT = (N . Cumplen o o a que N (Te Ts ) = ∅. t. El conjunto de traducci´n de un EDT se escribe: o Tr (EDT) = {(t. s) . S) →∗ (t. s) ((q0 .

que veremos en pr´cticas.2. Ahora bien. se usan t´cnicas de hashing y algoritmos como el de la tabla compacta.) e incluso llevan a cabo tareas sem´nticas mediante el manejo de tablas como a las que ya conocemos para la representaci´n de aut´matas. n´meros de u u l´ ınea. Para paliar esto.1: Objetivo de un scanner. El problema que hay en el o o manejo de las tablas es un problema de memoria debido al espacio que ocupan. n´meros de sentencia. por tanto. 1 Esto puede repercutir en la complicaci´n de la parte sem´ntica. p´gina 22). con las gram´ticas e a regulares. El tercer m´todo. Scanners a e Un analizador l´xico o scanner es una entidad cuya tarea consiste en: e Figura 3. e a o A continuaci´n.Cap´ ıtulo 3 An´lisis L´xico. por ejemplo. a El primer m´todo. el que ser´ exigido en o e a ejercicios en el examen de la asignatura. es sencillo y c´modo de utilizar. etc. los scanners no s´lo hacen esto. nos centraremos en el segundo de los m´todos. o o ıas Los analizadores l´xicos identifican con los AFD y. se˜alado en la mencionada figura como m´todo manual y que e n e veremos en ejercicios. es f´cil. reformatean texto o (eliminan espacios y l´ ıneas en blanco. o a 21 . sino que. Se puden expresar o describir por medio de una expresi´n regular. pero tambi´n laborioso cuando la gram´tica se complica a e a m´ ınimamente. comentarios. que e intenta guardar s´lo las casillas con informaci´n y no las vac´ 1 . o Existen diferentes formas de construir un analizador l´xico o scanner (ver figura e 3.

22 ´ ´ CAP´ ITULO 3.2: Maneras de construir un scanner. . SCANNERS Figura 3. ANALISIS LEXICO.

Propiedades En primer lugar. Dichos elementos son los o a que se muestran en la figura 3. a e 3. 3. se define su cerradura: Cerradura − Σ (s) = sk ∈ AFND/s →λ sk esto es. el conjunto de estados a los que se puede llegar desde s s´lo mediante o λ-transiciones. o necesitamos manejar algunos conceptos: Si s es un estado del AFND.3. Transformaci´n de un AFND con λ-transiciones en AFD o Antes de ver los pasos que hemos de seguir para llevar a cabo esta transformaci´n.1. se define a su vez su cerradura: Cerradura − Σ (T) = sk ∈ AFND/∃sj ∈ T. Algoritmo (m´todo) de Thompson e El algoritmo que describiremos en esta secci´n permite el paso de una expresi´n regular o o a un AFDN. Es un m´todo gr´fico que se basa en la concatenaci´n de cajas (componentes) e a o a partir de la definici´n de elementos b´sicos de dichas cajas.3 (p´gina 24). para ejemplos.1. haremos un recordatorio de las propiedades de las expresiones regulares. v´anse los ejercicios del tema. ya conocidas por nosotros: Dadas s. t dos expresiones regulares: Distributiva s(r|t) = sr|st (s|r)t = st|rt s∗∗ = s∗ Conmutativa r|t = t|r Asociativa (sr)t = s(rt) Elemento Neutro εr = rε = r (r|ε)∗ = r∗ Idempotencia 3.1.1.´ 3.1.1. CONSTRUCCION DE SCANNERS MEDIANTE AFS 23 3. Si T es un conjunto de estados del AFND. Construcci´n de scanners mediante AFs o Expresiones Regulares.2. sj →λ sk .

a e .24 ´ ´ CAP´ ITULO 3. ANALISIS LEXICO. SCANNERS Figura 3.3: Componentes b´sicos del m´todo de Thompson.

los pasos que se siguen son los siguientes: 1.a_i)) si (U no esta en el conjunto T) se a~ade U a T n transicion[T. Calculamos la funci´n de movimiento para todo ai s´ o ımbolo terminal del AFND y los diferentes estados generados en el paso anterior. Se calcula la funci´n de movimiento para A y todo ai s´ o ımbolo terminal del AFND. origin´ndose nuevos estados B.1. a 4. sj →a sk } A grandes rasgos. se define una funci´n de movimiento: o Mueve (T.´ 3. . CONSTRUCCION DE SCANNERS MEDIANTE AFS 25 Si T es un conjunto de estados del AFND y a es uno de sus s´ ımbolos terminales. Se calcula un nuevo estado A. la cerradura-Σ del estado inicial del AFND. a) = {sk ∈ AFND/∃sj ∈ T. Se calcula la cerradura-Σ del resultado del paso anterior.a_i]=U fin-para fin-mientras . . El algou a ritmo se formalizar´ ıa: calcular cerradura-E(0)=Estado A incluir A en NuevosEstados /* estados del AFD */ mientras (no estan todos los T de NuevosEstados marcados) hacer marcar T para cada a_i e T_e hacer U=cerradura-E(Mueve(T. para todos los terminales. El proceso contin´a y termina cuando ya no se generan m´s nuevos estados. . C. 3. 2.

26

´ ´ CAP´ ITULO 3. ANALISIS LEXICO. SCANNERS

Cap´ ıtulo 4 An´lisis Sint´ctico. Parsers a a
El an´lisis sint´ctico consiste en encontrar u obtener el ´rbol de derivaci´n que a a a o tenga como ra´ el axioma de una gram´tica dada. ız a

4.1.

Tipos de parsing

Hay diferentes tipos de parsing , como se indica en la siguiente figura:

Figura 4.1: Tipos de parsing.

27

28 Otra clasificaci´n: o

´ ´ CAP´ ITULO 4. ANALISIS SINTACTICO. PARSERS

Figura 4.2: Tipos de parsing, otra clasificaci´n. o El parsing descendente intenta construir el ´rbol sint´ctico partiendo del axioma a a (ra´ desplegando hojas hasta llegar a la frase que tengamos. Por su parte, el parsing ız) ascendente parte de los tokens (hojas, palabras que ha detectado el scanner ) para intentar llegar al axioma (ra´ ız). La gran mayor´ de los compiladores modernos son analizadores sint´cticos ascendenıa a tes, que suelen basarse en pivotes 1 . De ellos, los m´s potentes son los tipo LR(K), donde a la K representa el n´mero de tokens que el analizador necesita para saber qu´ pivote apliu e car a cada paso. Por supuesto, lo m´s interesante son los LR(1), de los cuales se conocen a los tres tipos que se mencionan: SLR (el m´s sencillo pero menos potente, impone m´s a a restricciones a sus gram´ticas), LR can´nico (el m´s potente pero tambi´n m´s complejo) a o a e a y el LALR (un punto intermedio entre los dos anteriores y en el que se basan herramientas como yacc o bison). Como siempre, el objetivo ser´ la consecuci´n de la tabla. a o Otro tipo de analizadores sint´cticos ascendentes son los que utilizan la filosof´ de a ıa an´lisis por precedencia. Hist´ricamente fueron los que primero se usaron, aunque hoy a o no tengan demasiada utilidad. Los analizadores sint´cticos descendentes, por su parte, se clasifican en analizadores a con retroceso, en los que se parte del axioma, se hace una exploraci´n y si resulta fao llida se vuelve hacia atr´s (backtracking) y se reintenta hasta que se consigue o bien se a agotan todas las posibilidades, y sin retroceso, en los que el algoritmo es m´s predictivo a y conoce con certeza en cada caso qu´ rama del ´rbol expandir. Entre estos ultimos se e a ´ encuentran los LL(K), donde de nuevo la K indica el n´mero de tokens que el parser u
1

Conjunto de tokens que forma la parte derecha de una regla de traducci´n. o

An´lisis por precedencia a Precedencia Simple Es un m´todo de an´lisis sint´ctico ascendente. pero son m´s bien o o a m´quinas te´ricas que aplicaciones reales. 4 V´anse ejemplos del tema. se establece una relaci´n de precedencia o mediante la cual uno de ellos tendr´ mayor.2. a o Que ser´n siempre de contexto libre.2. ANALISIS POR PRECEDENCIA 29 necesita conocer para saber por d´nde ir. se puede construir desde la base hacia la ra´ el o ız ´rbol de derivaci´n correspondiente4 . a Recu´rdese que ahora los terminales y no terminales no representan s´ e ımbolos. tokens. tambi´n aqu´ lo interesante es que K=1. e 3 2 . o Por ultimo. veremos: e √ √ √ √ Condiciones que impone. Renombrando a trozos de la expresi´n de esta manera. una tabla de precedencia (donde se indiquen las precedencias a relativas entre cada par de s´ ımbolos) y una expresi´n. sino palabras. mencionar que tanto entre los parsers descendentes como entre los as´ cendentes encontramos aut´matas de pila y esquemas de traducci´n. e a a Definici´n: o Entre dos tokens dados T1 y T2 . entonces. 4. o a Construcci´n de las tablas. todos los s´ o ımbolos que queden entre dos signos “<” y “>” con signos de igualdad entre ellos se dice que forman un pivote. 4. a o Las casillas en blanco de la tabla de precedencia son errores e indican que los dos s´ ımbolos no pueden relacionarse (no hay una relaci´n de precendencia definida entre ellos) o por medio de la gram´tica en cuesti´n. o Funcionamiento.1. igual o menor precedencia que el a otro: T1 > T 2 T1 = T2 T1 < T 2 Dada una gram´tica.´ 4.2. alguna regla del tipo A → pivote3 . de o e ı modo que estudiaremos los LL(1) y c´mo obtener la tabla a partir de ellos. Definici´n de las gram´ticas que admite2 . a o Para cada m´todo de los que estudiaremos. las adecuadas para manejar estructuras de frase y ya no palabras. En la gram´tica ha de existir.

puesto que es sencillo olvidarse de alg´n caso. a 6 5 . pueden obtenerse diferentes gram´ticas6 . Se dice que x ± y si y s´lo si A → αxy ∈ P. y)/(xRy) ∨ (xSy)} R × S = {(x. y ∈ A} Relaci´n traspuesta (de una dada) Se representa R o RT : o RT = {(y. Ello e u es as´ porque consiste simplemente en intentar extraer la tabla de precedencia a partir ı simplemente de analizar “a ojo” las producciones de la gram´tica. Relaci´n universal Se define: o U = A × A = {(x. x) /xRy} Relaci´n complementaria (a una relaci´n dada): o o R∼ = {(x. Reflexividad. yRz ⇒ xRz. ıa. y) /∼ (xRy)} Relaciones binarias Dadas dos relaciones R y S: R + S = {(x. y) /x ∈ A. xRx. PARSERS M´todo derivativo o del ´rbol e a Es un m´todo manual aplicable en caso de gram´ticas sencillas. Transitividad. Se dice que x > y si y s´lo si A → AαCyβ ∈ P y C ⇒+ γx. ∀x ∈ R. z ∈ R.30 ´ ´ CAP´ ITULO 4. y ∈ R. y)/(xRy) ∧ (xSy)} R · S = {(x. dada una tabla de precedencia simple. xRy. Se dice que x < y si y s´lo si A → αxBβ ∈ P y B ⇒+ yγ. ∀x. intentar obtener su gram´tica. ANALISIS SINTACTICO. S}: a 1. a Ver ejemplos del tema. 2. T . (xRz) ∧ (zSy)} El m´todo se describe de la siguiente manera: e √ Dada una gram´tica G = {N . o 3. M´todo matricial e Para ver c´mo obtener la tabla de precedencia mediante este m´todo necesitamos o e previamente definir: Relaci´n de equivalencia (R) Cumple lo siguiente: o 1. P. o Dada una misma tabla de precedencia simple. ∀x. y)/∃z. y. Simetr´ xRy ⇒ yRx. pero no recomendable e a en cuanto ´stas se complican un poco. o 2. Una pregunta de examen puede ser. hasta agotar todas las a 5 posibles derivaciones . 3.

// copia de la matriz de partida I=1.2. es un m´todo de an´lisis sint´ctico e a e a a ascendente en el que se buscan relaciones entre los s´ ımbolos. o o Relaci´n Ultimo Diremos que A ultimo X si y s´lo si ∃A ⇒ αβX. ANALISIS POR PRECEDENCIA M´s definiciones: a Relaci´n Primero Diremos que A primero X si y s´lo si ∃A ⇒ Xαβ. if (I<=N) then goto 3. else stop. . o o Relaci´n Dentro+ Diremos que A dentro+ X si y s´lo si ∃A ⇒+ αXβ.´ 4. o o Relaci´n Primero+ Diremos que A primero+ X si y s´lo si ∃A ⇒+ Xαβ. until todos los valores de J.2. o ´ o Relaci´n Dentro Diremos que A dentro X si y s´lo si ∃A ⇒ αXβ. o ´ o Relaci´n Ultimo+ Diremos que A ultimo+ X si y s´lo si ∃A ⇒+ αβX. Las relaciones se obtienen: √ (±). donde I es la matriz identidad (todo ceros con unos en la diagonal).K)=1. Precedencia Operador Puede considerarse un caso particular de precedencia simple (podr´ por tanto.K)=1) then A(I. reıa. √ (>) = (ultimo+ )T (±)(I + primero+ ). o o Algoritmo de Warshall /* permite hallar PRIMERO+ a partir de PRIMERO */ B=A. 31 Cuadro 4. I=I+1.J)=1) then for K=1 to N do if (A(J. solverse utilizando matrices o el m´todo del ´rbol). 4. 3: repeat if (B(I.2. a √ (<) = (±)(primero+ ). observando las reglas de la gram´tica.1: Algoritmo de Warshall.

ı). El m´todo de funcionamiento es independiente del lenguaje. no recursivo. se cumple siempre que: a a) Los identificadores tienen mayor precedencia que cualquier operador.3. b) Los par´ntesis tienen mayor precedencia que cualquier otro s´ e ımbolo. Veremos en seguida su estructura y c´mo se consa o truye. Como ya hemos comentado alguna vez. dado que la precedencia se define entre los operadores. errores. escribiremos θ1 > θ2 θ2 < θ1 ii) Si θ1 y θ2 son operadores de igual precedencia.3. . 4. etc) donde precedencia simple n n no resulta suficiente. Mayor precedencia ˆE */ Menor precedencia + asociatividad por la derecha asociatividad por la izquierda asociatividad por la izquierda Cuadro 4. An´lisis sint´ctico LL(K) a a An´lisis LL(1) a Es un m´todo predictivo. PARSERS La diferencia es que. Suele dar buenos resultados en aplicacioe nes peque˜as (shells. a 4. anotaremos θ1 > θ2 θ2 > θ1 θ1 < θ2 θ2 < θ1 si son asociativos por la izquierda si son asociativos por la derecha iii) Adem´s de todo ello. son indistinguibles entre s´ no son necesarios para determinar si la expresi´n est´ bien escrita. compiladores de peque˜os lenguajes. las casillas en blanco de la tabla a suponen acciones sem´nticas.2: Precedencia usual entre los operadores matem´ticos. no es necesario tener en cuenta los identificadores (que no tienen precedencia.1. Al variar ´ste s´lo vae e o riar´ la tabla.32 ´ ´ CAP´ ITULO 4. o a Construcci´n de la tabla o Los pasos son los siguientes: i) Si el operador θ1 tiene mayor precedencia que el operador θ2 . c) El s´ ımbolo $ (indicador de principio/fin de cadena) tiene menor precedencia que cualquier otro s´ ımbolo. ANALISIS SINTACTICO.

el parser consulta la tabla de an´lisis (que llamaremos M ) en a la posici´n (X. Hablamos siempre refiri´ndonos a la gram´tica que acepta el parser. Primero(X). P.3: Estructura de un parser LL(1). ANALISIS SINTACTICO LL(K) 33 Figura 4. Si X es no terminal. b) Si M (X. b) Si X → ε.´ ´ 4. Funcionamiento Los pasos que sigue un analizador sint´ctico de este tipo son: a Se lee la entrada y la cima de la pila. 3. Puede ocurrir: 1. T .3. entonces ε ∈ Primero(X).3. S). de la siguiente manera: a) Si X ∈ T 8 . 7 8 Ver ejemplos en los ejercicios del tema. a). que calcula el primer terminal de una cadena de caracteres. Si X = a = $ (donde X es el elemento de la cima de la pila. o a Construcci´n de la tabla de an´lisis o a Definiremos antes de nada dos operaciones: 1. e a . entonces se ha producido un error. u a El pseudoc´digo de la tabla 4. el parser saca X de la pila y mueve el apuntador de entrada al siguiente elemento del buffer. a 2. Si X = a = $. a) = ∅.1 (p´gina 34) realiza lo que acabamos de explicar7 . a el primer elemento ´ del buffer de entrada y $ el car´cter nulo). Hay dos posibilidades: o a) Si M (X. se llega al fin del analisis. se contin´a el an´lisis. entonces Primero(X)={X}. G = (N . a) = (X → uwz).

meter Yk.. ı do { sea X el simbolo de la cima de la pila y a el simbolo apuntado por æ.3: Algoritmo de an´lisis LL(1)... si no error { apuntar æ al primer s´mbolo de w.a]=X->Y1Y2. if (X es terminal o $) if (X=a) extraer X de la pila y avanzar æ.. a .34 ´ ´ CAP´ ITULO 4.Y1 en la pila. /* pila vacia */ } Cuadro 4.Yk-1. PARSERS entrada: cadena w y tabla de analisis sintactico M salida: si w pertenece al lenguaje que acepta el parser. una derivacion por la izquierda de w.. } while (X no sea $).Yk) { extraer X de la pila. else if (M[X. ANALISIS SINTACTICO. } else return (error). else return (error)..Yk. emitir la produccion X->Y1Y2.

2. las casillas en blanco supondr´n errores y dar´n lugar a a a tratamientos sem´nticos. 4. o b) Si A → αBβ. Como ya ha sido comentado. o 2. entonces M [A. 35 Una vez que se han calculado los conjuntos Primero y Siguiente. o a Comprobaci´n de si una gram´tica es LL(1) o a Dada una gram´tica libre del contexto G = {N . b] = A → α∀b ∈ Siguiente(A). Yn .´ ´ 4. mientras que si en una casilla aparece m´s de una regla. T . entonces {Primero(β)−{ε}} ⊂ Siguiente(B). entonces Siguiente(A) ⊂ Siguiente(B). ANALISIS SINTACTICO LR(K) c) Si X ∈ N y X → Y1 Y2 . el axioma. 3. entonces a ∈ Primero(X) y ∃i/a ∈ Primero(Yi ) y ε ∈ Primero(Yj ) ∀j < i. las reglas para construir la tabla son: 1. o o 3. S}. De nuevo. donde S es el s´ ımbolo inicial. es por el n´mero de s´ u ımbolos . debe darse que primero(α)∩ siguiente(A) = ∅. ∀a ∈ Primero(α). Si ε ∈ Primero(α). la metanoci´n. Siguiente(A) –con A ∈ N –. aplicar los dos pasos siguientes. Para toda producci´n A → α ∈ P.4. primero(α)∩ primero(β) = ∅. denominada an´lisis sint´ctico LR(K). . . An´lisis sint´ctico LR(K) a a En esta secci´n analizaremos una t´cnica eficiente de an´lisis sint´ctico ascendente o e a a que se puede utilizar para analizar una clase m´s amplia de gram´ticas independientes a a del contexto. 2. S´lo α ´ β pueden derivar ε (nunca ambos). dado un no terminal A. la a a conclusi´n es que la gram´tica no es LL(1) (no es determinista). que calcula. ¿c´mo podemos saber si es a o una gram´tica LL(1) o no sin tener que construir la tabla? La cuesti´n es tan sencilla a o como realizar las siguientes comprobaciones ∀A → α|β: 1.4. c) Si A → αBβ y β →∗ ε o A → αB. a] = A → α. M [A. el primer terminal que est´ a continuaci´n de A: a o a) Se cumple que $ ∈ Siguiente(S). esas tres reglas no son excluyentes. P. Si β ⇒∗ ε. Las tres reglas se aplican sobre la cadena en cada caso. Este tipo de analizadores recibe a a este nombre por lo siguiente: la L hace referencia a qe el examen de la entrada se realiza de izquierda a derecha. como ya imaginamos. la R se debe a que la reconstrucciones en orden inverso nos llevan a derivaciones por la derecha y la K.

An´lisis LR(1) a Figura 4. √ LR can´nico. o o . consta de dos partes: la funci´n acci´n. PARSERS de anticipaci´n que se necesitan para una correcta toma de decisiones. ANALISIS SINTACTICO. el m´s f´cil pero tambi´n el menos potente (puede que no a a e consiga construir la tabla para algunas gram´ticas). que veremos. Veremos modos de simplificarlo o a para obtener alguno de los dos anteriores. o Despu´s de estudiar el modo de operar de un analizador sint´ctico LR.4: Modelo de un analizador sint´ctico LR(1). el m´s poderoso y costoso de los tres. La primera se usa siempre. y se o e usan la combinaci´n del s´ o ımbolo de estado en la cima de la pila y el s´ ımbolo en curso de la entrada para indexar la tabla de an´lisis sint´ctico y determinar la decisi´n de a a o desplazamiento a reducci´n del analizador.4. utiliza una pila para almacenar una cadena donde Xi son s´ ımbolos gramaticales y Si son estados. 4. introduciremos e a tres t´cnicas para construir la tabla de an´lisis sint´ctico LR para una gram´tica dada: e a a a √ SLR (LR Sencillo). a a o o que indica una acci´n del analizador (indica qu´ hacer ). De un tipo de LR(1) a otro s´lo cambian las tablas. que indica las o e o transiciones entre estados.36 ´ ´ CAP´ ITULO 4. mientras que la segunda se usa s´lo si tiene lugar una reducci´n.1. o La tabla de an´lisis sint´ctico. a Este es el esquema de un analizador sint´ctico LR(1): se apoya en una tabla de an´lisis a a sint´ctico con dos partes. Cada s´ ımbolo de estado resume la informaci´n contenida debajo de ´l en la pila. un m´todo “intermedio”. acci´n e ir a. que funciona e con la mayor´ de las gram´ticas de los lenguajes de programaci´n y que usan ıa a o herramientas como yacc. a √ LALR (LR con examen por anticipado). a o o El programa analizador lee caracteres del buffer de entrada de uno en uno. en cada uno de los pasos. como decimos. y la funci´n ir a.

en la pila. Una configuraci´n de un analizador sint´ctico LR(1) es un par cuyo primer compoo a nente es el contenido de la pila y el segundo la entrada que a´n est´ sin procesar: u a (S0 X1 S1 X2 S2 . Xm−r+1 . . . exponiendo el estado Sm−r . A] (donde r es la longitud de β) de la tabla de e transiciones para obtener un nuevo estado Sq que se a˜ade a la cima de la pila. Se consulta la entrada accion[Sm . r de estados y r de s´ ımbolos de la gram´tica. a a e ◦ Si accion[Sm . En este caso se consulta tamo bi´n la entrada ir a[Sm−r .´ ´ 4. Tomamos Sm de la cima de la pila y ai de la entrada actual. A]. y Sm . ANALISIS SINTACTICO LR(K) Funcionamiento 1. y consultado despu´s la entrada e accion[Sm . . el analizador sint´ctico ha descubierto un error. ai ] =desplazar Sp . el lado derecho de la producci´n con que o se efect´a la reducci´n. . . Xm Sm ai Sp . . Xm−r Sm−r ASq . ai ai+1 . concuerda siempre con β. d ) Error. u o ◦ Si accion[Sm . a . Las configuraciones obtenidas despu´s de cada uno de los cuatro tipos de movimiento son las siguientes: e ◦ Si accion[Sm .4. ai ] de la tabla de acciones del analizador. an $) donde Sq = ir a[Sm−r . . no se ha modificado o la entrada en curso). el lado derecho de la producci´n o (el analizador ha extra´ 2r s´ ıdo ımbolos de la pila. . . el an´lisis sint´ctico ha terminado con ´xito. La secuencia de s´ ımbolos gramaticales extra´ ıdos de la pila. ai ] =error. b) Reducir por una producci´n gramatical A → β. . . 37 2. A] y r es la longitud de β. luego ha introducido A. ◦ Si accion[Sm . el estado del tope de la pila. el lado izquierdo a de la producci´n. an $) El siguiente movimiento del analizador se determina leyendo ai . la entrada de ir a[Sm−r . . ai ai+1 . . donde Sp es un estado. ai ] =reducir A → β. Xm Sm . el s´ ımbolo de la entrada en curso. 3. n c) Aceptar. Xm . . el analizador ejecuta un movimiento de desplazamiento entrando en la configuraci´n o (S0 X1 S1 X2 S2 . an §) (el analizador ha desplazado a la pila el s´ ımbolo de la entrada en curso y el siguiente estado. y Sq . pudiendo obtenerse uno de los siguientes valores: a) Desplazar Sp . Repetir hasta terminar la tira de entrada. y ai+1 se convierte en el s´ ımbolo de entrada actual). ai ] de la tabla de acciones del analizador. aceptarla o llegar a un error. ai ] =aceptar. ai+1 . entrando en la configuraci´n o o (S0 X1 S1 X2 S2 . entonces el analizador ejecuta un movimiento de reducci´n.

cerradura e ir a: Gram´tica aumentada Dada una gram´tica G. o ´ Operaci´n ir a La segunda funci´n util es ir a(I. Por esta raz´n. Elementos nucleares. De hecho. elemento) de a a una gram´tica G a una producci´n de dicha gram´tica que contiene un punto en algua o a na posici´n del lado derecho. o o Una serie de conjuntos de elementos LR(0) se denomina colecci´n can´nica LR(0) o o y proporciona la base para construir analizadores sint´cticos SLR. la producci´n A → XY Z produce los cuatro o o elementos: A → .38 ´ ´ CAP´ ITULO 4. se pueden dividir todos los conjuntos de los elementos que interesan en dos clases: 1. o Obs´rvese que si se a˜ade una producci´n de B a la cerradura de I con el punto e n o en el extremo izquierdo. la gram´tica aumentada G resulta de a a a a˜adir a G la regla S → S. entonces B → .γ ∈ cerradura(I). entonces todas las producciones de B se a˜adir´n de man a nera similar a la cerradura.4. a ∗ ∀A → α·Bβ ∈ cerradura(I). se incluye B → ·γ en o cerradura(I). ∗ Se aplica lo anterior hasta que cerradura(I) no var´ ıa. Elementos no nucleares. simplemente. 2.1. e . si ∃B → γ ∈ P. Intuitivamente. y el elemento inicial S → ·S. PARSERS Construcci´n de tablas de an´lisis sint´ctico SLR o a a Se llama elemento de an´lisis sint´ctico LR(0) (o. todos los elementos cuyos puntos est´n en el extremo a izquierdo. donde I es un conjunto de elemeno tos y X es un s´ ımbolo de la gram´tica (X ∈ (N ∪ T )).XY Z A → X. Se puede calcular la funci´n cerradura como se muestra en la tabla 4. n a Cerradura Dado un subconjunto I de elementos LR(0): ∗ Todo elemento de I est´ en cerradura(I). X). La producci´n A → ε s´lo genera el elemento A → ·. donde S es el axioma de la gram´tica. ANALISIS SINTACTICO. tambi´n se espera ver o e una subcadena derivable de γ en este punto. Por tanto.Z A → XY Z. Se define como la cerradura a del conjunto de todos los elementos A → αX · β tales que A → α · Xβ est´ en I. Si B → γ es una producci´n.Y Z A → XY. si A → α · Bβ est´ en cerradura(I) indica que. todos los elementos cuyos puntos no est´n en el extremo e izquierdo. se cree posible ver a continuaci´n una cadena a a o derivable de B como entrada. Para construir la coa lecci´n can´nica LR(0) para una gram´tica se define una gram´tica aumentada y dos o o a a funciones. en alg´n momento a u del proceso de an´lisis sint´ctico.

. n return J. .X) no est´ vac´o y e ı no est´ en C do e a~adir ir_a(I. .S)}. a 2. n a end Cuadro 4. end 39 Cuadro 4. un elemento ser´ v´lido o a a para muchos prefijos. repeat for cada elemento A->a.4: Algoritmo de c´lculo de cerradura. n until no se puedan a~adir m´s conjuntos de elementos a C. se aumenta para producir G . Dada una gram´tica G. o o o Diremos que un elemento A → β1 β2 es un elemento v´lido para un prefijo variable a ∗ αβ1 si existe una derivaci´n S ⇒ αAω⇒ αβ1 β2 ω. Los estados se obtienen a partir de los Ii (siendo Ik el estado k). o a o a procedimiento elementos_LR0 (G) begin C={cerradura(S’->. Se construye la colecci´n can´nica LR(0): o o C = {I0 . En general. Vistos estos conceptos. I1 .´ ´ 4.Bb en J y cada produccion B->l de G tal que B->.4. . Esta colecci´n nos permitir´ obtener el aut´mata a partir de la gram´tica. podemos ver el algoritmo para la obtenci´n de la coo lecci´n can´nica LR(0) de un conjunto de elementos LR(0) para una gram´tica auo o a mentada G . n until no se puedan a~adir mas elementos a J.X) a C. los pasos de construcci´n de la tabla son: o 1.l no este en J do a~adir B->. /* gram´tica aumentada */ a repeat for cada conjunto de elementos I en C y cada simbolo gramatical X de G tal que ir_a(I. In } 3. a Definidos estos conceptos.5: Construcci´n de la colecci´n can´nica LR(0).l a J. . ANALISIS SINTACTICO LR(K) funcion cerradura(I) begin J=I.

Las casillas se rellenan: ´ ´ CAP´ ITULO 4.aβ ∈ Ii . $] = aceptar. entonces se hace accion[i. a] pide una reducci´n por A → α s´lo si el siguiente o o s´ ımbolo de la entrada es a De este modo. ∈ Ii . no es capaz de mirar un elemento m´s all´. varias reducciones con diferentes no terminales a. entonces se hace Ir a[i. e Ir a(Ii . a] = reducir A → α ∀a ∈ siguiente(A). 6. a) = Ij . es importante saber que el m´todo SLR o e no funciona para cualquier gram´tica.40 4. frente al SLR. entonces se hace accion[i. A continuaci´n veremos a a o el m´todo LR-can´nico. c) Si S → S. algo que proporciona su potencia al LR-can´nico. Si Ir a(Ii . ANALISIS SINTACTICO. podemos tener varios casos. . que s´ lo hace. e o ı Construcci´n de tablas de an´lisis sint´ctico LR-can´nico o a a o El m´todo LR-can´nico es un m´todo de construcci´n de tablas de an´lisis sint´ctie o e o a a co m´s general. pero tambi´n m´s costoso desde el punto de vista del dise˜o. el elemento [A → α. a 5. A] = j. a] en lugar de [A → α. PARSERS a) Si A → α. A) = Ij . Si las acciones anteriores generan acciones contradictorias (aparece m´s a de una acci´n en alguna casilla de alguna de las tablas) se dice que la o gram´tica no es SLR. es decir.β] como en SLR. Todas las entradas no definidas por las reglas anteriores son consideradas error. ∈ Ii . o El m´todo para construir la colecci´n de conjuntos de elementos v´lidos ahora es e o a fundamentalmente el mismo que la forma en que se construye la colecci´n can´nica de o o conjuntos de elementos del an´lisis sint´ctico LR(0). SLR no a tiene en cuenta m´s que aqu´lla parte de la cadena de entrada que ya ha le´ para tomar a e ıdo decisiones. como hemos visto. Aunque no veremos los criterios de decisi´n. a a e a n El LR-can´nico a˜ade informaci´n adicional al estado redefiniendo los elementos de o n o an´lisis para incluir un s´ a ımbolo terminal como segundo componente. a] = desplazar j. Este nuevo elemento que se tiene en cuenta para la predicci´n.. b) Si A → α. s´lo hay que modificar los dos proa a o cedimientos Cerradura e Ir a. El problema es que. recibe el nombre de s´ o ımbolo de anticipaci´n. siendo A un no terminal. o y: no tiene efecto si β = ε si β = ε.β. entonces se hace accion[i. de forma que pasan a ser de la forma [A → α. m´s potente.

$]). a o function Ir_a(I. return (cerradura(J)).´ ´ 4.a] esta en I. n end Cuadro 4. cada produccion B->r en G’ y cada terminal b de Primero(ba) tal que [B->.r. n until no se puedan a~adir mas conjuntos de elementos a C.b] no esta en I. end Cuadro 4. a] en I. b] a I.Bb.7: Algoritmo de c´lculo de Ir a para LR-can´nico. do a~adir [B->. n return (I).S. o a o . repeat for cada conjunto de elementos I en C y cada simbolo X tal que Ir_a(I.X) no sea vacio y no este en C. ANALISIS SINTACTICO LR(K) 41 function cerradura(I) begin repeat for cada elemento [A->s.X) a C. end Cuadro 4.b. a o procedure elementos(G’) /* gramatica aumentada */ begin C=cerradura([S’->.4.X) begin J=conjunto de los elementos [A->sX.r. do a~adir Ir_a(I.Xb. n until no se puedan a~adir mas elementos a I.6: Algoritmo de c´lculo de cerradura para LR-can´nico.8: Construcci´n del conjunto de los elementos de an´lisis LR-can´nico.a] tal que [A->s.

Si la gram´tica realmente es LALR. que s´lo var´ a o ıan en el elemento de anticipaci´n (lookahead ). a] = reducir A → α (con A = S ).. Es decir. a 2. . de los cuales. consiste unicamente en traducir las modificaciones ´ a las celdas de la misma. para todo terminal a. 5. I1 . o El LR-can´nico es un m´todo de an´lisis muy potente. producci´n) de los elementos LR(1) es o o o el mismo en varios estados. 6. El m´todo LALR lo unico que hace es reunir o e ´ esos pares (conjuntos) de estados en uno solo. pero que produce muchos o e a estados. comprobaremos que el coraz´n (core. a] = desplazar j. Evidentemente. aplicado el m´todo LR-can´nico y obtenida o a e o la tabla de an´lisis sint´ctico (o simplemente el aut´mata finito). . ..42 ´ ´ CAP´ ITULO 4. entonces se hace accion[i. para fusionar dos estados no s´lo o es necesario que el coraz´n de todas las reglas de ambos sean iguales (no vale tampoco o que uno sea subconjunto del otro). es decir. a La obtenci´n de la tabla de an´lisis sint´ctico LALR a partir del nuevo aut´mata o a a o simplificado (comprimido) es sencilla. . 4. la fusi´n de los estados debe ir acompa˜ada por la compatibilidad de o n transiciones entre los estados que se fusionan. b] ∈ Ii e Ir a(Ii . generalmente dos (aunque pueden ser m´s). Las casillas se rellenan: a) Si [A → α. $] = aceptar. entonces se hace accion[i. PARSERS Una vez que tenemos el aut´mata finito (su diagrama de transici´n de estados). agrupando los elementos de anticipaci´n a o la derecha. . los o o pasos para la construcci´n de la tabla de an´lisis sint´ctico son: o a a 1. Si Ir a(Ii . Si las reglas anteriores producen un conflicto.aβ. sino que adem´s estados fusionados deben transicionar a a estados fusionados. se aumenta para producir G . In }. b) Si [A → α. se dice que la gram´tica no a es LR(1). Construcci´n de tablas de an´lisis sint´ctico LALR o a a Veremos el m´todo LALR como una “consecuencia” del LR-can´nico. Se construye C = {I0 . la colecci´n de conjuntos de elementos o LR(1) para G . A) = Ij . entonces se hace accion[i. El estado i se obtiene a partir de Ii . construiremos a partir a a o de ello un LALR realizando una compresi´n de estados. en gran mayor´ de ocasiones podemos hacer una compresi´n de ıa o la siguiente manera: analizando los estados del aut´mata generado por el m´todo LRo e can´nico. como una e o simplificaci´n.. Todas las entradas no definidas por las reglas anteriores se consideran error. a] ∈ Ii . A] = j. Dada una gram´tica G. dada una gram´tica. $] ∈ Ii . a) = Ij . ıamos que la gram´tica no es LALR. 3. ANALISIS SINTACTICO. entonces se hace Ir a[i. no deber´ haber problema a ıa alguno. c) Si [S → S. Si ello no ocurriera as´ dir´ ı.

como veremos. Adem´s. pointers. . el an´lisis sint´ctico (parsers. la parte del an´lisis que juzga el sentido a de las construcciones que han sido previamente validadas por scanners y parsers. . c´mo se a˜aden reglas sem´nticas de este tipo a las estructuras que ya hemos o n a estudiado (ser´. o a a real. veremos c´mo la definici´n de reglas en este caso estar´ ´ o o o o a ıntimamente relacionado con la arquitectura subyacente y definiremos nuestra “m´quina te´rica”. particularmente a a de grafos ac´ ıclicos dirigidos. . . Veremos. que detectaban las palabras y comprobaban a e si estaban bien formadas). o a o pues. al fin y al cabo. En an´lisis de tipos haremos referencia tanto a los tipos b´sicos (integer. que estudiaban la correcci´n en a a o la estructuras de las frases) y nos falta. o o En la figura 5. para a o trabajar sobre ella. En cuanto a la genea raci´n de c´digo. generaci´n de c´digo objeto. ). a o gesti´n de memoria. por tanto. operadores que. ) como a los constructores de tipos. a n a o El mecanismo t´ ıpico es trasladar las comprobaciones pertinentes a los nodos del ´rbol a sint´ctico que hemos aprendido a construir en el cap´ a ıtulo anterior (asignando un conjunto de rutinas a los mismos. entre otras cosas.Cap´ ıtulo 5 An´lisis Sem´ntico a a Traducci´n dirigida por la sintaxis o En el presente tema veremos el ultimo de los tipos de an´lisis que mencionamos en la ´ a introducci´n de la asignatura (figura 1. la generaci´n de c´digo. p´gina 7): el an´lisis sem´ntico. 43 . trabajando con tipos b´sicos. y es una alternativa al dise˜o m´s formal de esquemas de n a traducci´n. que se ocupar´n.1. arrays.. La encarnaci´n m´s simple de esta tarea es la comprobaci´n de tipos. ). a˜adir m´s informaci´n a las reglas que ya manejamos).1 (p´gina 44) se muestra un esquema que relaciona los temas principales a que veremos en breve en el seno de la traducci´n dirigida por la sintaxis. . construyen otros tipos (records. la o e a a a o o a tarea se ver´ simplificada tambi´n porque usaremos la misma sintaxis para la sem´ntica a e a que para la generaci´n de c´digo. Al situar en este punto la clave de o o o la acci´n tambi´n ser´ m´s f´cil. o a a a Ya hemos visto el an´lisis l´xico (scanners.. char. . Esta parte o de la disciplina del an´lisis sem´ntico se apoya en conceptos de grafos. de la comprobaci´n de tipos.

.1: Esquema de an´lisis sem´ntico. c2 . ..44 ´ ´ CAP´ ITULO 5.D. sintesis Generacion de codigo intermedio Arquitectura: − tercetos − cuartetos − codigo 3 direcciones − RPN Gramatica Traduccion dirigida por la sintaxis EDT Reglas semantica Analisis de tipos Sistemas de tipos Polimorfismo Sobrecarga Notaciones Tipos basicos Definicion de reglas Equivalencia de tipos Implementacion: − estructuras de control − expresiones − asignaciones − . a a 5.A. . dada una producci´n o o A → α tendremos un conjunto de reglas sem´nticas b = f (c1 . .. cn ) donde ci son los a atributos. en la traducci´n dirigida por la sintaxis. ANALISIS SEMANTICO Analisis Semantico Notaciones Grafos G. Conversion de tipos Comprobacion de tipos Constructores de tipos Maquina teorica Figura 5. . Notaci´n o Para describir acciones sem´nticas utilizaremos dos elementos: a reglas atributos de tal manera que.1.

5.2. SISTEMAS DE TIPOS

45

Cada nodo de evaluaci´n en un ´rbol sint´ctico (nodos correspondientes a partes o a a izquierdas de reglas de producci´n de la gram´tica) tendr´ asociada una f (funci´n de o a a o evaluaci´n) que aplicar´ sobre sus propios ci y sobre cj relativos o pertenecientes a sus o a hijos directos. Este proceso, que se da t´ ıpicamente en la evaluaci´n ascendente de izquierda o a derecha, se denomina arrastre de informaci´n. o

5.2.
5.2.1.

Sistemas de Tipos
Tipos b´sicos a

Un sistema de tipos es el conjunto de expresiones de tipos que tenemos a disposici´n en el lenguaje. A su vez, una expresi´n de tipo es, bien un tipo b´sico, o bien el o o a resultado de aplicar un constructor de tipos a un tipo b´sico. a Nosotros consideraremos: Tipos b´sicos los siguientes: a √ boolean √ char √ integer √ real como en la mayor´ de los lenguajes, y adem´s: ıa a √ error tipo √ void Constructores de tipos los siguientes: √ Matrices, que representaremos array(I,T) donde I es el tipo de los ´ ındices y T el de las variables que contendr´ el array. a √ Productos, que se definen: si T1 y T2 son expresiones de tipos, entonces T1 × T2 es otra expresi´n de tipo y se denomina producto. o √ Registros, consecuencia de la definici´n de productos, pues no son o m´s que “productos con nombres”. a √ Apuntadores o punteros, que representaremos pointer(T) donde T es el tipo a que apuntan. √ Funciones, que representaremos T1 × T2 × . . . × Tn → Tp , donde T1 × T2 × . . . × Tn es el dominio de la funci´n (de modo que los o argumentos de una funci´n son un producto) y Tp el tipo del rango. o Adem´s, claro est´, pueden construirse “constructores de constructores” a a (punteros a punteros, punteros a funciones, arrays, de punteros,. . . ). Esto dar´ lugar a los problemas de equivalencia que veremos m´s adelante. a a

46 Existen dos tipos de atributos:

´ ´ CAP´ ITULO 5. ANALISIS SEMANTICO

heredados, cuyo valor se calcula a partir de los valores de los atributos de los hermanos y del padre del nodo al que pertenecen sintetizados, cuyo valor se calcula a partir de los valores de los atributos de los hijos del nodo al que pertenecen En traducci´n dirigida por la sintaxis usaremos unicamente atributos sintetizados, o ´ raz´n por la que en alguna bibliograf´ puede encontrarse la denominaci´n traducci´n o ıa o o (definici´n) dirigida por la sintaxis con atributos sintetizados. o

En adelante, usaremos la siguiente gram´tica como referencia en explicaciones, ejema plos y ejercicios: P D T E S S S S -> -> -> -> -> -> -> -> D;E D;D | id:T char | integer | array[num] of T | ^T literal | numero | id | E mod E | E[E] | ^E id:=E if E then S1 while E do S1 S1;S2

Cuadro 5.1: Gram´tica de referencia. a Veamos a continuaci´n algunas reglas sem´nticas : o a → La comprobaci´n de tipos matriciales: o E → E 1 [E 2 ] requerir´ comprobar que E 2 es de tipo entero1 y asignar al tipo de E (no terminal a de arrastre de informaci´n) el tipo de los elementos del array: o E.tipo = if (E2.tipo=integer) and (E1.tipo=array[S,T]) then T else error_tipo;
1

Supondremos que el lenguaje s´lo permite que los ´ o ındices de los arrays sean enteros.

5.2. SISTEMAS DE TIPOS → La comprobaci´n de operaciones o E → E 1 mod E 2 (donde mod juega el mismo papel que cualquier otra operaci´n), o E.tipo = if (E1.tipo=integer) and (E2.tipo=integer) then integer else error_tipo;

47

→ La comprobaci´n de tipos en proposiciones del lenguaje como o S → if E then S 1 S → while E do S 1 es tan sencilla como S.tipo = if (E.tipo=boolean) then S1.tipo else error_tipo;

→ La comprobaci´n de la concatenaci´n de proposiciones, o o S → S1; S2 se har´ ıa: S.tipo = if (S1.tipo=void) and (S2.tipo=void) then void else error_tipo;

→ La comprobaci´n de tipos asociada a la asignaci´n o o S → id = E es de las m´s simples: a S.tipo = if (id.tipo=E.tipo) then void else error_tipo;

tipo=S) and (E1.. → La comprobaci´n de tipos relativa a funciones.tipo = literal | numero | integer | real | . esto es.. por ultimo.2. La comprobaci´n de la equivalencia de dos o o expresiones de tipo es tan trivial como comparar bit a bit sus respectivas codificaciones.tipo = if (E2.48 ´ ´ CAP´ ITULO 5.2.tipo=(fun S->T)) then T else error_tipo. . ANALISIS SEMANTICO → La comprobaci´n de tipos en expresiones o variables en s´ o ı E E E E E no tiene ning´n secreto.. Esta estrategia tiene la ventaja de que ahorra memoria (no se necesita tanto arrastre de informaci´n) y. → literal → numero → int → real → . asignar un c´digo binario a cada constructor o o de tipo y cada tipo b´sico. de suerte que cada expresi´n pueda codificarse mediante una a o secuencia de ceros y unos que represente los c´digos de los constructores y tipos b´sicos o a que se han utilizado para su composici´n. podr´ suceder que dos tipos compuestos distintos tuviesen como a a ıa representaci´n la misma secuencia de bits (ya que no se reflejan. es o o m´s r´pida. u E. son expresiones de tipo declarado id´ntico. Equivalencia de expresiones de tipo Se consideran dos tipos de equivalencia para las expresiones de tipo: Equivalencia estructural Se dice que dos expresiones de tipo tienen equivalencia estructural cuando son del mismo tipo b´sico o son resultado de a aplicar los mismos constructores en el mismo orden a los mismos tipos b´sicos (o incluso expresiones de tipo). es decir. tama˜os de o n matrices o argumentos de funciones). o ´ E → E 1 (E 2 ) se resuelve E. 5.. por ejemplo. a Equivalencia por nombre Se dice que dos expresiones de tipo tienen equivalencia por nombre cuando son del mismo “nombre” de tipo. puesto que la comparaci´n binaria puede realizarse en la propia ALU. e Una forma de realizar la comprobaci´n de equivalencia de tipos es mediante la codio ficaci´n de expresiones de tipo. Sin embargo.

2. tambi´n podemos enfrentarnos a la sobrecarga de funciones. mientras que cuando es expl´ o ıcitamente indicada por el programador es lo que conocemos como cast.. entonces? Mediante una conversi´n de tipo. La sobrecarga puede afectar tambi´n a los s´ e ımbolos.4. begin if (s y t son del mismo tipo basico) then return true else if (s=array(s1. En ese caso. ante una construcci´n o E → E 1 (E 2 ) . Sobrecarga Se dice que un operador est´ sobrecargado cuando en funci´n de las variables con las a o que trabaja tiene un significado u otro.t1) and equivest(s2. si se sobrecargan u los par´ntesis para referenciar matrices).t2)) else if (s=pointer(s1) and t=pointer(t1)) then return equivest(s1.s2) and t=array(t1.2.2. Restringi´ndonos a lo que hemos visto e hasta ahora. 5.5.t):boolean..t1) and equivest(s2.t2)) else if (s=s1xs2 and t=t1xt2) then return (equivest(s1. Conversores de tipo a=b×c Sup´ngase la situaci´n: o o donde a y c son reales mientras que b es un entero.. else return false end 49 Cuadro 5. perfectamente viable ¿c´mo es posible. e Asimismo. en cuyo caso puede crear problemas de ambig¨edad (por ejemplo. cuando es impl´ o ıcita. SISTEMAS DE TIPOS function equivest(s. est´ claro que esto fallar´ mas nuestra experiencia nos dice que es algo a ıa.3.t1) else if .t2)) then return (equivest(s1. motivo por el que se recomienda evitarlo.. o 5. hecha autom´ticamente por el compilador se a denomina coerci´n. . que recibe el e nombre de polimorfismo. o o Esta conversi´n.2: Algoritmo de comprobaci´n de equivalencia estructural.

tipo=real)) then real else if ((E1.tipo=integer)) then integer else if ((E1.tipo=integer)) then real else if ((E1. ANALISIS SEMANTICO Regla Sem´ntica a E.tipo = if ((E1.tipo=integer) and (E2. o o se admite que la expresi´n de tipo E 2 no sea unica.tipo=integer) and (E2.tipo=real)) then real else error tipo Cuadro 5.entrada) E.tipo = buscaTDS(id.tipo = { t / existen s en E2.tipos.tipo = real E.tipo=real) and (E2. s->t en E1.50 Producci´n o E → numero E → numero · numero E → id E → E 1 opE 2 ´ ´ CAP´ ITULO 5.tipos } . Se trabaja entonces con un conjunto o ´ 2 de expresiones de tipo posibles (E pasa a ser un conjunto) con la repercusi´n y modifio caciones que ello introduce en las reglas sem´nticas que hemos visto: a E.tipo = integer E.tipo=real) and (E2.3: Comprobaci´n de tipos para coerci´n de entero a real.

tambi´n favorece la reutilizaci´n.1. ya que el proceso de optimizaci´n trabajar´ sobre este a o a mismo c´digo intermedio. ya a que nos permitir´ optimizar mejor. ello va a reportar otros beneficios. del estilo o a = b op c (dos operandos y el resultado) ya que facilitar´ la generaci´n de c´digo objeto y tambi´n a o o e su depuraci´n. Notaciones No existe un “lenguaje intermedio universal”.Cap´ ıtulo 6 Generaci´n de C´digo Intermedio o o Tras el an´lisis sem´ntico llega el momento de generar lo que denominamos c´digo a a o intermedio. la raz´n por la que se genera o c´digo intermedio es evitar tener que construir un compilador desde cero para todas y o cada una de las diferentes arquitecturas. Adem´s. o ´ e o 6. Por ultimo. Los m´s conocidos y usados. o 51 . que posteriormente ser´ optimizado antes de dar lugar al definitivo c´digo a o objeto. son: Notaci´n Polaca Inversa (RPN) o Cuartetos Tercetos. que verea mos. Tercetos indirectos Lenguajes a tres direcciones P-c´digo o Interesa tener c´digo basado en 3 direcciones. El motivo por el que se realiza este paso intermedio.

@ es un s´ o ımbolo de control. o En RPN los par´ntesis se ignoran y la traducci´n de una expresi´n a esta notaci´n e o o o sigue las directrices que se muestran a continuaci´n: o Producci´n o S→E E→T E →E+T E →E−T E → −T T →F T →T ∗F T → T /F F → id F → (E) a Reglas Sem´nticas a P (i) = + P (i) = − P (i) = @ i=i+1 i=i−1 i = i + 1a P (i) = ∗ i=i−1 P (i) = / i=i−1 P (i) = buscarT DS(i) i = i − 1 Arrastre de informaci´n. Notaci´n Polaca Inversa (RPN) o Es la primera notaci´n de c´digo intermedio que se utiliz´. Con una pila es posible o o o construir un generador de c´digo muy sencillo.1: Notaci´n Polaca Inversa (RPN).. tambi´n llamada postfija representa las jerarqu´ en o e ıas forma de ´rbol de modo que cada nodo aparece inmediatamente despu´s de sus hijos.52 ´ CAP´ ITULO 6. finbloque read write decl sub := b bp bn bc Cuadro 6. y es en lo que se bas´ esta idea..1.1. El a e formato postfijo es f´cil de traducir y pasar a c´digo m´quina con ayuda de una pila: se a o a colocan los operandos y despu´s los operadores. Cuadro 6. o . o o La notaci´n polaca inversa.2: Traducci´n a RPN. CODIGO INTERMEDIO 6./ * mod div sqrt sin cos tan abs ord char bloque . e OPERADORES FUNCIONES BLOQUES DE CODIGO ENTRADA/SALIDA MATRICES ASIGNACION BIFURCACIONES SALTO INCONDICIONAL SALTO SI POSITIVO SALTO SI NEGATIVO SALTO SI CERO + .

3. X1. n. el resultado en c´digo e o intermedio.1. NOTACIONES donde la sem´ntica se asocia a cada nodo. . ) (JE. Se hace de abajo a arriba y de izquierda a derecha.1. obteniendo. E. B. por diferentes t´cnicas que veremos en este tema. . Los s´ ımbolos usados en esta notaci´n son: o OPERACIONES ARITMETICAS ASIGNACION X:=E ENTRADA/SALIDA SALTO ABSOLUTO INCONDICIONAL SALTO RELATIVO INCONDICIONAL SALTO INCONDICIONAL SALTO SI IGUAL A CERO SALTO SI MAYOR QUE CERO SALTO SI MENOR QUE CERO SALTO SI IGUALES SALTO SI MAYOR SALTO SI MENOR + . ) n = posicion relativa actual (JZ. X2) Cuadro 6. n.* / ^ mod abs sqrt sin cos (:=. . E. X) (JP. E. X1. ) n = posicion absoluta a saltar (JR. Tercetos La notaci´n de tercetos (tambi´n llamados triples en alguna bibliograf´ como [4]) o e ıa. . T1 ) donde T1 es un reıa gistro temporal. A.2.1. n. E.3: Notaci´n de cuartetos. < operando1 >. < operando2 >. n. se diferencia de la de cuartetos en que el resultado queda impl´ ıcito en el propio terceto. n. X2) (JL. . A/B. 6. n. < resultado >) es decir. siendo su formato: . [4]) tiene la siguiente forma: (< operador >. . n. ser´ representado como (/. por ejemplo. ) (JGZ. . X2) (JG. a 53 Hay dos formas de evaluar un ´rbol sint´ctico de una expresi´n: mediante esquemas de a a o traducci´n (no lo veremos) o mediante traducci´n dirigida por la sintaxis (lo que estamos o o viendo).6. X) (read. n. Cuartetos La notaci´n de cuartetos (tambi´n llamados cu´druplos en alguna bibliograf´ como o e a ıa. ) (JLZ. X1. X) (write. de manera determinista. o 6.

que recibe su o o a nombre por razones obvias debidas a su estructura.1. CODIGO INTERMEDIO (< operador >. La ventaja de los tercetos es que ocupan mucha menos memoria en variables temporales. que utilizaremos como base de o a aqu´ en adelante. la recolocaci´n del c´digo en optimizaci´n es m´s compleja porque o o o a hay que mantener las referencias correctamente. aunque pueden ser “simuladas”. de manera que no es necesario o o reescribir los tercetos -sus referencias. que son tercetos junto con los que se guarda un vector secuencia que marca el orden de ejecuci´n tras la recolocaci´n. M´quina Objeto a Para seguir concretando el el proceso de generaci´n de c´digo objeto. referenciando al anterior. Adem´s. b) etiquetado como [x] y seguidamente el terceto (+. [x]. destino con las palabras reservadas cl´sicas a . describiremos o o a continuaci´n una m´quina secuencial Von Neumann. en optimizaci´n e o de c´digo. Esta m´quina objeto tendr´: a a n registros R0 .2. < operando1 >. . c). quiz´s por su mayor claridad (recuerda al pseudoc´digo). Supondremos una CPU con una serie de operaciones (instrucciones) y ı una forma de mover datos entre la memoria y los registros. llamada c´digo a tres direcciones. 6. como haremos nosotros. < operando2 >) de manera que para hacer a + b + c tendr´ ıamos en primer lugar el terceto (+. se usa con mayor frea o cuencia en los lenguajes intermedios y tambi´n.en caso de reordenamiento. JG y JL. C´digo a tres direcciones o Esta ultima notaci´n que veremos.3). . Es una notaci´n m´s. el resto de la notaci´n es gemela a la de cuartetos (tabla 6. Para enfrentar este problema surgen los tercetos indirectos. ti = tj op tk y que. o 6. si los tercetos a se repiten s´lo es necesario repetirlos en el vector secuencia y no “f´ o ısicamente”. es en cierto ´ o o modo una generalizaci´n de todas las anteriores. Por su estructura. R1 . o Los s´ ımbolos que utiliza son los mismos que en cuartetos y tercetos. a. .54 ´ CAP´ ITULO 6. Rn−1 instrucciones de la forma operacion f uente. Por otra parte. los tercetos carecen de instrucciones JE. con la salvedad de que para los saltos se utiliza la palabra reservada goto.4.

u 2 1 . etc. Cuadro 6. c C es una constante.1. . registroI registroJ registroJ temporalK De manera que si tomamos esta estructura como “construcci´n base” a la que denoo minamos caja. o Sin tener en cuenta cuestiones como si los registros est´n previamente ocupados. el c´digo al final es un conjunto de cajas 2 . registroI. operandoB. se buscan las constantes en la TDS. registroJ.2. M´todo de las Cajas e Es una manera de modelizar las operaciones entre dos operandos..4.2.4: Modos de direccionamiento 6. o R es un registro de la CPU. Todas siguen el siguiente esquema: MOV MOV OPERACION_X MOV operandoA. MAQUINA OBJETO ADD SUB MUL DIV CALL GOTO MOVE 55 (llamada a funciones) (saltos) (accesos a memoria: cargas/almacenamientos) Los modos de direccionamiento que consideraremos ser´n los presentes en la tabla 6. a El paso de este “ensamblador” despu´s de “encajonado” a c´digo m´quina es trivial: la operaci´n se e o a o codifica seg´n un convenio.´ 6. Si analizamos de manera sencilla1 las posibles instrucciones que manejamos. veremos que casi todas ellas son muy similares. a Modo absoluto registro indexado registro indirecto indexado indirecto literal a b Forma Direcci´n o a M M R Rb C(R) C+contenido(R)c ∗R contenido(R) ∗C(R) contenido(C+contenido(R)) #C C Coste 1 0 1 1 2 1 M es una posici´n de memoria principal. .

es A[inf ]). o El c´digo que genera un cuarteto o (< operacion >. entendiendo por bondad del c´digo una combinaci´n entre su rao o o pidez y la memoria que ocupa y/o utiliza. igual que la generaci´n de variables o temporales l´gicamente innecesarias. Acceso a elementos de matrices Se puede acceder r´pidamente a los elementos de una matriz si se guardan en un bloque a de posiciones consecutivas. for. while). sabemos generar todas las instrucciones de control (if. que se sustituyen en la segunda. < operando1 >. < operando2 >. por supuesto.2. CODIGO INTERMEDIO El problema es que el c´digo resultante de aplicar al pie de la letra estas traducciones o es un c´digo muy malo. < destino >) (y. operandoB. do. registroI registroJ registroJ destino La generaci´n de c´digo a tres direcciones tambi´n se hace por sem´ntica. o 6. registroJ.56 ´ CAP´ ITULO 6. registroI. entonces el i-´simo elemento de la matriz A comienza en la posici´n e o base + (i − inf ) × a donde inf es el l´ ımite inferior de los sub´ ındices y base es la direcci´n relativa de la posici´n o o de memoria asignada a la matriz (es decir.2. Los int´rpreo o e a e tes cl´sicos (puros) usaban RPN ya que es m´s intuitivo (ya contamos con una pila). una vez que ya se conoce la direcci´n base.3. puesto que es un c´digo en absoluto optimizado. La expresi´n anterior se puede evaluar parcialmente durante la compilaci´n si se escribe o o como i × a + (base − inf × a) ya que la subexpresi´n base − inf × a se puede evaluar cuando aparece la declaraci´n de o o la matriz y ser guardada en entrada de la TDS de A. . para evitar o la carga sucesiva del mismo operador varias veces. a a Una forma sencilla de optimizaci´n que se puede hacer en tiempo de compilaci´n es o o mantener una tabla de localizaci´n del almacenamiento de los operandos. Generaci´n y Representaci´n de saltos o o Si sabemos generar saltos. Son necesarias dos “pasadas” por el c´digo para hacer eso: en la primera se o generan etiquetas relativas.2. Si el ancho de cada elemento de la matriz es a. o 6. tambi´n un terceto) es tambi´n una caja: e e MOV MOV OPERACION_X MOV operandoA.

todo ello almacenado en la TDS. en caso de tener una matriz triangular de la que se almacenen s´lo los ele´ o i + (j − 1) × j mentos por debajo de la diagonal. . . . si supj fuese el l´ ımite superior para el valor de j. . ´ e Generalizando. . . supn ] donde inf1 . data de 1970 y es usada por lenguajes como Pascal. j] ser´ ıa . jn ] tendr´ la direcci´n a o base + + + + + (j1 − i1 ) × e2 × e3 × . bien en forma de columnas (columna a columna). . Esta estrategia se debe o a McKeeman. . . j2 . . . bien en forma de filas (fila a fila). si tenemos una matriz de n dimensiones M [inf1 . sup1 .4. (jn−1 − in−1 ) × en (jn − in ) + + + + Por ultimo.2. . ´ o la expresi´n anterior se puede reescribir como o ((i × nj ) + j) × a + (base − (infi × nj ) + infj ) × a) donde el ultimo t´rmino puede determinarse durante la misma. la direcci´n relativa de A[i. . Las soluciones hist´ricas que se han adoptado al respecto o son: Definici´n de un tama˜o m´ximo para cualquier string y reservar un banco de o n a memoria “troceado” al efecto. MAQUINA OBJETO 57 Esto se puede extender a los c´lculos de direcciones de elementos de matrices multidia mensionales. . y nj es el n´mero de u valores que puede tomar j. . × en . Es decir.´ 6. Horning y Wortman. . entonces nj = supj − infj + 1. . 2 6. Un ejemplo de uso de esta estrategia es Fortran. Mantenimiento de un registro con el par (nombre. . . Suponiendo que i y j son los unicos valores que no se conocen durante la compilaci´n. supn o son los l´ ımites superiores de cada dimensi´n y n es el n´mero de dimensiones de la matriz. sup2 . . sup2 . j] o se puede calcular mediante base + ((i − infi ) × nj + j − infj ) × a donde infi e infj son los l´ ımites inferiores de los valores de i y j. × en (j2 − i2 ) × e3 × e4 × ..2. infn . . inf2 .. . infn son los l´ ımites inferiores de cada dimensi´n. . Representaci´n de strings o Pero no s´lo la representaci´n de matrices es un problema. . Una matriz bidimensional se almacena generalmente en una de dos formas. o u dando por sentado que supi ≥ infi el n´mero de elementos de cada dimensi´n es de nuevo u o ei = supi −infi +1 y el acceso a un elemento cualquiera M [j1 . . . inf2 . . el acceso a cada uno de ellos [i. longitud del string) y un puntero a la direcci´n de inicio. sino que tambi´n lo es la o o e de las cadenas de caracteres. En el caso de una matriz bidimensional almacenada por filas. sup1 .

CODIGO INTERMEDIO .58 ´ CAP´ ITULO 6.

tiene problemas de portabilidad. en lugar de poner s = 2 * PI se pondr´ ıa s = 6. cada vez se usa menos debido al gran desarrollo hardware actual. incluso es preferible generar previamente varias variables que se utilicen en diferentes iteraciones que operar en cada interaci´n. e 7. subrutinas. Optimizaci´n en c´digo intermedio. realizada normalmente por el proo o gramador. por ejemplo.1. extremadamente ineficientes. e o o e como ya se coment´ en su momento. 2. Optimizaci´n en c´digo objeto. Optimizaci´n en c´digo fuente. o o a es la que realizan los compiladores gracias a la aplicaci´n de t´cnicas de o e an´lisis de flujo de datos. la m´s importante de las tres. muy orientada a la m´quina y muy o o a dependiente de ´sta.1. a 3. 7. o 59 .1. T´cnicas de optimizaci´n en c´digo fuente e o o Reducci´n simple o Reducci´n de operaciones o o Consiste en evitar incluir en el c´digo fuente operaciones que pueden ser realizadas o previamente. etc.Cap´ ıtulo 7 Optimizaci´n de C´digo o o T´cnicas de generaci´n de c´digo como el m´todo de las cajas que hemos visto son.283185 Esto es importante sobre todo si expresiones como la anterior se incluyen en lazos. En ocasiones. o o o Las t´cnicas de optimizaci´n se aplican a 3 niveles: e o 1. Por ello. la optimizao ci´n de c´digo puede verse incluso como parte de la propia generaci´n.

Reducci´n de potencias o Ante una operaci´n como o s = a**2 siempre es preferible utilizar s = a*a ya que no hay ning´n ensamblador que contenga instrucciones de potenciaci´n.1. Etiquetado del ´rbol: a PASO-2. ıa 7. como C y algunos bloques de Fortran. 7.1. Eliminaci´n de redundancias o Debe evitarse siempre la realizaci´n de c´lculos repetitivos. a o PASO-2.5. donde es frecuente encontrar expresiones similares a: M[i][j][k] = M[i x bi x di][j x bj x dj][k x bk x dk] + incremento donde toda la primera parte1 supone una redundancia y podr´ extraerse. Reacondicionamiento o Reordenamiento de instrucciones Consiste en alterar el orden de secuenciaci´n de las instrucciones (sin que var´ su o ıe sem´ntica.60 ´ ´ CAP´ ITULO 7.3.4. OPTIMIZACION DE CODIGO 7. mienu o tras que todos incluyen el producto puesto que es una operaci´n que ya las propias ALUs o realizan. Reordenaci´n de expresiones: Algoritmo de Nakata o El algoritmo de Nakata y Anderson data de 1964 y su objetivo es marcar una pauta para la reordenaci´n de expresiones: o PASO-1. La optimizaci´n siempre o a o centra su especial atenci´n en cuerpos cr´ o ıticos como los lazos.1. como el uso de un menor n´mero de registros o o u y variables temporales. Construir el ´rbol de la expresi´n a reordenar. . IF n es hoja THEN IF n es hijo m´s a la derecha de su padre THEN a etiqueta(n) = 1 ELSE 1 En lenguajes que manejen las matrices como punteros.2. 7.1. claro est´) a fin de conseguir tanto la generaci´n de menos instrucciones de a a o c´digo intermedio como de c´digo objeto.1.

N a[i] = t otro i 7.´ 7. nk hijos ordenados /* por etiqueta */ THEN etiqueta(n) = max(etiqueta(ni) + i ..cn) i = 1. para generar la expresi´n a o se parte de la ra´z y se desciende por la rama del sub´rbol ı a cuya etiqueta contenga el valor m´ximo. An´lisis Global del Flujo de Datos a Detecci´n de lazos en los grafos de flujo o Decimos que un nodo d domina a un nodo n si todo camino desde el nodo inicial a n pasa obligatoriamente por d.3} .{1.. As´ por ejemplo. Una vez etiquetado el ´rbol.N a[i] = f(c1.2.1) END PASO-3.2} TODOS .c2..1. salvo si la operaci´n no es conmutativa.1. Extracci´n de invariantes o Llamamos expresiones invariantes de lazo a aqu´llas que pueden sacarse fuera de los e bucles ya que su valor no sufre variaci´n durante las iteraciones.2.2...cn) otro i se persigue construir preferiblemente t = f(c1.1 (p´gina 62): ı.... 7. n2.c2. seg´n la figura 7. i = 1. o 61 7. u a 1 2 3 4 domina domina domina domina TODOS 2 TODOS . As´ en lugar de o ı.... a En caso de igualdad....{1. ANALISIS GLOBAL DEL FLUJO DE DATOS etiqueta(n) = 0 ELSE BEGIN SEAN n1. se opta por la subrama de la derecha.6.2.

que domina a todos los nodos a o del lazo.9.62 ´ ´ CAP´ ITULO 7. o 5 6 7 8 9 10 domina domina domina domina domina domina 5 6 7.10 8.8. los nodos se identifican con bloques de instrucciones. .1: Grafo de Flujo y Arbol de Dominaci´n.9. a o Propiedades de los lazos Los lazos tienen una serie de propiedades que debemos considerar: Un lazo tendr´ un s´lo punto de entrada. OPTIMIZACION DE CODIGO 1 1 2 3 4 2 3 4 6 5 7 6 5 7 8 8 9 (a) Grafo de Flujo 10 9 ´ (b) Arbol de Dominaci´n o 10 ´ Figura 7.10 9 10 En el an´lisis de c´digo.

. pn de forma que pi es el punto que precede a una proposici´n y pi+1 o es el que la sigue. hasta d´nde llegan.´ 7. El tipo de an´lisis de flujo que se realice (hay varias estrategias diferentes) marcan su a diferencia en la definici´n del c´lculo de los conjuntos sal.1. es decir. p3 . S sal[S] 7. . Una definici´n se desactiva o o si durante el camino a otro punto se define de nuevo. En el primer caso se concreta y se habla de definici´n no ambigua. p2 . Un camino de un punto p1 a un punto pn es una secuencia de puntos p1 . cuando hablamos de variables.3. . ANALISIS DE FLUJO Debe existir al menos una forma de iterar. a a a Para ello se usan ecuaciones. o bien pi es el final de un bloque y pi+1 es el comienzo del siguiente. An´lisis de Flujo a El an´lisis de flujo consiste en recopilar informaci´n de variables.3.3. .. tambi´n podemos hablar de expresiones a e e incluso punteros y llamadas a funciones. d´nde se modifican. o o Llamamos alcance de una definici´n d a un punto p si existe un camino desde el o siguiente punto a d hasta p sin que la definici´n se desactive. 63 7. Definiciones de Alcance Llamamos definici´n de una variable x a una proposici´n que asigna un valor a x o o ´ que puede asignarlo. Sin embargo. hay al menos un camino hacia el encabezamiento. se establecen puntos entre sentencias y tambi´n a o e entre cada par de bloques. gen. . . . a o por ejemplo d´nde se definen. Para localizar lazos el m´todo es buscar aristas cuyas cabezas dominen a e las colas. o a En el an´lisis de bloques de c´digo. nos ce˜iremos a las primeras por n simplicidad. a trav´s del o o o e ´rbol de an´lisis sint´ctico. etc. ent y desact. expresiones. y la ecuaci´n base es: o sal[S] = gen[S] ∪ (ent[S] − desact[S]) donde es un bloque de c´digo o representa las variables que salen activas tras la ejecuci´n de S o gen[S] las variables que toman valor en S ent[S] las variables que llegan activas a S desact[S] las variables que son redefinidas en S Claro est´ que..

Bloque unico ´ Para el caso m´s sencillo.64 ´ ´ CAP´ ITULO 7. tenemos que: a ´ o Punto entrada S d: a:=b+c Punto salida gen[S] = {d} desact[S] = Da − {d} sal[S] = gen[S] ∪ (ent[S] − desact[S]) donde Da representa todas las definiciones de la variable a del programa. OPTIMIZACION DE CODIGO Veremos a continuaci´n los valores que pueden tomar en un bloque de c´digo los o o conjuntos sal. ent y desact. gen. el de un bloque unico de c´digo. Secuencia Dada una secuencia de bloques de instrucciones: S1 S S2 gen[S] desact[S] ent[S1 ] ent[S2 ] sal[S] = = = = = gen[S2 ] ∪ (gen[S1 ] − desact[S2 ]) desact[S2 ] ∪ (desact[S1 ] − gen[S2 ]) ent[S] sal[S1 ] sal[S2 ] .

el an´lisis de bucles o lazos. ANALISIS DE FLUJO Bifurcaci´n o 65 El an´lisis de sentencias de control tipo if y algunos saltos es dependiente del tipo de a an´lisis que se est´ realizando.´ 7.3. Nosotros consideraremos que ambas ramas se activan. no encierra ning´n secreto: ´ a u S S1 gen[S] desact[S] ent[S1 ] sal[S] = = = = gen[S1 ] desact[S1 ] ent[S] ∪ sal[S1 ] = ent[S] ∪ gen[S1 ] sal[S1 ] . a e S S1 S2 gen[S] desact[S] ent[S1 ] ent[S2 ] sal[S] = = = = = gen[S1 ] ∪ gen[S2 ] desact[S1 ] ∩ desact[S2 ] ent[S] ent[S] sal[S1 ] ∪ sal[S2 ] Bucle Por ultimo.

En el bloque Si . Procederemos por inducci´n: o Iteraci´n 1 o 0 E1 = E 0 X1 = G1 ∪ (E − D1 ) Iteraci´n 2 o 1 0 E1 = E ∪ X1 = E ∪ [G1 ∪ (E − D1 )] = E ∪ G1 1 1 X1 = G1 ∪ (E1 − D1 ) = G1 ∪ [(E ∪ G1 ) − D1 ] = G1 ∪ (E − D1 ) (y as´ sucesivamente. mientras que un posterior recorrido en profundidad hacia abajo teniendo en cuenta atributos heredados (del padre y/o hermanos) permite obtener ent y sal. an ) con n =n´mero de definiciones del programa. E1 = E ∪ X1 X1 = G1 ∪ (E1 − D1 ) donde E. Notaci´n Vectorial o El an´lisis de flujo de datos.3. su recorrido hacia arriba arrastrando atributos sintetizados a a permite obtener gen y desact. que es lo que pretend´ ıamos) Dado un ´rbol sint´ctico. por comodidad.2. OPTIMIZACION DE CODIGO ent[S1 ] = ent[S] ∪ sal[S1 ] sal[S1 ] = gen[S1 ] ∪ (ent[S1 ] − desact[S1 ]) que escribiremos. de modo que simplemente recordemos que. la componente ai = 1 u indica que se ha generado o desactivado (seg´n el vector que se considere) la definici´n i.66 ´ Demostracion. . 7. u o Las ecuaciones que se aplican no var´ ıan.Partimos de ´ ´ CAP´ ITULO 7. como ya hemos mencionado. . entre vectores binarios: A − B = VA ∧ ¬VB A ∪ B = VA ∨ VB A ∩ B = VA ∧ VB . G1 y D1 son “constantes”. no necesitamos seguir porque ya hemos obtenido ı E = E ∪ G1 . suele acometerse por bloques a preferentemente a por instrucciones. Se definen entonces vectores que representan lo que se genera/desactiva: V = (a1 a2 .

´ 7. ANALISIS DE FLUJO 67 7. y de que: P ∈ predecesores ent[B] = predecesores sal[P ] sal[B] = gen[B] ∪ (ent[B] − desact[B]) y bajo estas condiciones el algoritmo es: Entrada: gen[B] y desact[B] para cada B Salida : ent[B] y sal[B] para cada B ent[Bi] := O. o Decimos que un bloque B genera una expresi´n x + y si eval´a x + y y no genera una o u redefinici´n de x ´ de y. sino cualquier operaci´n en general. o Partimos de que se ha calculado genera y desactiva de cada bloque para todos los bloques del programa. para cada Bi hacemos ent[Bi] := Up sal[P]. /* P predecesores */ salant := sal[Bi]. fin-para fin-mientras fin-para 7. para cada Bi hacemos sal[Bi] := gen[Bi].3. o o 2 El signo “+” no significa aqu´ la operaci´n de suma. o a no necesariamente sin lazos. mientras (cambio) hacemos cambio := false.3. ı o o .3. Soluci´n Iterativa para las ecuaciones de Flujo de Datos o Definiciones de alcance (alcance de definiciones) Definimos un bloque como una proposici´n de asignaci´n o una cascada de proposio o ciones de asignaci´n. ´ o o Decimos que un bloque B desactiva una expresi´n x + y si asigna un valor a x o a y.3.desact[Bi]).4. desde el nodo inicial hasta P eval´a x + y y despu´s de la u e ultima evaluaci´n antes de P no hay asignaci´n ni de x ni de y. cambio := true. si (sal[Bi] <> salant) entonces cambio := true. An´lisis de Expresiones Disponibles a Decimos que una expresi´n x + y 2 est´ disponible en un punto P si todo camino. sal[Bi] := gen[Bi] U (ent[Bi] .

68 Expresaremos: e gen[Bi ] = e desact[Bi ] = U ∅ Y usaremos las ecuaciones: ´ ´ CAP´ ITULO 7.desact[Bi]. sal[Bi] := e_gen[Bi]. El algoritmo es: Entrada: e_gen[Bi] y e_desact[Bi] para todo Bi Salida : ent[Bi] y sal[Bi] para todo Bi ent[Bi] := O.3. mientras (cambio) hacemos cambio := false. para todo Bi<>B1 hacemos sal[Bi] := U . si no se vuelve a usar. ıa a o e . Este an´lisis pretende liberar memoria. de modo que estar activo significa que se puede a (y de hecho. de abajo hacia arriba. el an´lisis anterior daba todo el alcance posible. se hace) usar el valor. An´lisis de Variables Activas a Una variable a es activa en un punto P si se puede utilizar el valor de a en alg´n u camino que comience en P .5. cambio := true. para cada Bi<>B1 hacemos ent[Bi] := ^p sal[P]. fin-para fin-mientras 7. salant := sal[Bi]. Esta a filosof´ obliga a hacer el an´lisis en el c´digo al rev´s. OPTIMIZACION DE CODIGO expresi´n que genera el bloque Bi o expresi´n que desactiva el bloque Bi o = universal = vac´ ıo sal[Bi ] = e gen[Bi ] ∪ (ent[Bi ] − e desact[Bi ]) ent[Bi ] = Bi = Binicial p sal[Pi ] ent[Bi ] = ∅ Bi = Binicial Como se puede observar. como antes. sin embargo a ahora queremos ser muy conservadores para poder usar el valor de la expresi´n (en lugar o de etiquetar las asignaciones. ahora se etiquetan las expresiones). si (salant <> sal[Bi]) entonces cambio := true.e_desact[Bi]). entonces no se est´ activo. sal[Bi] := e_gen[Bi] U (ent[Bi] .

Por ultimo. Llamamos salida al conjunto de variables activas a la salida de un bloque. uso[Bi] para todo Bi Salida : sal[Bi] para todo Bi para todo Bi hacemos sal[Bi] == O. para todo Bi hacemos ent[Bi] := uso[Bi]. Llamamos definidas al conjunto de variables a las que se les asigna un valor en el bloque.´ 7.3. /* S sucesores */ ent[Bi] := uso[Bi] U (sal[Bi] . fin-para fin-mientras . se llama ´ uso al conjunto de variables cuyos valores se utilizan antes de cualquier definici´n de la o variable. ANALISIS DE FLUJO 69 Llamamos entrada al conjunto de variables activas al comienzo de un bloque. Las ecuaciones usadas en este tipo de an´lisis son: a ent[Bi ] = uso[Bi ] ∪ (sal[Bi ] − def [Bi ]) Si ∈ sucesores sal[Bi ] = s ent[Si ] El algoritmo es el siguiente: Entrada: grafo de flujo G y def[Bi]. mientras ocurren cambios en los conjuntos ent[Bi] hacemos para cada Bi hacemos sal[Bi] := Us ent[S].def[Bi]).

OPTIMIZACION DE CODIGO .70 ´ ´ CAP´ ITULO 7.

otros no m´s de 30 procedimientos. se deben a descuidos del programados (situaciones como aco cesos a matrices fuera de rango. en compiladores puede ser interesante para o nosotros intentar subsanar errores lexicogr´ficos. cuando falta un par´ntesis). Errores sint´cticos. ser´n susceptibles de ser realizadas u a diferentes medidas de correci´n. o a 71 . e Errores sem´nticos. Tipos de errores Consideraremos la exitencia de varios tipos de errores: Errores l´xicos.. . a a Errores de ejecuci´n. como la inclusi´n de elementos extra˜os entre elementos o o n correctos. ). son aqu´llos en los que donde se esperaba una palabra reservada del e e lenguaje aparece otra (por ejemplo. . Recuperaci´n de errores o Seg´n el tipo de error ante el que nos encontremos.2. Errores de compilaci´n. . a 8. o u Afrontaremos. poner far en lugar de for). o la desaparici´n de alg´n elemento. .Cap´ ıtulo 8 Errores En este breve tema comentaremos algunas generalidades acerca de los errores en el ´mbito que nos ocupa. 8. aparecen cuando llevamos a cabo acciones inadecuadas sobre a elementos incorrectos (por ejemplo.1. . aparecen por limitaciones propias del compilador (algunos o no permiten m´s de 10 bucles anidados. tanto aqu´llos que suponen la sustitua e ci´n de unos elementos por otros. ). la correcci´n de errores lexicogr´ficos desde estas perspectivas. a ficheros no abiertos. hacer la ra´ cuadrada de una variable de tipo ız string). son aqu´llos que provocan que no se encuentre un ´rbol sint´ctia e a a co que analice el programa (por ejemplo. En particular. pues.

T. dado por o o EDT (N. C n (x) = {y/y ∈ T ∗ ∧ y resultado de n cambios en x} Adem´s. se define el operador de borrado: B(a) = λ ´ ε o de tal forma que B n (x) = {ε si |x| < n} = {y/y ∈ T ∗ ∧ y resultado de eliminar n caracteres en x} El error de borrado es muy f´cil de detectar en lenguajes donde se definan todas las a palabras de la misma longitud. αi .1. o u . Correcci´n de errores de cambio o Supone admitir palabras del lenguaje con uno o m´s errores. ERRORES 8. P . Ts . Se define el operador a de cambio1 : C(a) = T − {a} de tal modo que C 1 (x) = {y/y ∈ T ∗ ∧ y resultado de 1 cambio en x} C 2 (x) = {y/y ∈ T ∗ ∧ y resultado de 2 cambios en x} .2.2. 1 ∀a ∈ T Que s´lo act´a sobre elementos terminales. a De modo que para corregir errores. αi (no existen errores) (con µ = C 1 (αi )) (con β = C 2 (αi )) (con δ = C n (αi )) 8. si |x| < n..72 CAP´ ITULO 8. n ≥ 0} La correcci´n de errores se implementa mediante un esquema de traducci´n. Correcci´n de errores de borrado o Del mismo modo. es decir. entonces C n (x) = ∅. para admitir palabras con alg´n error u durante el proceso de compilaci´n. P. αi . S) en la que las reglas ser´n a a P = P ∪ {reglas de las operaciones de cambio} de tal forma que el “nuevo lenguaje” aceptado puede expresarse como L(G ) = {y/y ∈ T ∗ ∧ y ∈ C n (x) ∧ x ∈ L(G). Te . A → δ . por convenio.. S). P. S).2. crearemos o a una gram´tica G = (N.. si tenemos una gram´tica G = (N. T. definido seg´n la estructura: u A → αi A → µ A → β .. αi .

Modo p´nico a Algunos compiladores. Este modo de comportarse es lo o que se conoce como modo p´nico. cuando encuentran un error. buscan el principio y final de “secci´n” o “bloque” entre los que se encuentra el o error. lo ignoran.2. entonces I(a) = {aa1 + aa2 + .3. y siguen analizando el resto del c´digo. . a2 . . . Correcci´n de errores de inclusi´n o o El operador de inclusi´n se define: o I(a) = xa + ax ∀a ∈ T ∀x ∈ T de tal forma que si T = {a1 . MODO PANICO 73 8. . an }.3. detienen el an´lisis. Otros. . en a cambio. . . . a .´ 8.3. an a} 8. + aan + a1 a + a2 a + .

ERRORES .74 CAP´ ITULO 8.

1. otra para procedimientos.. o ´mbito.2. y suelen ser de car´cter est´tico. por ejemplo. Independientemente del modo de almacenamiento.. reestructurando la TDS en o caso necesario. por tanto. tal como su nombre a a indica y se puede observar en la figura 9. TDS ´rbol binario a La TDS ´rbol binario guarda una estructura en forma de ´rbol.1. pues a a su implementaci´n no es compleja y tanto inserci´n como b´squeda tienen la misma o o u complejidad. TDS ordenada Se determina un ordenamiento.1. par´metros de entrada y salida. u o a a 9.3. car´cter de los a a a par´metros de entrada —por valor o por referencia—. . . tipo. y la b´squeda suele ser dicot´mica.1. ) y procedimientos (nombre. el orden alfab´tido de identificadores. o 9.1.1 (p´gina 76). .Cap´ ıtulo 9 La Tabla de S´ ımbolos Ya hemos hablado en alguna ocasi´n de las tablas de s´ o ımbolos. r´pida y f´cil de implementar. a La mayor´ de los compiladores mantiene una TDS por tipo de objeto (una para ıa variables. o u linealmente. ). 9. . la inserci´n se realiza en el lugar adecuado. es uno de los tipos m´s utilizados. u 9. Pese a que se desperdicia un a poco m´s de espacio adicional en los punteros. . ). e Una vez definido. Tipos TDS lineal Consiste en ir almacenando la informaci´n sobre los objetos seg´n se va obteniendo.. Su utilidad es a a patente al principio del proceso de compilaci´n. . Veremos a continuaci´n una serie de formas de implementar las TDS. pues en el paso a c´digo objeto ya dejan o o de ser necesarias. de manera secuencial. la tabla de s´ ımbolos o TDS es una estructura utilizada por los compiladores para almacenar informaci´n sobre variables (nombre. 75 . La b´squeda se realiza.

. cn . donde empieza en memoria la TDS o o es el valor num´rico asignado a ci e es el tama˜o de la TDS n Para otro tipo de claves (identificadores) no s´lo compuestos por caracteres (como por o ejemplo i2). En la mayor´ de las ıa ocasiones se mantienen punteros de enlace por comodidad y rapidez. si el valor que se pretende encontrar no se halla en la posici´n que le corresu o ponde. LA TABLA DE S´ IMBOLOS AB AA BC BA BD Figura 9. . C = c1 c2 .1. realizando la exploraci´n linealmente a partir del lugar original. .76 CAP´ ITULO 9.1: TDS en forma de ´rbol binario. la funci´n de hash t´ o ıpica es: Hashing(C) = (α0 + i=0 αi ci ) modulo T donde α0 αi T es la direcci´n o posici´n inicial. En o o b´squeda. podr´ adoptarse: ıa Hashing(C) = (ord(id[i] ∗ 10) + ord(id[2])) modulo T Hashing abierto Con la mayor´ de las funciones de hash existe la posibilidad de colisiones. a 9. TDS con hashing n Dado un identificador C con n caracteres.4. se sigue buscando secuencialmente a partir de la misma. La t´cnica ıa e de hashing abierto establece que en caso de conflicto el valor se introduce en la siguiente posici´n libre.

y si no es as´ seguir el puntero a la tabla del bloque que contiene ı. excepto cuando se hace otra definici´n de variable con el o o mismo bloque (en dicho bloque interior). . donde se almacenan linealmente enlazados. o 9. al bloque actual y buscar all´ Se procede recursivamente hasta que se encuentra o se llega ı.1. hab´ ıamos comentado que puede incluirse el nombre. y tambi´n el alcance (bloques del proe grama en los que la variable est´ activa). La estrategia e ıa de b´squeda consiste en comprobar si el identificador est´ en la tabla del bloque en que se u a encuentra la referencia. . e Un identificador declarado en un bloque puede ser udaso dentro de los bloques interiores a la definici´n. al bloque principal.. El m´todo de las TDS enlazadas evita la inclusi´n a e o de este dato en la TDS definiendo una tabla por bloque del programa y relacion´ndolas a entre s´ ı. podemos definir un identificador (variable) en relaci´n a su amu e o plitud : Un identificador se declara al principio de un bloque1 y se puede usar dentro de ´l.1.9. tipo. Este es el m´todo que se usa en la mayor´ de los compiladores actuales. En este caso. Hashing con encadenamiento El hashing con encadenamiento perfeciona la t´cnica del hashing con overflow y estae blece que la primera TDS contenga s´lo punteros la TDS de segundo nivel. 1 En algunos lenguajes esto no es necesario que se cumpla estrictamente. TIPOS Hashing con overflow 77 El hashing con overflow es otra variante que pretende solucionar el problema de las colisiones. .5. Por lo que respecta a las variables. TDS enlazadas Como hemos mencionado al principio. Seg´n este m´todo. los valores conflictivos van a parar a una segunda tabla. en la tabla de s´ ımbolos suelen almacenarse datos relativos a variables y procedimientos.

78 CAP´ ITULO 9. LA TABLA DE S´ IMBOLOS .

. lo que es lo mismo. En el caso de las matrices (arrays bidimensionales) M [b1 . volveremos ahora a hablar con un poco m´s de detalle de la representaci´n de las estructuras de informaci´n. a2 ].1.1. a o o 10.Cap´ ıtulo 10 Representaci´n de la Informaci´n o o y Gesti´n de Memoria o 10. k es el n´mero de bytes por elemento y C es el n´mero o u u de elementos por fila o. pero requiere o a bastantes menos c´lculos para acceder: a 79 .1. . b2 . tenemos dos funciones de acceso seg´n su almacenamiento: u Almacenamiento por filas: Dir(Mij ) = M + k · [(i − b1 ) × C + (j − b2 )] donde M es la direcci´n base. . pues no es m´s que una colecci´n de n objetos o a o iguales que se ubican contiguos en memoria. Esta representaci´n ocupa un poco m´s de espacio (el vector de punteros). a1 . el n´mero de filas. k es el n´mero de bytes por elemento y F es el n´mero o u u de elementos por columna o. . lo que es lo mismo. el n´mero de columnas. u Almacenamiento por columnas: Dir(Mij ) = M + k · [(i − b2 ) × F + (i − b1 )] donde M es la direcci´n base. Representaci´n de arrays y matrices o La representaci´n de un array es simple. Representaci´n de la Informaci´n o o Aunque ya hemos dado pinceladas al respecto en temas anteriores. u Representaci´n con vectores enlazados o Otra forma de representar matrices es mediante vectores: se tiene un vector de punteros (uno por fila) que apuntan a su vez a los vectores-fila que forman el array bidimensional.

. ∗ en . simplemente hay que hacer sumas y restas.80 ´ ´ CAP´ ITULO 10. . Representaci´n de matrices de n dimensiones o Dada una matriz: M [i1 .. . ∗ en (j2 − i2 ) ∗ e3 ∗ . . . s2 . .. = s1 − i1 + 1 s2 − i2 + 1 sn − in + 1 entonces para acceder a M [j1 . . . veremos por ultimo un m´todo que consiste ´ e en almacenar un vector de informaci´n con la siguiente forma: o Numero de dimensiones Termino constante Direccion de comienzo i1 i2 in s1 s2 . . . obviamente ii ≤ si . s1 . jn ] debemos hacer M + + + + + (j1 − i1 ) ∗ e2 ∗ e3 ∗ . Si llamamos e1 e2 en = = . REP. . . in . j2 .. i2 . sn ] donde ii = l´ ımites inferiores si = l´ ımites superiores n = n´mero de dimensiones u y. . . .. (jn−1 + in−1 ) ∗ en (jn + in ) + + + + Vector “Dope” o Vector de Informaci´n o Para representar este tipo de estructura. . . DE INFORMACION Y GESTION DE MEMORIA Dir(Mij ) = (vector + i − 1) + j − 1 donde (vector + i − 1) es el valor del puntero correspondiente (la direcci´n). . sn e1 e2 en .. Como se o puede ver. .

En la TDS se guarda informaci´n acerca del n´mero y tipo de sus campos. Representaci´n de cadenas y tiras de caracteres o Las cadenas suelen almacenarse contiguas en memoria. a 10. . Representaci´n de registros o Los registros (tambi´n conocidos como records) suelen almacenarse contiguos en mee moria.´ 10. del control del o tama˜o y situaci´n de los objetos en la memoria. etc.1. de o u modo que el acceso a un determinado dato siempre es f´cilmente calculable. a fin de que no conlleve m´s c´lculos el acceso que la propia operaci´n a a o que se pretend´ realizar sobre ellas. Claro que esto puede derivar en una situaci´n donde la a o proliferaci´n de cadenas segmentadas y punteros sea demasiado costosa. concatenaci´n).2. Gesti´n de memoria o proporcionada por el compilador Los compiladores suelen proporcinar una serie de rutinas que son incorporadas al c´digo del usuario y que se encargan de gestionar la detecci´n de errores de ejecuci´n (por o o o ejemplo. 10. esta estructura permite la implementaci´n ıa a o del dinamismo con arrays bidimensionales de manera sencilla. determinando un car´cter que a se˜ala el fin de las mismas. alguo nos compiladores incluyen rutinas de reagrupamiento que se disparan autom´ticamente.2. a 10. IRQ Codigo Datos estaticos Pila Monticulo (a) M. principal. (b) M. divisiones por cero).3. ya que las ubicaciones de las cadenas o originales en memoria pueden ser distantes y crear una nueva cadena en cada operaci´n o supone demasiado moviento de datos y reserva de espacio en el data block. proceso. Lo que se suele hacer es asociar las cadenas mediante punteros.1. evitando de esta manera el mencionado tr´fico de operacones en memoria. Zona programas Dispositivos Pantalla Cod. GESTION DE MEMORIA PROPORCIONADA POR EL COMPILADOR 81 La utilidad de esta estrategia reside en la recopilaci´n de la m´xima informaci´n posible o a o sobre las matrices. de la gesti´n de variables locales y globales. n o S. en ese caso. Los mayores problemas los presentan las operaciones de man nejo de tiras de caracteres (copia. Adem´s.2.O.

REP.. Los est´ticos permiten buscar variables a las que tiene acceso o a a a . DE INFORMACION Y GESTION DE MEMORIA Las variables locales de los procedimientos se colocan en la pila.82 ´ ´ CAP´ ITULO 10. Del mismo modo. En este ´rbol. . asignar los valores a las variables locales y comenzar la ejecuci´n del a o procedimiento. mientras que la gran o mayor´ tiene asignaci´n din´mica. ) Puntero al registro de activaci´n anterior o llama a A B A llamador B llamado B A pila Un procedimiento es recursivo si se puede activar antes de la finalizaci´n de la actio vaci´n anterior. ıa o a 10. que recibe el nombre o a de ´rbol de activaci´n. se dice que un nodo A es padre de un nodo B si a o a el control fluye de A hacia B. o Algunos lenguajes s´lo tienen gesti´n est´tica de memoria (por ejemplo. de forma que mecanismos como la recursi´n puedan funcionar adecuadamente. flags.2. o Existen dos tipos de punteros implementados en la estructura de registros de activaci´n: est´ticos y din´micos. De aqu´ surge el concepto de o ı registro de activaci´n. que veremos.1. .2. o Los registros de activaci´n se pueden organizar en forma de ´rbol.2. en F66 nada o o a puede crecer en tiempo de ejecuci´n y no existe la recursividad). la secuencia de retorno recupera los datos del campo estado del registro de activaci´n para restaurar la situaci´n anterior y borra el mencionado registro o o para continuar la ejecuci´n. Registro de activaci´n o Los registros de activaci´n son la unidad estructural de la pila y almacenan: o Datos locales del procedimiento Par´metros que se le pasan a Datos temporales introducidos por el compilador Datos sobre el estado de la m´quina antes de la ejecuci´n del procedimiento (estado a o de la CPU: registros. Por su parte. 10. se dice que un nodo A est´ a la izquierda a de un nodo B si se ejecuta A antes que B. Secuencia de llamada y retorno La secuencia de llamada consiste en guardar en el registro de activaci´n el estado o de la m´quina.

volc´ndose su valor en el verdadero a al final del procedimiento. GESTION DE MEMORIA PROPORCIONADA POR EL COMPILADOR 83 valor devuelto y parametros enlace de control estado datos temporales y locales procedimiento llamado procedimiento llamador el procedimiento pero que no son locales y los din´micos son referencias al procedimiento a llamador (son los que realmente permiten implementar la pila).2. a . en f se trabaja con una copia de a. Las variables globales del programa se ubican en la parte de datos est´ticos del proceso.2. o o S´lo escritura: al llamar a f (a). en f se trabaja con una copia de a cuyo valor inicial o no est´ determinado (puede ser un valor por defecto) y al finalizar se copia su valor a al verdadero a. en f se lee de a y se escribe en una copia de a. variables o identificadores que solamente aparea a cen en el subprograma que es llamado. a de forma que se ahorra el tener que colocarlos repetidamente en los registros de activaci´n o y se consigue que est´n accesibles para todos los subprocesos. por tanto. variables o expresiones que aparecen en el proa cedimiento llamador. u a o Lectura y escritura • Por valor o resultado: al llamar a f (a). Adem´s. que act´a. Argumentos o Par´metros efectivos. la llamada puede clasificarse: a S´lo lectura: al llamar a una funci´n f (a). como un par´metro de devoluci´n.´ 10.3. Subprogramas Los argumentos con que se llama a un subprograma pueden ser: Par´metros o Par´metros ficticios. e 10.

por ejemplo). E. existen partes reubicables y partes no reubicables (como o el c´digo de las interrupciones. ). y los compiladores o lenguajes que la utilizan (como FORTRAN) emplean en realidad una variante en la que. Durante el proceso. tras establecer punteros con valor adecuado (puntero de inicio de programa. 10. o • Por nombre: el procedimiento al que se llama no recibe una direcci´n o un o contenido. En los programas. B+100 D-40 C+30 F Cada bloque tiene un l´der. tanto para o lectura como para escritura (se tiene la direcci´n).84 ´ ´ CAP´ ITULO 10. que se utiliza como ra´ para construir el ´rbol de equivaı ız a lencia. . Estructuras COMMON y EQUIVALENCE en FORTRAN En FORTRAN se pueden establecer relaciones de equivalencia entre variables con respecto a la posici´n f´ o ısica que ocupan en un bloque com´n (bloque que puede crecer u din´micamente).2. . etc. 10. Montadores y Cargadores Los montadores (linker ) resuelven las referencias externas que existen en los objetos a montar.3. le dar´ el valor u a correspondiente. a el l´ ıder est´ unido mediante enlaces directos a la hoja m´s a la izquierda y a la hoja m´s a a a a la derecha. A. C. REP. resolviendo el problema de la reubicaci´n. D 0 B −110 C −40 A 100 Esta estructura viene del ensamblador. . valores de los registros de la CPU.4. flags. se detectan errores (“Unresolved external”) y si no aparecen enlazan todos los objetos en un unico objeto ´ entendible por el cargador. el cargador da o el control al programa. Tras cargarlo en memoria. sino un “literal”. de forma que. que son respectivamente los extremos inferior y superior del bloque COMMON. Esto se hace con sentencias del tipo: a EQUIVALENCE EQUIVALENCE EQUIVALENCE EQUIVALENCE A. para lo que utilizan una tabla. seg´n su contexto. en el ´rbol de equivalencia. en f se trabaja directamente con a. Los cargadores (loader ) cargan en memoria un objeto. DE INFORMACION Y GESTION DE MEMORIA • Por direcci´n: al llamar a f (a).

. Ficheros objeto Contienen una serie de registros de la forma: <cabecera><texto><checksum> donde la cabecera contiene.4. a Otros Como registros de principio de bloque. Actualmente.5. o a . fue decayendo posteriormente o ıa. De referencias externas Contienen: <cabecera><datos_externos><checksum> donde <datos_externos> = <direccion><nombre_bloque_externo> De texto con iteraci´n Se usan para rellenar zonas de memoria con un o dato: <cabecera><bloque_iteracion><checksum> donde <bloque_iteracion> = <direccion><contador><contenido> donde se repetir´ contenido contador veces. frente a la de los compiladores. 10. desde la o aparici´n de VBASIC y sobre todo de java. casi por completo su utilizaci´n. . a su vez. final de bloque. o Entre los tipos de registros que puede contener un fichero objeto podemos encontrar: De definici´n de bloques Contienen: o <cabecera><datos_bloque><checksum> donde <cabecera> = <longitud><tipo_definicion_bloque> <datos_bloque> = <longitud><nombre_bloque><tipo_bloque> donde el tipo del bloque se refiere a si es reubicable o no.10.4. . por ejemplo. est´n volviendo a resurgir. FICHEROS OBJETO 85 10. Int´rpretes e Fueron muy usados en un principio debido a que los equipos ten´ poca memoria y era ıan preferible tener cargado siempre el int´rprete y el c´digo fuente a tener un compilador y el e o c´digo objeto. <longitud><tipo> y donde el checksum representa la comprobaci´n de paridad para el control de errores. con el avance de la tecnolog´ no obstante.

B := 8.1 . a Modernos Son int´rpretes que realmente generan un c´digo intermedio sin e o errores.. X GOTO . REP. DE INFORMACION Y GESTION DE MEMORIA Distinguimos dos tipos de int´rpretes: e Cl´sicos Son int´rpretes que van ejecutando el c´digo fuente l´ a e o ınea a l´ ınea tal y como est´ tecleado. /* INTERPRETE */ case v[pos] of ident. datos entrada Programa fuente Analizador lexico Analizador sintactico RPN Interprete TDS Etapa analisis Ejecucion/interpretacion datos salida Figura 10. B WRITE .. que es el que es interpretado l´ ınea a l´ ınea..1: Estructura y funcionamiento de un int´rprete moderno.. B 8 := . B B A + := . GOTO X.1 e introducir el resto en la pila representar en pantalla rep evaluar elemento PCP y ponerlo en direccion PCP .86 ´ ´ CAP´ ITULO 10. p:=p+1.. /* CODIGO RPN */ A 9 := . B := B+A. e Un ejemplo: /* CODIGO FUENTE */ A := 9. entero : ’+’ : ‘‘write’’ : ‘‘:=’’ : end apilar(v[op]). WRITE B. sumar PCP + PCP .

27 o sint´ctico. 29 m´todo del ´rbol. 30 e a m´todo derivativo. 16 objetivo. 17 o axioma. 14 s´ ımbolos in´tiles. 29 sem´ntico. 46 sintetizados. 42 acciones sem´nticas. eliminaci´n o recursividad por la izquierda. 19 o cuartetos. 17 configuraci´n. 10 o representaci´n gr´fica.´ Indice alfab´tico e ´rbol a de derivaci´n. 18 algoritmo de Thompson. 63 derivaci´n. 51 optimizaci´n. 42 lookahead. 10 c´digo o a 3 direcciones. 14 reglas unitarias. 11 a core. 16 inicial. 16 lenguaje generado. 31 detecci´n lenguaje vac´ 13 o ıo. 32 LR(1). 43 o intermedio. 17 de salida. 31 simple. 46 aut´mata o con pila. 59 o cierre reflexivo. 27 a LL(1). 17 o a transici´n. 16 determinista. 32 LL(K). 11 o a errores recuperaci´n. 51 objeto. 21 e atributos 87 heredados. 43 a sint´ctico. 53 definiciones de alcance. 16 o final. 30 e m´todo matricial. 30 e operador. 15 reglas lambda. 35 an´lisis de flujo. 16 no determinista. 54 generaci´n. 71 o tipos. 36 LR(K). 9 conjunto de traducci´n. 16 de pila. 18 representaci´n gr´fica. 13 u an´lisis a por precedencia. 59 o en c´digo fuente. 71 . 63 a analizador l´xico. 23 de Warshall. 17 reconocedor por agotamiento de pila. 9 de entrada. 9 transitivo. 44 a alfabeto. 16 finito.

43. 52 s´ ımbolo accesible. 11 de contexto libre. 49 o equivalencia. 15 formas sentenciales. 30 de equivalencia. 20 o forma normal. 30 universal. 11 metanoci´n. 10 scanner. 9 traducci´n o dirigida por la sintaxis. 9 longitud. 49 sobrecarga. 18 transitividad. 75 tercetos. 28 producciones. 16 inicial. 16 o o gram´tica. 30 reglas cadena. 21 simetr´ 30 ıa. 49 tira de caracteres. 10 a ambigua. 14 o notaci´n o polaca inversa. 30 traspuesta. 20 o lambda. 11 funci´n de transici´n. 23 forma de traducci´n. 48 polimorfismo. 15 de Greibach. 45 a coerci´n. 16 expresion regular propiedades. 20 o estado. 15 por la izquierda. 10 independiente del contexto. 19 finito. 15 autoimbricadas. 10 lenguaje. 23 final. 9 nula.88 esquemas de traducci´n. 10 o de traducci´n. 21 construccion. 30 complementaria. 10 tipos. 10 terminable. 53 indirectos. 30 RPN. 43. 44 traductor con pila. 14 relaci´n o binaria. 9 parsing ascendente. 49 o comprobaci´n. 9 potencia. 45 conversi´n. tabla de s´ ımbolos. 10 sensible al contexto. 13 anulable. 12 de producci´n. 10 limpia. 15 ´ ´ INDICE ALFABETICO sem´nticas. 13 u no terminal. 16 cerradura. 46 a unitarias. 14 in´til. 28 descendente. 10 reflexividad. 54 tipos b´sicos. 12 regular. 15 por la derecha. 15 de Chomsky. 13 terminal. 52 palabra. 43. 43 o constructores. 14 recursivas. 30 variantes .

36. 38 89 . 42 LR can´nico. 36. 40 o SLR. 36.´ ´ INDICE ALFABETICO LR(1) LALR.

90 ´ ´ INDICE ALFABETICO .

. . . . . . .1. . . . Maneras de construir un scanner. . . . . . . . . . . . 2. . . . . . . . . 2. . . .1. . . . . . . .2.3. 62 o 9. . . . . . . . . . . o Representaciones de un aut´mata.3. . . . 27 28 33 36 5. Objetivo de un scanner. . . . . . Tipos de parsing. . 22 3. . . . . . .1. . . . . . .´ Indice de figuras 1. . . . . . . . . .1. . . . . . . Grafo de Flujo y Arbol de Dominaci´n. . . . a Relevancia en el orden de los algoritmos de simplificaci´n. . . . . . . . . . . . . . . . . . . . . . . . . . . . Tipos de parsing. . . . . . . . . . . TDS en forma de ´rbol binario. . . . .1. . 44 a a ´ 7. . . . . . . . . . .4. 76 a 10. . . . o . . . . . . . . . . . . . . . . Esquema de an´lisis sem´ntico. . . . . . . . . . . . . . . 21 3. . . . . . . . . a . . . . . . . . . . . .2. . . . . . . . . . . . . . . . . . 2. . . . . . . . .4. . . Esquema de las tareas de un compilador. . . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . Estructura y funcionamiento de un int´rprete moderno. . . . Ejemplo de ´rbol sint´ctico. . Componentes b´sicos del m´todo de Thompson. . 4.2. . .3.1. . . . . . . . . . . . . 2. Modelo de un analizador sint´ctico LR(1). . . . . 86 e 91 . . . o Estructura de un parser LL(1). . . . . 4. . . . . . . . . . . . 7 11 12 14 17 3. . . . . . . . . . . . . . . . . . . . . .1. a a Ejemplo de gram´tica ambigua. . 24 a e 4. . . . . otra clasificaci´n. . . . . . . . . . . . . . . . . . .

92 ´ INDICE DE FIGURAS .

6. . . . . . . . .3. . . . .6. .1. . . . . . 4. . .4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 o 5. . . . . . . . . a Algoritmo de c´lculo de cerradura. . . . . . . . . . . . . o o o Algoritmo de c´lculo de cerradura para LR-can´nico. . . . 6. . . . . . . . . . . . . . . . . . . . . . . . . . 50 o o 6. . .2. . . . . . . a Algoritmo de an´lisis LL(1). Notaci´n Polaca Inversa (RPN). LR-can´nico. . . . Correspondencia gram´ticas-aut´matas. . . . .7. . . a Construcci´n del conjunto de los elementos de an´lisis o a 5. . . . . . . . . . . . .2. . 16 . . o . . . . Algoritmo de comprobaci´n de equivalencia estructural. . . . . . . .3. . . . . . .8. . .1.2. o Modos de direccionamiento . . . . . . . . . . . . . . . . . . . . . o Traducci´n a RPN. Comprobaci´n de tipos para coerci´n de entero a real. . . . . . . 4. . . . a o o Algoritmo de c´lculo de Ir a para LR-can´nico. . . 4. . . . . . . . 4. . . . . . . . . 4. . . . Precedencia usual entre los operadores matem´ticos. . . . . . . . . . . . 52 52 53 55 93 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. . . . . .1. . . .4. . . . . . 31 32 34 39 39 41 41 41 Algoritmo de Warshall. . . . . . . . . o Notaci´n de cuartetos. 6. . . . . . . . . . . . . . . . 46 a 5. . . .3. . . .5. . . . . . . . . . . . . . . . . . . . . . . 4.1. . .´ Indice de cuadros 2. . a Construcci´n de la colecci´n can´nica LR(0). . . . . . . . . . a o 4. . Gram´tica de referencia. .

94 ´ INDICE DE CUADROS .

o 95 . Sanch´ Llorca. ı o Paraninfo S. 1998. a ıs Compiladores. o [4] Aho. Mc-Graw Hill International. 1988. 1a reimpresi´n . Compiladores. e Addison Wesley Longman. 1996.P. Dough. O’Reilly. Series in Software Engineering. Jeffrey D. C. 2a edici´n . Lex & Yacc. 2a edici´n.Bibliograf´ ıa [1] Bennett. t´cnicas y herramientas. J.J. [3] Mason. Teor´a y construcci´n.A. Introduction to Compiling Techniques. John y Brown. Tony y Levine. Principios. o [2] Gal´n Pascual. Alfred V. F.. y Sethi. Ravi y Ullman. Madrid. 1992.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->