Facultad de Ingeniería
Compiladores
Segundo ciclo 2019
Mgtr. Diana Gutiérrez
Ejercicios - Análisis semántico
Instrucciones: Resolver cada uno de los ejercicios que se presentan a continuación. Deje
constancia de su razonamiento y procedimiento.
1. Diseñe una gramática que permita generar números enteros binarios.
a. Amplíe la gramática anterior en una gramática de atributos para convertir
un número binario entero a un número decimal entero.
b. Construya el árbol de análisis sintáctico anotado para la cadena 11001 y
encontrar su valor decimal. Indicar el orden de evaluación de los atributos.
2. Asuma que a partir del 2020 las computadoras pasarán de trabajar con cadenas
de dígitos 0 y 1 a trabajar con la letra x para representar el 0 y la letra y para
representar el 1. Además, se invertirá el orden de los símbolos. Por ejemplo, la
cadena 00111 se convertirá en yyyxx. Se desea diseñar una TDS que realice esta
traducción usando la gramática base:
S → 0AS | 1
A → 0SA | 1
3. La siguiente gramática genera divisiones de números enteros y reales. La idea de
esta gramática es que la operación de división se interprete de forma diferente
dependiendo de si se trata de números enteros o reales. Por ejemplo: 5/4 puede
tener el valor 1.2 o 1, si se trata de una división de reales o entera.
exp → exp / exp | num_int | num_real
El lenguaje de programación requiere que las operaciones en las que aparecen
números enteros combinados con reales, tienen que ser convertidos
implícitamente a expresiones con punto flotante. Por ejemplo: la expresión 5/2/2.0
es 1.25, mientras que el significado de 5/2/2 es 1. Agregue las reglas semánticas
necesarias para que se puedan distinguir entre estos dos tipos de operaciones.
Tip: se necesitan tres atributos: un atributo booleano isFloat; que indica si aparece
un operando que tiene un valor real, otro atributo etype que indica el tipo de una
subexpresión (int o real) y un atributo val para almacenar el valor de la expresión.
4. Diseña una TDS para traducir declaraciones de funciones en C a Pascal. Usar
como gramática base:
S → Tipo fun L ;
Tipo_fun → void | int | float
L → F Lista_fun
Lista_fun → , F Lista_fun | ε
F → id ( A )
A → void | Argu LArgu | ε
LArgu → , Argu LArgu | ε
Argu → Tipo id | Tipo * id
Tipo → int | float
Algunos ejemplos:
int f(), g(float a, int *b); function f:integer; function g(a:real; var
b:integer):integer;
void h(int a, float *c), j(void); procedure h(a:integer; var c:real); procedure j;
float f(int a); function f(a:integer):real;
Producciones Reglas semánticas
S → Tipo_fun L ; L.type = Tipo_fun.type
S.trad = L.trad || “;”
Tipo_fun → void Tipo_fun.type = void
Facultad de Ingeniería
Compiladores
Segundo ciclo 2019
Mgtr. Diana Gutiérrez
Tipo_fun.trad = “procedure”
Tipo_fun → int Tipo_fun.type = int
Tipo_fun.trad = “function”
Tipo_fun → float Tipo_fun.type = float
Tipo_fun.trad = “function”
L → F Lista_fun F.type = L.type
Lista_fun.type = L.type
L.trad = F.trad || Lista_fun.trad
Lista_fun → , F Lista_fun1 F.type = Lista_fun.type
Lista_fun1.type = Lista_fun.type
Lista_fun.trad = “;” || F.trad || Listad_fun1.trad
Lista_fun → ε Lista_fun.trad = “”
F → id ( A ) if (F.type = void and A.trad = “”) “procedure” || id.lexema
if (F.type = void and A.trad <> “”) “procedure” || id.lexema || “(” || A.trad || “)”
if (F.type = int and A.trad = “”) “function” || id.lexema || “: integer”
if (F.type = int and A.trad <> “”) “function” || id.lexema || “(” || A.trad || “)” || “:
integer”
if (F.type = float and A.trad = “”) “function” || id.lexema || “: real”
if (F.type = float and A.trad <> “”) “function” || id.lexema || “(” || A.trad || “)” ||
“: real”
A → void A.trad = “”
A → Argu LArgu A.trad = Argu.trad || LArgu.trad
A→ε A.trad = “”
LArgu → , Argu LArgu1 LArgu.trad = “,” || Argu.trad || LArgu1.trad
LArgu → ε LArgu.trad = “”
Argu → Tipo id Argu.trad = id.lexema || “:” || Tipo.trad
Argu → Tipo * id Argu.trad = “var” || id.lexema || “:” || Tipo.trad
Tipo → int Tipo.trad = “integer”
Tipo → float Tipo.trad = “real”