Representaciones Intermedias

Anuncio
Representaciones Intermedias
CI4721 – Lenguajes de Programación II
Ernesto Hernández-Novich
<[email protected]>
Universidad “Simón Bolívar”
Copyright ©2012-2016
Hernández-Novich (USB)
Representaciones Intermedias
2016
1 / 32
Generación de Código Intermedio
Acceso a elementos en arreglos
• Haremos las suposiciones modernas de almacenamiento para los
elementos de un arreglo
• Elementos almacenados en posiciones contiguas.
• Disposición por filas (row major).
• La anchura de cada elemento es conocido e incluye el padding sufijo
cuando aplique.
• El acceso a cualquier elemento requiere
• Conocer la base de almacenamiento del arreglo.
• Calcular el desplazamiento hasta la posición deseada.
• Determinar si se quiere el r-value o el l-value según el contexto
gramatical.
. . . con la mínima cantidad de operaciones
Hernández-Novich (USB)
Representaciones Intermedias
2016
2 / 32
Generación de Código Intermedio
Acceso a Arreglos
Caso general de una dimensión
Sea un arreglo A
• Unidimensional.
• Elementos de anchura w .
• Indices en el rango low y high.
• Dispuesto a partir de la dirección base.
Entonces el i−ésimo elemento está en la dirección
high
i
low
···
Ai
···
w
base
Hernández-Novich (USB)
base + (i − low ) × w
Representaciones Intermedias
2016
3 / 32
Generación de Código Intermedio
Acceso a Arreglos
Cálculo más eficiente
Como base, low y w son conocidas a tiempo de compilación, podemos
expandir y reordenar la fórmula para obtener
i × w + (base − low × w )
• ¡La expresión c = base − low × w es constante!
• Se evalúa una vez a tiempo de compilación al procesar la declaración.
• Se almacena como atributo para el arreglo en la tabla de símbolos.
• Para calcular la dirección de A[i] solamente es necesario generar
código para la expresión i × w + c.
Hernández-Novich (USB)
Representaciones Intermedias
2016
4 / 32
Generación de Código Intermedio
Acceso a Arreglos
Agreguemos una dimensión
Si A tiene dos dimensiones y está dispuesto en row major . . .
• A[i, j] es equivalente a A[i][j] – arreglo de arreglos.
• A[i1 , i2 ] – “desplazarse i1 filas y agregar i2 elementos”.
Así que podemos deducir la fórmula
base + ((i1 − low1 ) × n2 + i2 − low2 ) × w
donde n2 es la cardinalidad de i2 .
Como base, low1 , low2 y w son conocidas a tiempo de compilación,
nuevamente reescribimos
((i1 × n2 ) × i2 ) × w + (base − ((low1 × n2 ) + low2 ) × w )
Hernández-Novich (USB)
Representaciones Intermedias
2016
5 / 32
Generación de Código Intermedio
Acceso a Arreglos
El caso general
Si A es un arreglo k−dimensional con la j−ésima dimensión variando entre
lowj y highj , la posición
A[i1 , i2 , . . . , ik ]
tiene dirección
((· · · ((i1 × n2 + i2 ) × n3 + i3 ) · · · )nk + ik ) × w
+base − (· · · ((low1 × n2 + low2 ) × n3 + low3 ) · · · )nk + lowk ) × w
• ∀j : nj = highj − lowj + 1 – el segundo sumando puede calcularse a
tiempo de compilación.
• Si las dimensiones tienen base cero, se reduce a base.
Hernández-Novich (USB)
Representaciones Intermedias
2016
6 / 32
Generación de Código Intermedio
Acceso a Arreglos
Esquema directo con base cero – El uso de los arreglos
S → L := E
E→ L
• L genera el nombre del arreglo y la secuencia de expresiones índice.
• Asignaciones y expresiones extendidas permitiendo acceso a arreglos.
Hernández-Novich (USB)
Representaciones Intermedias
2016
7 / 32
Generación de Código Intermedio
Acceso a Arreglos
Esquema directo con base cero – El uso de los arreglos
S → L := E
E→ L
{gen(L.array
.base 0 [0 L.addr 0 ]0 0 :=0 E .addr )})
(
E .addr ← newtemp();
gen(E .addr 0 :=0 L.array .base 0 [0 L.addr 0 ]0 )
• L genera el nombre del arreglo y la secuencia de expresiones índice.
• Asignaciones y expresiones extendidas permitiendo acceso a arreglos.
• El acceso a cualquier posición de un arreglo sólo depende de tener la
base y el offset calculados previamente.
• L.array .base debe contener la base del arreglo.
• L.addr debe contener el offset.
Hernández-Novich (USB)
Representaciones Intermedias
2016
7 / 32
Generación de Código Intermedio
Acceso a Arreglos
Esquema directo con base cero – Los cálculos
L→ id [ E ]
L→ L1 [ E ]
Hernández-Novich (USB)
Representaciones Intermedias
2016
8 / 32
Generación de Código Intermedio
Acceso a Arreglos
Esquema directo con base cero – Los cálculos
L→ id [ E ]


L.array ← lookup(top, id.lexema)

L.type ← contents(L.array .type)






L.addr ← newtemp()



0
0



gen(L.addr := E .addr 0 *0 L.type.width)
L→ L1 [ E ]
• L.array apunta a la tabla de símbolos – la base está en L.array .base.
• contents() – aplicado sobre array (I, T ) retorna T
Hernández-Novich (USB)
Representaciones Intermedias
2016
8 / 32
Generación de Código Intermedio
Acceso a Arreglos
Esquema directo con base cero – Los cálculos
L→ id [ E ]
L→ L1 [ E ]


L.array ← lookup(top, id.lexema)

L.type ← contents(L.array .type)







L.addr ← newtemp()





gen(L.addr 0 :=0 E .addr 0 *0 L.type.width)




L.array ← L1 .array







L.type
←
contents(L
.type)
1




t ← newtemp()



L.addr ← newtemp()





gen(t 0 :=0 E .addr 0 *0 L.type.width)







0
0
0 0
gen(L.addr := L1 .addr + t)
• L.array apunta a la tabla de símbolos – la base está en L.array .base.
• contents() – aplicado sobre array (I, T ) retorna T
Hernández-Novich (USB)
Representaciones Intermedias
2016
8 / 32
Generación de Código Intermedio
¿Cómo funciona?
Accediendo a un arreglo
foo
: array [2] of array [3] of int ;
bar ,i , j : int ;
bar := foo [ i ][ j ]
• Supongamos que la anchura de int es 4 bytes.
• El tipo de foo es array (2, array (3, integer )) – anchura es 24 bytes.
• El tipo de foo[i] es array (3, integer ) – anchura es 12 bytes.
Hernández-Novich (USB)
Representaciones Intermedias
2016
9 / 32
Generación de Código Intermedio
¿Cómo funciona?
El árbol decorado – bar := foo[i][j]
S
E .addr = bar
:=
E .addr = t4
L.array =foo
L.type =int
L.addr =t3
bar
L.array =foo
L.type =array (3, int)
L.addr =t1
foo.type = array (2, array (3, int)) [
E .addr = i
[
E .addr = j
]
] j
i
Hernández-Novich (USB)
Representaciones Intermedias
2016
10 / 32
Generación de Código Intermedio
¿Cómo funciona?
El código generado – bar := foo[i][j]
L→ id [ E ]
L→ L1 [ E ]
E→ L
Hernández-Novich (USB)
Representaciones Intermedias
2016
11 / 32
Generación de Código Intermedio
¿Cómo funciona?
El código generado – bar := foo[i][j]
L→ id [ E ]

L.array ← lookup(top, id.lexema)


L.addr ← newtemp()
0
0

L.type ← contents(L.array .type)
gen(L.addr := E .addr 0 *0 L.type.width)
L→ L1 [ E ]
E→ L
• L.type = array (3, int) con anchura 12
t1
:= i * 12
L.addr = t1 , E .addr = i
Hernández-Novich (USB)
Representaciones Intermedias
2016
11 / 32
Generación de Código Intermedio
¿Cómo funciona?
El código generado – bar := foo[i][j]
L→ id [ E ]
L→ L1 [ E ]

L.array ← lookup(top, id.lexema)
L.type ← contents(L.array .type)


L.addr ← newtemp()

0
0
0 0
gen(L.addr := E .addr * L.type.width)

L.array ← L1 .array






L.type ← contents(L1 .type)

t ← newtemp()
L.addr ← newtemp()



0 *0 L.type.width)


gen(t 0 :=0 E0 .addr

0
0 0
gen(L.addr := L1 .addr + t)
E→ L
• L.type = array (3, int) con anchura 12
L.addr = t1 , E .addr = i
• L.type = int con anchura 4
t1
t2
t3
:= i * 12
:= j * 4
:= t1 + t2
L.addr = t3 , E .addr = j
Hernández-Novich (USB)
Representaciones Intermedias
2016
11 / 32
Generación de Código Intermedio
¿Cómo funciona?
El código generado – bar := foo[i][j]
L→ id [ E ]
L→ L1 [ E ]
E→ L

L.array ← lookup(top, id.lexema)
L.type ← contents(L.array .type)


L.addr ← newtemp()

0
0
0 0
gen(L.addr := E .addr * L.type.width)

L.array ← L1 .array






L.type ← contents(L1 .type)

t ← newtemp()
L.addr ← newtemp()



0 *0 L.type.width)


gen(t 0 :=0 E0 .addr

0 L .addr 0 +0 t)
gen(L.addr
:=
1
n
o
E .addr ← newtemp()
gen(E .addr 0 :=0 L.array .base 0 [0 L.addr 0 ]0 )
• L.type = array (3, int) con anchura 12
L.addr = t1 , E .addr = i
• L.type = int con anchura 4
L.addr = t3 , E .addr = j
t1
t2
t3
t4
:=
:=
:=
:=
i * 12
j * 4
t1 + t2
foo [ t3 ]
• L.array .base = foo, L.addr = t3 , E .addr = t4
Hernández-Novich (USB)
Representaciones Intermedias
2016
11 / 32
Generación de Código Intermedio
¿Cómo funciona?
El código generado – bar := foo[i][j]
L→ id [ E ]
L→ L1 [ E ]
E→ L

L.array ← lookup(top, id.lexema)
L.type ← contents(L.array .type)
L.addr ← newtemp()

0
0
0 0
gen(L.addr := E .addr * L.type.width)

L.array ← L1 .array






L.type ← contents(L1 .type)

t ← newtemp()
L.addr ← newtemp()



0 *0 L.type.width)


gen(t 0 :=0 E0 .addr

0 L .addr 0 +0 t)
gen(L.addr
:=
1
n
o
E .addr ← newtemp()
gen(E .addr 0 :=0 L.array .base 0 [0 L.addr 0 ]0 )
• L.type = array (3, int) con anchura 12
L.addr = t1 , E .addr = i
• L.type = int con anchura 4
L.addr = t3 , E .addr = j
• L.array .base = foo, L.addr = t3 , E .addr = t4
• L.addr = t4 , E .addr = bar
Hernández-Novich (USB)


Representaciones Intermedias
t1
t2
t3
t4
bar
:=
:=
:=
:=
:=
i * 12
j * 4
t1 + t2
foo [ t3 ]
t4
2016
11 / 32
Flujo de Control
Estructuras de control
• La generación de código para estructuras de control está influenciada
por la generación de código para expresiones booleanas.
• Vamos a suponer que el problema de generación de código para una
expresión boolean B está resuelto y cumple
• Los atributos B.true y B.false son etiquetas.
• El código de B salta a B.true o B.false según el resultado de la
expresión booleana.
• El atributo heredado S.next corresponde a la etiqueta de la siguiente
instrucción después del código de S.
• Esto va a generar muchas etiquetas – pero son baratas.
• Permite evitar saltos a saltos.
• newlabel() – cada llamada retorna un nombre de etiqueta único.
• label() – genera código para incorporar la etiqueta.
Hernández-Novich (USB)
Representaciones Intermedias
2016
12 / 32
Flujo de Control
Instrucciones Simples
Esquema de generación
P→ S
S → S1 S2
Hernández-Novich (USB)
Representaciones Intermedias
2016
13 / 32
Flujo de Control
Instrucciones Simples
Esquema de generación
P→ S


S.next ←newlabel()





P.code←S.code ++

label(S.next)
S → S1 S2
• El programa principal es el caso base para S.next.
Hernández-Novich (USB)
Representaciones Intermedias
2016
13 / 32
Flujo de Control
Instrucciones Simples
Esquema de generación
P→ S
S → S1 S2


S.next ←newlabel()
P.code←S.code ++






label(S.next)




S1 .next←newlabel()







S
.next←S.next
2








S.code ←S1 .code ++


label(S1 .next)



S2 .code
• El programa principal es el caso base para S.next.
• Al secuenciar instrucciones:
• La siguiente a la secuencia es natural – piensen “FOLLOW”.
• Hace falta definir la siguiente para el punto medio.
Hernández-Novich (USB)
Representaciones Intermedias
2016
13 / 32
Flujo de Control
Selectores
S → if B then S1
is false
B.code
is true
B.true:
S1 .code
B.false:
Hernández-Novich (USB)
Representaciones Intermedias
2016
14 / 32
Flujo de Control
Selectores
S → if B then S1
is false
B.code
is true
B.true:
S1 .code
B.false:
¡B.false corresponde a S.next!
Hernández-Novich (USB)
Representaciones Intermedias
2016
14 / 32
Flujo de Control
Selectores
Esquema para el if-then
S→ if B then S1

B.true ←newlabel()





B.false
←S.next


S .next←S.next
1











S.code ←B.code ++








label(B.true)
++






S1 .code
• Necesitamos una nueva etiqueta para el cuerpo.
• Encadenamos S.next dos veces
• Para el salto de salida cuando B es falso.
• Como siguiente de la instrucción como un todo.
Hernández-Novich (USB)
Representaciones Intermedias
2016
15 / 32
Flujo de Control
Selectores
S → if B then S1 else S2
is false
B.code
is true
B.true:
S1 .code
goto S.next
B.false:
S2 .code
S.next:
Hernández-Novich (USB)
Representaciones Intermedias
2016
16 / 32
Flujo de Control
Selectores
S → if B then S1 else S2
is false
B.code
is true
B.true:
S1 .code
goto S.next
B.false:
S2 .code
S.next:
¡S1 .next y S2 .next deben coincidir con S.next!
Hernández-Novich (USB)
Representaciones Intermedias
2016
16 / 32
Flujo de Control
Selectores
Esquema para el if-then-else
S→ if B then S1 else S2

B.true ←newlabel()





B.false ←newlabel()




S1 .next←S.next





S2 .next←S.next


S.code ←B.code ++




































label(B.true) ++




S1 .code ++



0
0

gen( goto S.next) ++




label(B.false) ++



S2 .code
• Etiquetas dedicadas para los brazos del if-then-else.
• Salidas de los brazos coinciden con salida del bloque –
instrucciones anidadas en los brazos saltan directo a la salida.
Hernández-Novich (USB)
Representaciones Intermedias
2016
17 / 32
Flujo de Control
Iteración
S → while S1
begin:
is false
B.code
is true
B.true:
S.code
goto begin
B.false:
Hernández-Novich (USB)
Representaciones Intermedias
2016
18 / 32
Flujo de Control
Iteración
S → while S1
begin:
is false
B.code
is true
B.true:
S.code
goto begin
B.false:
¡B.false corresponde a S.next!
Hernández-Novich (USB)
Representaciones Intermedias
2016
18 / 32
Flujo de Control
Iteración
Esquema para el while
S→ while B do S1

begin ←newlabel()





B.true ←newlabel()




B.false ←S.next





S1 .next←S.begin
















S.code ←label(begin) ++



B.code ++



label(B.true) ++





S1 .code ++



0
0
gen( goto begin)















• Necesitamos una nueva etiqueta para el cuerpo.
• Al ejecutar el cuerpo se regresa a evaluar la condición.
• Se ejecutó todo hasta alcanzar el goto explícito.
• Hay un salto en el bloque anidado que aprovecha S1 .next.
Hernández-Novich (USB)
Representaciones Intermedias
2016
19 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code
• Las expresiones booleanas se interpretan según su contexto
• Para alterar el flujo de control.
• Como valor de una expresión booleana.
Hernández-Novich (USB)
Representaciones Intermedias
2016
20 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code
• Las expresiones booleanas se interpretan según su contexto
• Para alterar el flujo de control.
• Como valor de una expresión booleana.
• Si la definición del lenguaje obliga a evaluar todas las partes de una
expresión booleana, la generación de código es similar a la de
expresiones.
• Codificar true y false como 1 y 0, respectivamente.
• Generar código para calcular el resultado en un temporal.
Hernández-Novich (USB)
Representaciones Intermedias
2016
20 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code
• Las expresiones booleanas se interpretan según su contexto
• Para alterar el flujo de control.
• Como valor de una expresión booleana.
• Si la definición del lenguaje obliga a evaluar todas las partes de una
expresión booleana, la generación de código es similar a la de
expresiones.
• Codificar true y false como 1 y 0, respectivamente.
• Generar código para calcular el resultado en un temporal.
• Si la definición del lenguaje permite evaluar parcialmente la expresión,
se genera código de corto circuito o Jumping Code.
• Los operadores booleanos se traducen a saltos.
• La posición en el código representa el valor parcial o definitivo de la
expresión booleana.
Hernández-Novich (USB)
Representaciones Intermedias
2016
20 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code – casos base
B→ true
B→ false
B→ not B1
B→ E1 < E2
Hernández-Novich (USB)
Representaciones Intermedias
2016
21 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code – casos base
B→ true
B→ false
{B.code ← gen(0 goto0 B.true)}
{B.code ← gen(0 goto0 B.false)}
B→ not B1
B→ E1 < E2
• B.true y B.false contienen la etiqueta destino – Just do it!
Hernández-Novich (USB)
Representaciones Intermedias
2016
21 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code – casos base
B→ true
B→ false
B→ not B1
{B.code ← gen(0 goto0 B.true)}
{B.code ← gen(0 goto0 B.false)}
(
)
B1 .true ←B.false
B1 .false←B.true
B.code ←B1 .code
B→ E1 < E2
• B.true y B.false contienen la etiqueta destino – Just do it!
• La negación mantiene el código, pero invierte el sentido de saltos.
Hernández-Novich (USB)
Representaciones Intermedias
2016
21 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code – casos base
B→ true
B→ false
B→ not B1
B→ E1 < E2
{B.code ← gen(0 goto0 B.true)}
{B.code ← gen(0 goto0 B.false)}
(
)
B1 .true ←B.false
B1 .false←B.true
B.code ←B1 .code

B.code←E1 .code ++



E2 .code ++
gen(0 if0 E1 .addr 0 <0 E2 .addr 0 goto0 B.true) ++



gen(0 goto0 B.false)
• B.true y B.false contienen la etiqueta destino – Just do it!
• La negación mantiene el código, pero invierte el sentido de saltos.
• Cada operador relacional genera los saltos a las etiquetas
correspondientes.
Hernández-Novich (USB)
Representaciones Intermedias
2016
21 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code – disyunción
B→ B1 or B2


B1 .true ←B.true




B1 .false←newlabel()





B2 .true ←B.true
B .false←B.false












2






B.code
←B1 .code ++








label(B
.false)
++


1






B2 .code
• Si B1 es cierta, seguimos directo a B.true – cortocircuito.
• Si B1 es falsa, evaluamos B2 saltando a la nueva etiqueta.
• El resto de salidas para B1 y B2 se mantienen a partir de B.
Hernández-Novich (USB)
Representaciones Intermedias
2016
22 / 32
Expresiones Booleanas para Control de Flujo
Expresiones Booleanas para Control de Flujo
Jumping Code – conjunción
B→ B1 and B2


B1 .true ←newlabel()




B1 .false←B.false





B2 .true ←B.true
B .false←B.false












2






B.code
←B1 .code ++








label(B
.true)
++


1






B2 .code
• Si B1 es falsa, seguimos directo a B.false – cortocircuito.
• Si B1 es cierta, evaluamos B2 saltando a la nueva etiqueta.
• El resto de salidas para B1 y B2 se mantienen a partir de B.
Hernández-Novich (USB)
Representaciones Intermedias
2016
23 / 32
Expresiones Booleanas para Control de Flujo
Un ejemplo
. . . que conduce a una mejora
if (x < 100 or x > 200 and x != y ) x = 0;
El esquema generaría código similar a
if x
goto
L3: if x
goto
L4: if x
goto
L2: x :=
L1:
< 100 goto L2
L3
> 200 goto L4
L1
!= y goto L2
L1
0
Hernández-Novich (USB)
• goto L3 es redundante
• Ambos goto L1 podrían
eliminarse si se contara
con ifnot en el TAC.
Representaciones Intermedias
2016
24 / 32
Expresiones Booleanas para Control de Flujo
Mejorando el código para el if
Fall Through Optimization
S→ if B then S1

B.true ←fall





B.false ←S.next
S .next←S.next







1





S.code
←B.code ++






S1 .code
• El código de S1 siempre está después del código de B.
• No generar una etiqueta en medio.
• La etiqueta fall indica “dejarse caer” a la siguiente instrucción.
• Se aplica la misma técnica para el while.
Hernández-Novich (USB)
Representaciones Intermedias
2016
25 / 32
Expresiones Booleanas para Control de Flujo
Mejorando el código para expresiones booleanas
Fall Through Optimization para operadores relacionales
B→ E1 < E2


test ← E1 .addr ++ 0 <0 ++ E2 .addr










if
B.true
=
6
fall
and
B.false
=
6
fall
then






0
0
0
0
0
0


s
←
gen(
if
test
goto
B.true)
++
gen(
goto
B.false)








else if B.true 6= fall then





 s ← gen(0 if0 test 0 goto0 B.true)


else if B.false 6= fall then




s ← gen(0 ifnot0 test 0 goto0 B.false)





else




s ←00




















B.code ← E1 .code ++ E2 .code ++ s
Ahora genera la cantidad mínima de saltos.
Hernández-Novich (USB)
Representaciones Intermedias
2016
26 / 32
Expresiones Booleanas para Control de Flujo
Mejorando el código para expresiones booleanas
Fall Through Optimization para disyunción
B→ B1 or B2



B1 .true ←if B.true 6= fall then B.true else newlabel()








B
.false←fall


1








B
.true
←B.true
2




B .false←B.false

2

B.code ←if B.true =
6 fall then




B
.code
++ B2 .code

1




else



B1 .code ++ B2 .code ++ label(B1 .true)













Ahora genera la cantidad mínima de saltos.
Hernández-Novich (USB)
Representaciones Intermedias
2016
27 / 32
Expresiones Booleanas para Control de Flujo
El ejemplo, después de la optimización
if (x < 100 or x > 200 and x != y ) x = 0;
El esquema optimizado generaría código similar a
if x < 100 goto L2
ifnot x > 200 goto L1
ifnot x != y goto L1
L2: x := 0
L1:
Hernández-Novich (USB)
• No hay etiquetas
redundantes
• Menos saltos.
Representaciones Intermedias
2016
28 / 32
Expresiones Booleanas por su valor
Evaluando Expresiones Booleanas
Jumping Code hasta el resultado
• Jumping Code sigue aplicando para evaluar expresiones booleanas
para obtener su valor.
• Se salta por cortocircuito hasta determinar el valor final.
• La instrucción final produce el valor booleano correspondiente.
• El valor booleano puede ser natural o codificado según convenga al
lenguaje y al TAC.
• Este método es el más eficiente si la semántica del lenguaje permite
evaluar con corto circuito.
Hernández-Novich (USB)
Representaciones Intermedias
2016
29 / 32
Expresiones Booleanas por su valor
Expresiones Booleanas por su valor
Cálculo del valor final
S→ id := B




B.true ←newlabel()








B.false←newlabel()










S.code←B.code
++






label(B.true) ++
0
0

gen(id.addr := true) ++






0 goto0 S.next) ++


gen(










label(B.false)
++






0
0
gen(id.addr := false)
Hernández-Novich (USB)
Representaciones Intermedias
2016
30 / 32
Consideraciones
Consideraciones
• La generación para instrucciones utiliza la técnica de concatenación
de cadenas. Reescríbala para hacer generación progresiva.
• La generación para instrucciones utiliza atributos heredados.
• Intente escribirla para utilizar atributos sintetizados.
• Aplique la técnica de marcadores y posible reescritura de reglas para
convertir la herencia en copia a través de la pila de un reconocedor LR.
• Extienda el esquema de generación por corto circuito para incluir
implicación, disyunción exclusiva y equivalencia.
• Complete el esquema de generación por corto circuito aplicando la
técnica de fall through para la conjunción y los casos agregados
anteriormente.
Hernández-Novich (USB)
Representaciones Intermedias
2016
31 / 32
Referencias Bibliográficas
Bibliografía
• [Aho] (Primera Edición)
• Secciones 8.3 y 8.4
• Ejercicios 8.7 a 8.10
• [Aho] (Segunda Edición)
• Secciones 6.4.3, 6.4.4
• Ejercicios 6.4.1 a 6.4.9
Hernández-Novich (USB)
Representaciones Intermedias
2016
32 / 32
Descargar