Tutoría 4 — Simulacro de Examen: Acciones Semánticas y Gramáticas de Atributos
Resumen Ejecutivo
Tutoría/taller centrada en la parte semántica del examen (la más difícil), continuando el simulacro de tutorías anteriores. Se resuelven en directo, paso a paso, acciones semánticas sobre gramáticas de atributos: contar elementos, propagar valores y hacer comprobaciones semánticas con condiciones anidadas. Mensaje pedagógico recurrente: el objetivo no es programar sino conceptualizar y diseñar; se puede responder en pseudocódigo.
Reparto de nota del examen: léxico 3 pts, sintáctico 3,5 pts, semántico 3,5 pts. ⚠️ EXAMEN
(La transcripción tiene tramos con silencios largos —la profesora escribía en pantalla—; los apuntes recogen el contenido reconstruido.)
Conceptos Clave
- Atributo sintetizado: se calcula a partir de los hijos y sube por el árbol (de derecha a izquierda/padre). Es lo natural en analizadores LR ascendentes. ⚠️ EXAMEN
- Atributo heredado: se pasa a un hermano o hijo (p.ej. el tipo en
T id). Más difícil en ascendente: requiere marcadores. ⚠️ EXAMEN - Regla de redenominación: producción con un solo símbolo a cada lado (
L → E,R → T); solo pasa todos los atributos del hijo al padre, sin añadir nada. ⚠️ EXAMEN - Notación de atributos:
$$= padre;$1,$2,$3= símbolos de la parte derecha (en CUP:RESULTy etiquetas con nombre). ⚠️ EXAMEN - Conversión de valor en
E → num: convertir el lexema a entero (Integer.parseInt) o usar el valor ya tipado que pasa el léxico. ⚠️ EXAMEN E → id: no tiene valor numérico → inicializar el atributovalor = 0. ⚠️ EXAMEN- Comprobaciones anidadas: varias condiciones semánticas se anidan con
IF ... ELSE; elOKsolo se da si se cumplen todas. ⚠️ EXAMEN
Desarrollo del Temario
1. Filosofía: pseudocódigo y diseño, no programación
"No os estáis formando para ser programadores; lo vuestro es conceptualizar, diseñar y pensar el algoritmo para que luego otro pique el código."
- Se valora explicar cada línea y justificar las decisiones.
- Se acepta
padre.numR = hijo1.numRigual que$$.numR = $1.numR: lo importante es que se vea qué información pasa del hijo al padre. - Los nombres de los atributos importan: representan semánticamente qué se quiere hacer (
valor,numEles,numR…). - Mejor no mezclar Java y pseudocódigo; elegir uno.
2. Ejercicio 1 — Contar elementos y valores (R → R + T)
Para una producción R → R + T con atributos:
- numR = nº de elementos de la expresión.
- valor / numY = otro contador (p.ej. nº de símbolos Y).
Acciones semánticas:
R → R + T { $$.numR = $1.numR + $3.numR + 1 // +1 por el signo '+'
$$.numY = $1.numY + $3.numY }
Por qué el +1: la producción tiene tres partes (R, +, T); el + cuenta como un elemento más. Al aplicar la recursividad, la R izquierda ya trae acumulado lo sumado en pasos anteriores.
Casos base:
T → x { $$.numR = 1 // un elemento que aporta a R
$$.numY = 0 }
T → y { $$.numR = 1
$$.numY = 1 } // cuenta una Y
R → T { $$ = $1 } // redenominación: pasa todos los atributos
3. Ejercicio 1 — Hojas E → num y E → id
E → num { $$.valor = Integer.parseInt($1.lexema) // o $1.valor si el léxico ya lo tipó
$$.numL = 1 }
E → id { $$.valor = 0 // un identificador NO tiene valor numérico → inicializar
$$.numL = 1 }
Dos opciones para num según el léxico:
- El léxico pasa solo el lexema (string de dígitos) → hay que convertir a entero.
- El léxico ya pasa el valor tipado (porque la expresión regular reconoció el número) → se propaga directamente.
4. Ejercicio 1 — Redenominación L → E y comprobación final
L → E { $$.numL = $1.numL
$$.valor = $1.valor } // equivale a $$ = $1 (o sin acción → paso automático en CUP)
Comprobación semántica (anidada) en S → L , R (o similar): el número de elementos de L debe coincidir con el de R y la suma de valores cumplir una condición:
S → L , R {
IF ($1.numL == $3.numR) THEN
IF ($1.valor >= $3.numY) THEN
$$ = OK
ELSE
error("el valor de num no es mayor o igual que el nº de elementos Y")
ELSE
error("el nº de elementos de L no coincide con el de R")
}
⚠️ Clave: las condiciones se anidan, no se ponen independientes. Si se pusieran sueltas y la primera da OK, se "olvidaría" comprobar la segunda. El OK solo se emite cuando ambas se cumplen.
5. Sintetizados vs. heredados
- Todo lo que se ha subido (numR, valor, numL) son atributos sintetizados (van hacia arriba). En la raíz no se "heredan": se hace una comprobación de condición.
- Atributo heredado (ejemplo
T id, una declaración):Tlleva el tipo (int, char…) que ha subido; se lo pasa alid(su hermano a la derecha). Eso es herencia (de padres o hermanos). - Puede extenderse a una lista de identificadores: el tipo se reparte a todos.
- En analizadores ascendentes la herencia es más difícil (las reducciones van hacia arriba) → requiere marcadores; por eso se usan menos ejemplos con atributos heredados.
6. Ejercicio 2 (propuesto) — Restricciones de longitud
Gramática recursiva por la izquierda:
- P genera muchas A precedidas de una B (P → P a | b).
- Q genera muchas C precedidas de una D (Q → Q c | d).
Restricciones a comprobar:
1. Si P contiene más de dos símbolos A, entonces Q debe contener al menos un símbolo.
2. longitud(P) ≤ longitud(Q).
Atributos: numA (cuenta A en P), num (cuenta C/D en Q), longP, longQ. Se cuentan los símbolos por separado con atributos distintos y se acumulan por la recursividad; al llegar arriba se comparan.
longP = numA + 1(la única B);longQ = numC + 1(la única D).- Hay formas más eficientes (un solo atributo
long) y otras más detalladas (un atributo por símbolo y comparaciones al final).
Recordatorio de gramáticas: en la recursividad por la izquierda
P → P a, cada aplicación añade unaa; la recursividad para cuando se aplica el caso baseP → b. Sin caso base, el lenguaje no genera cadenas.
Preguntas de Autoevaluación
- ¿Cómo se reparte la nota del examen entre léxico, sintáctico y semántico?
- En
R → R + T, ¿por qué la acción del contador suma+1? ¿Qué hace laRizquierda en la recursividad? - En
E → num, ¿cuándo hay que convertir el lexema a entero y cuándo basta con propagar el valor? - ¿Por qué en
E → idse inicializavalor = 0? - ¿Qué es una regla de redenominación y qué acción semántica lleva? ¿Se puede omitir en CUP?
- ¿Por qué las comprobaciones semánticas deben anidarse con
IF/ELSEen vez de ponerse independientes? - Diferencia entre atributo sintetizado y heredado. Pon un ejemplo de herencia con
T id. - ¿Por qué los atributos heredados son más difíciles en un analizador LR ascendente?
- ¿Qué significan
$$,$1,$2,$3y cómo se traducen a CUP? - Para el ejercicio P/Q, ¿qué atributos definirías y cómo calcularías
longPylongQ?