Vous êtes sur la page 1sur 18

TEMA 6 GRAMTICAS DE ATRIBUTOS Y SEMNTICA

6.1 Gramticas de atributos Una gramtica de atributos es una gramtica independiente del contexto en la cual a sus smbolos terminales y no terminales se les dota de unos atributos y a sus producciones de unas funciones de evaluacin que hacen que dichos atributos se propaguen a travs de la gramtica. Su fin es conocer un determinado valor de un atributo en cualquier parte del rbol de derivacin y tomar la decisin oportuna. Un atributo es una propiedad asociada a una estructura sintctica. Si una estructura sintctica representada por el smbolo gramatical X tiene asociado un atributo a lo representaremos por X.a (NombreSimbolo. Nombre atributo) Las funciones semnticas relacionan los valores de los atributos definidos sobre la gramtica atribuida y van asociadas a producciones de la gramtica atribuida. Ejemplo: Sea el lenguaje L={an |n>=0} generado por la siguiente gramtica: G={={a, $}, N={S, A}, S, P) P: SA$ AaA Aa Se quiere atribuir para que contabilice y escriba el nmero de aes que tiene una palabra generada
SA$ {writeln (A.num)} AaA {A1.num=1+A2.num} Aa {A.num=1} a S.num A.num $ A.num a 1

Definicin formal Una gramtica de atributos est formada por una tripleta GA={GIC, A, F} G gramtica independiente del contexto A atributos asociados a los smbolos terminales y no terminales F funcin de evaluacin, funcin asociada a produccin que determina como obtener unos atributos en funcin de otros dentro de la misma produccin AX1 X2 X3 Xn ; AN y Xi(|N) A.a=f (X1.a,X2.b,Xm.z) a es un atributo asociado al smbolo no terminal A y obtiene su valor en funcin de los atributos: a asociado a X1, b asociado a X2 ,y z asociado a Xm ( es un atributo obtenido en funcin de la parte derecha de la produccin) X1.a=f (A.a,X2.b) a es un atributo asociado al smbolo X1 y obtiene su valor en funcin de los atributos: a asociado a A , b asociado a X2 ( es un atributo obtenido en funcin de elementos de la parte derecha e izquierda de la produccin) A.a=f (y1.b, B.a) , X1.a=f (y1.b, B.a) atributos incorrectos no se obtienen dentro de la produccin Tipos de atributos: Sintetizados- son atributos que se propagan desde las hojas a la raiz AX1 X2 X3 Xn ; AN y Xi(|N) A.a=f(X1.a,X2.b,Xm.z) a es un atributo sintetizado obtienen sus valores de los atributos de un nivel inferior en la generacin del rbol, es decir de la parte derecha de la produccion A.a
SA$ {writeln (A.num)} AaA {A1.num=1+A2.num} Aa {A.num=1} Xna

X1..a

X2b

Heredados - son atributos que se propagan desde la raiz a las hojas o dentro de un mismo nivel AX1 X2 X3 Xn ; AN y Xi(|N) X1.a=f(A.a,X2.b,) a es un atributo heredado obtenido en funcin de los atributos a y b obtiene sus valores de los atributos del mismo nivel o superior en la generacin del rbol, es decir se calculan descendentemente
A.a SA$ {A.num=0} AaA {A2.num=1+A1.num} Aa {writeln (A.num+1} Xn.za

X1..a

X2b

Intrnsecos Son atributos relativos a smbolos terminales, por lo tanto valores correspondes a las hojas (valores finales). Son valores fijos obtenidos de antemano cuyo valor se obtiene de partida. En el ejemplo anterior de contabilizar aes, el valor intrnseco de cada a es 1.
A.a X1..a X2b Xn.za SA$ {writeln (A.num)} AaA {A1.num=1+A2.num} Aa {A.num=1}

Poder de significacin de las gramticas de atributos La gramticas de atributos tienen un mayor poder de significacin que una gramtica independiente del contexto. Puede reconocer lenguajes de tipo superior, es decir de tipo 1 o tipo 0 . Sea el lenguaje L={anbncn| n>=0} es un lenguaje de tipo 1, solo puede ser generado por una gramatica de tipo 1 o 0 . Se puede construir una gramtica de atributos GA=( GIC, A, F) que genere dicho lenguaje: Sea la gramtica: SAB AaAb | BcB | que genera el lenguaje L={anbncm| n>=0,m>=0} Podemos atribuirla para que genere el lenguaje L={anbncn| n>=0} Atributos, necesarios para contabilizar las aes, bes y ces: num_ab atributo sintetizado asociado a A y num_c atributo sintetizado asociado a B Funciones asociadas a las producciones necesarias para la propagacin de los atributos: SAB {IF A.num_ab<>B.num_c Then error semntico} AaAb {A1.num_ab=A2.num_ab+1} | {A1.num_ab=0} BcB {B1..num_c=B2.num_c+1} | {B..num_c=0} Ejemplos de gramticas de atributos - Nmero de veces que se da la subcadena ab en una palabra, sobre una gramtica que genera aes y bes, como la siguiente: SaS | bS | Atributos necesarios: uno sintetizado que contabilice el nmero de ab que se dan en la palabra y el otro tambin sintetizado para saber si anteriormente se ha dado una b. Funciones asociadas a producciones necesarias para la propagacin de los atributos S {S.es_b=false, S.num_ab=0} SbS {S,es_b=true, S1.num_ab=S2.num_ab} SaS {IF S2.es_b=true THEN S1.num_ab=S2.num_ab +1, S1.es_b=false ELSE S1.num_ab=S2.num_ab; S1.es_b=S2.es_b } - La mayor subcadena formadas de aes en una palabra, sobre una gramtica que genera aes y bes como la siguiente: SaS | bS | Atributos necesarios: uno sintetizado que contabilice el nmero de aes que se dan en la palabra y el otro tambin sintetizado para almacenar el nmero mayor de aes consecutivas.

Funciones asociadas a producciones necesarias para la propagacin de los atributos S {S.num_aes=0, S.mayor=0} SaS {S1,num_aes=S2.num_aes+1, S1.mayor=S2.mayor} SbS {IFS2.num_aes>S2.mayor THEN S1.mayor:=S2.nun_aes;S1.num_aes:=0 ELSE S1.mayor:=S2.mayor S1.num_aes=0} Crear una gramtica de atributos que calcule el valor en decimal de un nmero binario, a partir de la siguiente gramtica: S S, S0S |1S |0 | 1 S`S {writeln (S.valor)} S0 S {S1.pos:=s2.pos+1;S1.valor:=s2.valor} S1 S {S1.pos:=s2.pos+1;S1.valor:=s2.valor+2 s1.pos} S0 {S.valor:=0; S.pos:=0 } S1 { S.pos:=0; S.valor:=2 s.pos} Ejemplo anterior con pos como atributo heredado S`S {S.pos:=0; writeln (S.valor)} SS 0 {S2.pos:=S1.pos+1;S1.valor:=S2.valor} SS 1 {S2.pos:=S1.pos+1;S1.valor:=S2.valor+2 s1.pos} S0 {S.valor:=0} S1 {S.valor:=2 s.pos} - Crear una gramtica de atributos que calcule el valor en decimal de un nmero binario, a partir de la siguiente gramtica: SA.B ; ADA |D ; BBD |D ; D0 | 1 Atributos necesarios: uno sintetizado que contiene la suma de los valores y otro tambin sintetizado para llevar la posicin Funciones asociadas a producciones necesarias para la propagacin de los atributos AD {A.pos:=0, A.valor:=D.2A.pos } ADA {A1.pos:=A2.pos+1; A1.valor:=A2.valor+ D.2A1.pos } BD {B.pos:=-1, B.valor:=D.2B.pos } BBD {B1.pos:=B2.pos+1; B1.valor:=B2.valor+ D.2B1.pos } SAB {S.valor:=A.valor+B.valor} - Sea L el lenguaje formado por palabras del alfabeto ={ a,b} en las que existen n grupos de repeticin, donde n>=2, tal que: Cada uno de los n-1 primeros grupos de repeticin (todos menos el ltimo) tiene longitud par. El ltimo grupo de repeticin tiene longitud n, indicando el nmero de grupos de repeticin que tiene una palabra. A partir de la gramtica S AX | BY A aA |a X BY |B Y AX |A B bB |b , obtener una GA que defina L.

Usaremos tres atributos de tipo sintetizado:long, asociado a los no terminales A y B, expresa la longitud del grupo long_ult, asociado a X e Y, expresa la longitud del ltimo grupo que generan dichos no terminales. grupos, asociado a X e Y, expresa el nmero de grupos generados por dichos no terminales. Funciones asociadas a producciones necesarias para la propagacin de los atributos: { IF A.long mod 2 <> 0 OR X.long_ult <> X.grupos + 1 THEN rechazar_palabra() } { IF B.long mod 2 <> 0 OR Y.long_ult <> Y.grupos + 1 THEN rechazar_palabra() } { IF B.long mod 2 <> 0 THEN rechazar_palabra(); X.long_ult := Y.long_ult; X.grupos := Y.grupos + 1 } XB { X.long_ult := B.long; X.grupos := 1 } YAX { IF A.long mod 2 <> 0 THEN rechazar_palabra(); Y.long_ult := X.long_ult; Y.grupos := X.grupos + 1; } YA { Y.long_ult := A.long; Y.grupos := 1; } AaA { A1.long := 1 + A2.long; } A->a { A.long := 1; } { B.long := 1; } BbB { B1.long := 1 + B2.long; } B->b SAX SBY XBY

- Dado el alfabeto = {a, b, 0, 1} sea la siguiente gramtica: <Raiz> ::= <Cadena> <Cadena> ::= <Letra> <Cadena> <Letra> | <Letra> <Digito> <Letra> <Letra> ::= a | b <Digito> ::= 0 | 1 que define las palabras con la siguiente estructura: En primer lugar una subpalabra compuesta por letras a y b A continuacin, en el centro de la palabra, un dgito que puede ser 0 o 1. Finalmente, una segunda subpalabra compuesta por letras a y b, y que tiene la misma cantidad de smbolos que la primera subpalabra. Se desea afinar el lenguaje anterior para que las palabras cumplan adems las siguientes restricciones: Si el dgito central es 0, la primera subpalabra deber empezar por a. Por ejemplo, seran vlidas las palabras aba0bba, a0a y a0b. Pero no seran vlidas b0a ni ba0aa. Pero si el dgito central es 1, entonces es la segunda subpalabra quien deber empezar por a. Por ejemplo, seran vlidas las palabras a1a, b1a y abb1abb. Pero no seran vlidas a1b ni ba1ba. Se pide: A partir de la gramtica anterior y sin modificarla, obtener una gramtica de atributos que compruebe dichas restricciones, dando un mensaje indicativo en la raz del rbol (representada por la produccin <Raiz> ::= <Cadena> ). Dicho mensaje ser simplemente 'palabra vlida' o 'palabra no vlida'. Previamente se indicarn los atributos a utilizar, justificando su uso, los valores que podrn tomar y si se propagan de forma heredada o sintetizada. Los atributos utilizados son: valor, que sirve tanto para el no terminal <Digito> como para <Letra>. En el primer caso podr valer 0 1, mientras que en el segundo valdr a o b. En ambos casos es de tipo sintetizado. digito (dgito central) es un atributo sintetizado de <Cadena> que mantiene el valor (0 1) del dgito central generado. comienzo_1a (comienzo primera subcadena) y comienzo_2a (comienzo segunda subcadena) son dos atributos sintetizados de <Cadena> que expresan las letras por las que empiezan la primera y la segunda subcadenas, respectivamente. <Digito> ::= 0 { <Digito>.valor := 0 } <Digito> ::= 1 { <Digito>.valor := 1 } <Letra> ::= a { <Letra>.valor := a } <Letra> ::= b { <Letra>.valor := b } <Cadena> ::= <Letra> <Digito> <Letra> { <Cadena>.digito := <Digito>.valor; <Cadena>.comienzo_1a := <Letra1>.valor; <Cadena>.comienzo_2a := <Letra2>.valor; } <Cadena> ::= <Letra> <Cadena> <Letra> { <Cadena1>.digito := <Cadena2>.digito; <Cadena1>.comienzo_1a := <Letra1>.valor; <Cadena1>.comienzo_2a := <Cadena2>.comienzo_2a } <Raiz> ::= <Cadena> { IF (<Cadena>.digito = 0) AND (<Cadena>.comienzo_1a = a) OR (<Cadena>.digito = 1) AND (<Cadena>.comienzo_2a = a) THEN writeln (palabra vlida) ELSE writeln (palabra no vlida) }

La gramtica de atributos resultante ser, pues:

6.2 Gramtica de atributos en el anlisis semntico de un lenguaje de programacin Podemos ampliar la definicin de gramtica de atributos enfocndola en la especificacin del anlisis semntico, es decir verificar la validez semntica. As la tripleta anterior se pasa a la cudrupla GA= (G, A, F, C) En donde C es el conjunto de condiciones que deben cumplir los atributos asociados a las funciones semnticas de una produccin Crear una gramtica de atributos que especifique la comprobacin de tipos de las expresiones de un lenguaje L, cuya sintaxis es la siguiente: <expresin>::=<expresin> <op1> <termino> | <termino> <termino>::=<termino> <op2> <factor> op1, op2 | <factor> entero <factor>::=<unario><operando> real <operando>::=identificador | cte_ent | ( <expresin> ) <op2> ::= * | / <op1> ::= + | <unario>::= + | - |

entero entero real

real real real

La semntica asociada a estas reglas de produccin debe cumplir con las siguientes condiciones: Las operaciones solo se podrn realizar con tipos numricos (entero o real). El resultado ser siempre real a no ser que ambos sean enteros en cuyo caso el resultado ser entero <expresin>::=<expresin> <op1> <termino> {IF (<expresin2>.tipo<> entero ) AND (<expresin2>.tipo <>real OR (<termino>.tipo<>real) AND(<termino>.tipo<>entero THEN error semntico ELSE IF ((<expresin2>.tipo= entero AND (<termino>.tipo=entero)) THEN ((<expresin1>.tipo= entero ELSE((<expresin1>.tipo= real } expresin>::= <termino> { <expresin2>.tipo::=<termino>.tipo} <termino>::=<termino> <op2> <factor> {IF (<termino2>.tipo<> entero ) AND (<termino2>.tipo <>real OR (<factor>.tipo<>real) AND(<factor>.tipo<>entero THEN error semntico ELSE IF ((<termino2>.tipo= entero AND (<factor>.tipo=entero)) THEN ((<termino1>.tipo= entero ELSE((<termino1>.tipo= real } <termino>::= <factor> { <termino>.tipo::=<factor>.tipo} <factor>::= ident {<factor>.tipo ::0 ident.tipo } <factor>::= const_ent {<factor>.tipo ::= entero } <factor>::= const_real {<factor>.tipo ::= real } <factor>::= (<expresin> {<factor>.tipo ::= <expresin>.tipo }

6.3 Semntica de un lenguaje de programacin Es la encargada del significado de los programas fuente en ese lenguaje. Se divide en dos partes: semntica esttica y dinmica. Semntica esttica Un texto fuente es correcto, si es correcto su lxico, sintaxis y su semntica esttica. La semntica esttica se encargada de las condiciones que deben cumplir los objetos que forman las estructuras que intervienen en un texto fuente. Se llama objeto a cualquier entidad que puede intervenir en un texto (programa fuente): variables, constantes, tipos y subprogramas. Los objetos que intervienen en las estructuras que componen un texto fuente, tienen que cumplir unas ciertas propiedades y caractersticas que llamamos atributos o caractersticas asociadas a esos objetos: nombre, tipo, visibilidad, definicin. Los atributos de los diferentes objetos que aparecen en el texto fuente se van almacenando durante el anlisis en una estructura de datos denominada tabla de datos (tabla de smbolos), y as, poderlos utilizar durante la etapa de ejecucin. La accin mediante en la cual a un objeto se le asocia un determinado atributo o caracterstica se llama ligadura, esta ligadura puede ser de dos tipos: esttica (ligadura temprana) se hace a nivel de anlisis, ligadura en tiempo de compilacin y, dinmica (ligadura tarda) se hace a nivel de sntesis, ligadura en tiempo de ejecucin. PROGRAM ejercicio; identificador a b c VAR a,b:integer; tipo integer integer real c: real; visible ejercicio ejercicio ejercicio BEGIN definida si si si READ (b,c); a:=b+c; END. El anlisis semntico se realiza normalmente de forma simultnea al anlisis sintctico. Siguiente ejemplo:
<sintaxis> PROGRAM <decl_cte> id ; <parte_decl> <decl_var> VAR <una_var> ; <mas_var> <una_sent> <sent_read> Alm_tipo ( id) , alm_tipo (id) <mas_id> : <tipo>.tipo READ ( <list_val> ) <mas_id> integer Dec (id) <mas_id> visible , Dec (id) <mas_id> visible <sent_asig> visible Id.tipo= <expr>.tipo <expr>.tipo <term>.tipo <fact>.tipo <opdo>.tipo real Obt_tipo (id) + <term>.tipo <fact>.tipo <opdo>.tipo Obt_tipo (id) <mas_sent> <parte_ejec> BEGIN <list_sent> END .

<decl_tip>

<una_var> ; <mas_var>

Alm_tipo (id) <mas_id> : <tipo>.tipo

Caractersticas a cumplir por los objetos Compatibilidad de tipos Existen lenguajes fuertemente tipados como Pascal y otros como C que dan una mayor flexibilidad A continuacin se presentan unas tablas de compatibilidad del lenguaje Pascal entre los operandos ligados por operadores : +.-,*,<,>,=,:=,DIV.. +,-,* integer real DIV integer real integer integer real integer integer integer real real real real integer integer / integer real <,>,= integer real integer real real integer boolean error real real real real error Boolean

Compatibilidad entre los objetos ligados por el operador de asignacin := variable integer real := expresin Integer (real incompatible) Integer , real puede hacerse: por nombre o por

- La compatibilidad en los lenguajes con estructura de bloques estructura TYPE tamao=array [1..10] of integer VAR u,v: tamao; x,y:array [1..10] OF integer

u=v compatibilidad por nombre ; u=x compatibilidad por estructura Otras de las caractersticas de los objetos es su existencia y visibilidad: En los lenguajes con estructuras de bloques como lo son: Algol, Pascal, C, es necesario conocer donde puede estar un objeto, que condiciones tiene y donde se puede usar. Para ello es importante conocer las reglas de mbitos del lenguaje. En los lenguajes con estructuras de bloques, se llama lnea de mbito a una sucesin de bloques anidados Un objeto es visible en su ambiente local y global de la lnea de mbito de dicho bloque, se denomina (1 regla de mbito) En otras palabras, en un bloque son visibles los objetos locales declarados en l y los objetos declarados en los bloques de su misma lnea de mbitos que son exteriores a l. PROGRAM P; VAR r, s : integer; PROCEDURE Q ( q1,q2); VAR t, u: real; .. PR0CEDURE R( r1,r2,); VAR.. v, x: real; .. PROCEDURE S ( s1,s2); VAR y, z: real; P r, s variables,. Q, S subprogramas visible los objetos locales a P Q t, u var iables , R subprograma q1,q2..parmetros visible los objetos locales a P y Q R v, x var iables, r1, r2,..parmetros visible los objetos locales a P , Q y R S y, z variables, s1, s2,..parmetros visible los objetos locales a P y S

Desde el subprograma S no se puede hacer uso de los objetos locales de Q, pero si se puede hacer una llamada a Q. El valor de referencia que toma la existencia de un objeto dentro de un bloque, parte desde el interior hacia el exterior de su lnea de mbito se llama (2 regla de mbito) 7

PROGRAM P; VAR x, y : integer; . PROCEDURE Q ( q1,q2); VAR x, y: real; .. PROCEDURE R( r1,r2,); VAR x, y: boolean; . PROCEDURE S ( s1,s2); VAR x, y: char;

.integer .real. ..boolean char

En los lenguajes con estructuras de bloques se pueden emplear el mismo nombre para definir objetos distintos declarados en bloques distintos resolviendo la regla entre uso y declaracin. Se puede provocar la inaccesibilidad a un objeto haciendo que otro objeto declarado en un bloque mas interno, en su misma lnea de mbito, tenga su mismo nombre Caractersticas de los objetos subprogramas (fundamentales en los lenguajes con estructuras de bloques) - conocer nmero de parmetros - orden de colocacin - coincidencia de tipos - coincidencia de parmetros actuales con formales - definicin de prototipo - .. Semntica dinmica Semntica dinmica se refiere al significado propiamente dicho de las estructuras (sentencias) que conforman el texto fuente en tiempo de ejecucin. PROGRAM ejercicio; VAR a,b:integer; c: real; BEGIN READ (b, c); a:=b+c; END. La semntica de las sentencias (estructuras) del ejemplo fuente anterior READ (b,c); a:=b+c; ser: Toma el valor del tipo de variable del buffer de entrada y lo pone en la direccin de memoria b y c ; INPUT b INPUT c Coloca en la pila, la direccin de la variable a la que se va a llevar el resultado PUSHA a, lleva a la pila el valor de la direccin de la variable b PUSHA b LOAD, hacer lo mismo para la variable c lleva a la pila el valor de la direccin de la variable c PUSHA c LOAD , una vez colocados los dos valores en la pila se suman y dejando el resultado en la pila ADD y se almacena en la direccin de memoria a STORE. si queremos sacar el resultado, OUTPUT a { INPUT b INPUT c PUSHA a PUSHA b LOAD PUSHA c LOAD ADD STORE OUTPUT a} Con el conocimiento de la semntica dinmica del lenguaje es posible resolver el problema de separacin semntica que existe entre el lenguaje de alto nivel y el lenguaje mquina , para su resolucin se emplean los procesadores de lenguaje: traductores como compiladores o intrpretes.

6.4 Aplicacin de las gramtica de atributos en la especificacin semntica de un LP La sentencia de decisin de un lenguaje L se define con las siguientes reglas sintcticas: <sent-decide> ::= DECIDE <tipo-decide> <lista-casos> END-DECIDE <tipo-decide> ::= <por-condicin> | <por-valor> <por-condicin> ::= CONDITION <por-valor> ::= VALUE OF id <lista-casos> ::= <un-caso> | <un-caso> <lista-casos> <un-caso> ::= <exp> : <sentencia> ; <exp> ::= <trmino> | <trmino> <operador-1> <exp> <trmino> ::= <factor> | <factor> <operador-2> <trmino> <factor> ::= id | cte-entera | cte-real | cte-lgica | ( <exp> ) <operador-1> ::= < | > | = | <> <operador-2> ::= + | - | * | / | AND | OR <sentencia> ::= <sent-decide> | La semntica asociada a dicha sentencia establece las siguientes reglas: Los identificadores pueden ser de tipo entero, real o lgico, incluido el que aparece en la regla <por-valor>. Todas las operaciones de tipo relacional <operador-1> pueden realizarse entre operandos de tipo entero y/o real (no tienen por qu ser iguales), siendo el resultado de tipo lgico. Las operaciones de suma, resta, multiplicacin y divisin pueden realizarse entre operandos de tipo entero y/o real, siendo el resultado de tipo real. Excepcionalmente, en el caso de que ambos operandos sean enteros y el operador no sea la divisin, el resultado es entero. Las operaciones AND y OR slo pueden realizarse entre operandos de tipo lgico, siendo ste el tipo del resultado. En el caso de la sentencia decide por condicin, todas las expresiones que componen sus casos tienen que ser de tipo lgico, mientras que en el caso de la sentencia decide por valor el tipo tiene que ser idntico al del identificador de cuyo valor se trata. Construir la gramtica de atributos necesaria para la especificacin semntica de las anteriores restricciones, indicando claramente cules son los atributos ligados a cada smbolo de la sintaxis y si son heredados o sintetizados. La sintaxis no puede ser modificada en ningn caso. Se utilizar el atributo tipo para realizar todas las comprobaciones de tipo pedidas en el enunciado. Y adems el atributo clase para diferenciar el tipo de operador considerado, ya que para operadores que estn en la misma regla sintctica se aplica diferente semntica. <sent-decide> ::= DECIDE <tipo-decide> <lista-casos> END-DECIDE { IF <tipo-decide>.tipo <> <lista-casos>.tipo THEN error_semantico ( ) } <tipo-decide> ::= <por-condicin> {<tipo-decide>.tipo := logico } <tipo-decide> ::= <por-valor> {<tipo-decide>.tipo := <por-valor>.tipo } <por-condicin> ::= CONDITION <por-valor> ::= VALUE OF id {<por-valor>.tipo := id.tipo } <lista-casos> ::= <un-caso> {<lista-casos>.tipo := <un-caso>.tipo } <lista-casos> ::= <un-caso> <lista-casos> { IF <un-caso>.tipo <> <lista-casos2>.tipo THEN error_semantico ( ) ELSE <lista-casos1>.tipo := <lista-casos2>.tipo } <un-caso> ::= <exp> : <sentencia> ; {<un-caso>.tipo := <exp>.tipo} <exp> ::= <trmino>{<exp>.tipo := <termino>.tipo } <exp> ::= <trmino> <operador-1> <exp> { IF ((<termino>.tipo = entero) OR (<termino>.tipo = real)) AND ((<exp2>.tipo = entero) OR (<exp2>.tipo = real)) THEN <exp1>.tipo := logico ELSE error_semantico ( ) } 9

<operador-2> ::= AND{<operador-2>.clase := and } <operador-2> ::= OR {<operador-2>.clase := or } <sentencia> ::= <sent-decide> |
<sent_case>::=CASE identificador OF <lista_alternativas> END <lista_alternativas>::=<alternativa><resto_alternativas> <resto_alternativas>::=<alternativa><resto_alternativas> | <alternativa>::=<constantes>:<sentencia>; <constantes>::= <cte>, <constantes> |<cte> <cte>::=cte_ent | cte_car |identificador

<trmino> ::= <factor>{<termino>.tipo := <factor>.tipo} <termino> ::= <factor> <operador-2> <trmino> {CASE <operador-2>.clase OF and,or : IF (<factor>.tipo = logico) AND (<termino2>.tipo = logico) THEN <termino1>.tipo := logico ELSE error_semantico ( ) suma, resta, producto :IF (<factor>.tipo = logico) OR (<termino2>.tipo = logico) THEN error_semantico ( ) ELSE IF (<factor>.tipo = entero) AND (<termino2>.tipo = entero) THEN <termino1>.tipo := entero ELSE <termino1>.tipo := real division :IF (<factor>.tipo = logico) OR (<termino2>.tipo = logico) THEN error_semantico ( ) ELSE <termino1>.tipo := real } <factor> ::= id {<factor>.tipo := id.tipo } <factor> ::= cte-entera {<factor>.tipo := entero } <factor> ::= cte-real { <factor>.tipo := real } <factor> ::= cte-lgica{ <factor>.tipo := logico } <factor> ::= | ( <exp> ) {<factor>.tipo := <exp>.tipo } <operador-1> ::= < | > | = | <> <operador-2> ::= + {<operador-2>.clase := suma } <operador-2> ::= - {<operador-2>.clase := resta } <operador-2> ::= * {<operador-2>.clase := producto} <operador-2> ::= / {<operador-2>.clase := division }

- Dada la siguiente sintaxis que define la sentencia case de un lenguaje L

Donde <sentencia> se refiere a cualquier sentencia del lenguaje de programacin L y no es necesario definirla para este ejercicio. Ejemplo: CASE car OF a:sent1; b,c:sent2; Letra,z:sent3; END La semntica de la sentencia CASE obliga a que el tipo de todas las constantes utilizadas en las diferentes alternativas ha de ser igual al del identificador selector (el que aparece a continuacin de la palabra reservada CASE). A partir de la gramtica anterior y sin modificarla, obtener una gramtica de atributos que realice dichas comprobaciones, dando un mensaje de error en la produccin donde se detecte un error semntico. Explicar para qu se utiliza cada uno de los atributos utilizados y si son heredados o sintetizados. <sent_case> ::= CASE identificador OF <lista_alternativas> END { <lista_alternativas>.tipo := identificador.tipo } <lista_alternativas> ::= <alternativa> <resto_alternativas> 10

{ <alternativa>.tipo := <lista_alternativas>.tipo; }

<resto_alternativas>.tipo := <lista_alternativas>.tipo

<resto_alternativas> ::= <alternativa> <resto_alternativas> { <alternativa>.tipo:=<resto_alternativas1>.tipo; <resto_alternativas1>.tipo} <resto_alternativas> ::= { (* Esta produccin no tiene semntica asociada *) }

<resto_alternativas2>.tipo:=

<alternativa> ::= <constantes> : <sentencia> { <constantes>.tipo := <alternativa>.tipo } <constantes> ::= <cte> , <constantes> { <cte>.tipo := <constantes1>.tipo; <constantes2>.tipo := <constantes1>.tipo } <constantes> ::= <cte> { <cte>.tipo := <constantes>.tipo } <cte> ::= cte_ent { IF <cte>.tipo <> ENTERO THEN error(TIPOS_INCOMPATIBLES) } <cte> ::= cte_car { IF <cte>.tipo <> CARACTER THEN error(TIPOS_INCOMPATIBLES) } <cte> ::= identificador { IF <cte>.tipo <> identificador.tipo THEN error(TIPOS_INCOMPATIBLES) } - Dada la siguiente gramtica de expresiones aritmticas: <Expresin> ::= <Expresin> + <Trmino> | <Expresin> - <Trmino> | <Trmino> <Trmino> ::= <Factor> * <Trmino> | <Factor> / <Trmino> | <Factor> <Factor> ::= <Unario><Operando> <Unario> ::= + | - | <Operando> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 Se pretende comprobar que no haya ninguna divisin por cero. Para ello, a partir de la gramtica anterior y sin modificarla, obtener una gramtica de atributos que visualice un mensaje de error en el mismo momento en que detecte alguna divisin por cero (no es necesario propagarlo hasta la raz). Para ello, se deber utilizar nicamente un atributo, que ser sintetizado y tomar valores lgicos (true y false). Elegimos el atributo de tipo booleano es_cero. Cuando valga true para algn smbolo significar que la evaluacin de la expresin correspondiente da como resultado 0. De este modo podremos controlar cundo se produce una divisin por 0. La gramtica de atributos resultante es: <Operando> ::= 0 { <Operando>.es_cero := true } <Operando> ::= 1 | 2 | ... | 9 { <Operando>.es_cero := false (* para las 9 prods. *) } <Factor> ::= <Unario> <Operando> { <Factor>.es_cero := <Operando>.es_cero } <Trmino> ::= <Factor> { <Trmino>.es_cero := <Factor>.es_cero } <Trmino> ::= <Factor> * <Trmino> { <Trmino1>.es_cero := <Factor>.es_cero OR <Trmino2>.es_cero } - La sintaxis de las expresiones utilizadas en diferentes sentencias es la siguiente: <Expresin> ::= <Expresin> + <Trmino> | <Expresin> * <Trmino> | <Trmino> <Trmino> ::= <Unario> <Operando> <Unario> ::= # | <Operando> ::= Cte_ent | identificador | <Vector> | (<Expresin>) <Vector> ::= { <Componentes> } <Componentes> ::= cte_ent , <Componentes> | cte_ent 11

Donde: Identificador es una variable de tipo entero o de tipo vector con un tamao determinado en la declaracin, segn se vio en el ejemplo inicial. Vector se refiere a un vector concreto, con unos valores. Por ejemplo: {1, 2, 9} # es la operacin longitud de un vector, que es un valor entero. As, expresiones sintcticamente correctas podran ser las siguientes: t + { 3, 4, 5 } t + { 3, 4, 5, 6, 7 , 8 } 3*t + ( 9 * { 4, 5, 6}) 5 + (#t * x) Se desea aadir las comprobaciones semnticas oportunas para las operaciones: Operacin +: Se puede establecer entre dos operandos del mismo tipo (enteros o vectores), dando un resultado de ese tipo. En caso de establecerse entre dos vectores, ambos deben tener el mismo nmero de componentes, dando como resultado un vector con ese nmero de componentes. As, la expresin la segunda expresin de los ejemplos: t + { 3, 4, 5, 6, 7, 8} no sera correcta, ya que se est sumando un vector de 3 elementos ( t ) con otro de 6 elementos. Operacin *: Se puede realizar entre dos operandos enteros, dando como resultado otro entero; pero no entre dos vectores. Tambin se puede aplicar entre un entero y un vector (en este orden), dando como resultado un vector con el mismo nmero de componentes. Por ejemplo, 3*{1,2} dara como resultado el vector {3,6} Operacin # (unario): Unicamente se puede aplicar sobre un vector, dando como resultado la longitud del mismo, que es un valor entero. Se pide: Tomando como punto de partida la gramtica de expresiones propuestas y sin modificarla, obtener una gramtica de atributos que realice las comprobaciones semnticas propuestas. Indicar previamente los atributos que se van a utilizar, su funcionalidad y si son heredados o sintetizados. Se utilizarn los siguientes atributos sintetizados: Tipo: para determinar si se trata de un entero o de un vector. Long: nmero de componentes que tiene un vector. Clase: para determinar si hay operador unario. <Expresin> ::= <Expresin> + <Trmino> { IF <Expresin2>.tipo <> <Trmino>.tipo THEN error_semantico ELSE IF <Expresin2>.tipo = entero THEN <Expresin1>.tipo := entero ELSE IF <Expresin2>.long = <Trmino>.long THEN <Expresin1>.tipo := vector ; <Expresin1>.long := <Expresin2>.long END ELSE error_semantico } <Expresion> ::= <Expresin> * <Trmino> { IF <Expresin2>.tipo = vector THEN error_semantico ELSE IF <Trmino>.tipo = entero THEN <Expresin1>.tipo := entero ELSE BEGIN <Expresin1>.tipo := vector ; <Expresin1>.long := <Trmino>.long END } <Expresin> ::= <Trmino> { <Expresin>.tipo := <Trmino>.tipo ; IF <Trmino>.tipo = vector THEN <Expresin1>.long := <Trmino>.long } <Trmino> ::= <Unario> <Operando> { CASE <Unario>.clase OF almohadilla : IF <Operando>.tipo = vector THEN <Trmino>.tipo := entero ELSE error_semantico; 12

END } <Unario> ::= # { <Unario>.clase := almohadilla } <Unario> ::= { <Unario>.clase := vacio } <Operando> ::= Cte_ent { <Operando>.tipo := entero } <Operando> ::= identificador { <Operando>.tipo := identificador.tipo ; IF identificador.tipo = vector THEN <Operando>.long := identificador.long <Operando> ::= <Vector> { <Operando>.tipo := vector <Operando>.long := <vector>.long } <Operando> ::= (<Expresin>) { <Operando>.tipo := <Expresin>.tipo ; IF <Expresin>.tipo = vector THEN <Operando>.long := <Expresin>.long <Vector> ::= { <Componentes> } { <Vector>.long := <Componentes>.long } <Componentes> ::= cte_ent , <Componentes> { <Componentes1>.long := 1 + <Componentes2>.long } <Componentes> ::= cte_ent { <Componentes>.long := 1 } - Dada la siguiente gramtica BNF: <Expresin> ::= <Expresin> + <Trmino> | <Expresin> - <Trmino> | <Trmino> <Trmino> ::= <Trmino> * <Factor> | <Factor> <Factor> ::= - <Cifra> | <Cifra> <Cifra> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

vacio : BEGIN <Trmino>.tipo := <Operando>.tipo ; IF <Operando>.tipo = vector THEN <Trmino>.long := <Operando>.long END

Se quiere conocer el nmero de veces en que aparece el operador binario - inmediatamente seguido por el operador unario -. Por ejemplo: 3--4*8+6--8 Se ha encontrado 2 veces 8*6--5 Se ha encontrado 1 vez Se pide: Partiendo de la gramtica anterior y sin modificarla, obtener una gramtica de atributos que obtenga esta informacin. Previamente se deber indicar los atributos utilizados, su funcionalidad y si son heredados o sintetizados. Dos atributos sintetizados: num para calcular el nmero de apariciones del menos unario con el binario. negativo para controlar si un trmino empieza por un menos unario <Expresin> ::= <Expresin> + <Trmino> { <Expresin1>.num := <Expresin2>.num }

<Expresin> ::= <Expresin> - <Trmino> { IF <Trmino>.negativo THEN <Expresin1>.num := <Expresin2>.num + 1 ELSE <Expresin1>.num := <Expresin2>.num

} 13

<Expresin> ::= <Trmino> { <Expresin>.num := 0 } <Trmino> ::= <Trmino> * <Factor> { <Trmino1>.negativo := <Trmino2>.negativo } <Trmino> ::= <Factor> { <Trmino1>.negativo := <Factor>.negativo <Factor> ::= - <Cifra> { <Factor>.negativo := true <Factor> ::= <Cifra> { <Factor>.negativo := false } } }

Ejercicios propuestos - Sea la siguiente semntica en BNF, que representa la declaracin de subprogramas en un lenguaje de programacin L: <subp>::= PROCEDURE identificador (<parametros>); <decl_variables> <parte_ejec> <parametros>::= <param>;<parametros> | <param> <param>::= <clase_par> identificador : <tipo> <clase_par>::= VAR | <tipo>::= ENTERO | REAL | LOGICO <decl_variables>::= <lista_var>; <decl_variables> | <lista_var>::= VAR <lista_id>: <tipo> <lista_id>::= identificador, <lista_id> | identificador <parte_ejec>::= ... A la vez que se realiza el anlisis de una declaracin de subprogramas se pretende obtener una informacin: el tamao que ocuparn los datos durante la ejecucin del subprograma. Estos datos estn formados por parmetros y variables globales, de ah que no interese para este problema la sintaxis de la parte ejecutable. El tamao de cada uno de los datos es el siguiente: - Para las variables ha de considerarse nicamente el tipo de las mismas. As una variable entera ocupa dos posiciones, una real cuatro y una lgica una. - Para los parmetros hay que diferenciar entre parmetro por valor y parmetro variable (por VAR). Los primeros tienen una ocupacin igual que lo expuesto para las variables, mientras que los segundos ocupan siempre cuatro posiciones, independientemente del tipo, ya que al tratarse de una referencia lo que hay que guardar en memoria es siempre una direccin, no el dato. Por ejemplo: PROCEDURE ejemplo(x:ENTERO; VAR y: LOGICO); 14

VAR aux1,aux2, aux3: REAL; VAR cont1: LOGICO; Ocupacin de variables = 4 (aux1) + 4 (aux2) + 4 (aux3) + 1 (cont1) = 13 Ocupacin de parmetros = 2 (x) + 4 (y) = 6 Ocupacin total de los datos en tiempo de ejecucin = 19 posiciones Partiendo de la gramtica propuesta y sin modificar ninguna produccin, obtener una gramtica de atributos que calcule el tamao total de los datos en memoria. Indicar previamente los atributos que se van a utilizar, qu funcionalidad tiene cada uno y si son sintetizados o heredados. - Con objeto de que el compilador pueda generar cdigo de forma ptima, se desea saber qu partes de la expresin son constantes, para as reflejar en el cdigo generado el valor de dicha constante, en lugar de reflejar operaciones entre constantes. Por ejemplo, si se tiene la expresin 3-2+aux, donde aux es un identificador de variable, se generar cdigo para 1+aux, ya que la subexpresin correspondiente 3-2 habr sido marcada como una constante. Si en el mismo ejemplo, aux fuera un identificador de constante con valor 5, se generar cdigo para 6, ya que la totalidad de la expresin habr sido marcada como constante. Se pide: A partir de la gramtica anterior y sin modificarla, obtener una gramtica de atributos en la que todos los no terminales del rbol quedarn decorados con un atributo que indique si la subexpresin que hay debajo es constante o variable. Adems, en caso de ser constante deber figurar otro atributo que contenga el valor de la constante. As por ejemplo, si se tiene la expresin 3-2+aux, donde aux es una variable, quedar marcado en el rbol que 3-2 es constante de valor 1, mientras que 3-2+aux es variable. - Se pretende definir un lenguaje de programacin L muy simple al estilo de Pascal. En dicho lenguaje es posible realizar declaraciones de constantes y de variables. Si bien, los nicos tipos permitidos para las mismas son dos: numrico y cadena. Las operaciones que se consideran necesarias definir son la suma ( + ) y el producto ( * ) entre operadores de tipo numrico; y la concatenacin ( + ) para cadenas. Se ha visto la conveniencia de definir sentencias del tipo mientras, con lo que se plantea el problema de cmo definir las expresiones lgicas que controlen estas sentencias. Como el uso que se va a hacer del lenguaje es para programas muy concretos y muy sencillos, se ha decidido que es suficiente con utilizar un operador relacional en dichas expresiones, con lo que no se incluyen en el lenguaje los operadores lgicos (por tanto la expresin lgica tendr una nica condicin). En conclusin, la gramtica propuesta para las sentencias mientras es la siguiente: <sent_mientras> ::= MIENTRAS <exp_logica> HACER <sentencia> <exp_logica> ::= <exp_simple> <op_relacional> <exp_simple> <op_relacional> ::= < | > | <= | >= | = | <> <exp_simple> ::= <exp_simple> + <operando> | <exp_simple> * <operando> | <operando> <operando> ::= cte_numerica | cte_cadena | identificador | ( <exp_simple> ) Se plantean ahora una serie de problemas relativos a la semntica que son los que se pide solucionar en este ejercicio: En primer lugar, las expresiones deben ser correctas, es decir, el operador + se podr utilizar entre operandos del mismo tipo (numrico o cadena), mientras que el operador * se podr utilizar exclusivamente entre operandos numricos. De igual manera, los operadores relacionales slo tienen sentido cuando se utilizan entre operandos del mismo tipo (numrico o cadena). Adems, se cree conveniente tambin comprobar que en la expresin lgica utilizada exista algn identificador de variable. Por ejemplo, la expresin a > 3 * b ser correcta si al menos un identificador (a o b) ha sido declarado como variable, e incorrecta si ambos han sido declarados como constantes (una comparacin de constantes carece de sentido).

15

Se pide: a) Qu informacin (atributos) es necesario saber de cada identificador declarado en el programa para poder realizar las comprobaciones anteriores ? b) Definir a partir de la sintaxis dada una gramtica de atributos que realice dichas comprobaciones, dejando muy claro a qu regla sintctica pertenece cada accin semntica. Justificar tambin el tipo de los atributos utilizados (heredados o sintetizados) Son necesarios dos atributos: Tipo numerico o cadena Clase- constante o variable Ambos atributos son sintetizados <sent_mientras> ::= MIENTRAS <exp_logica> HACER <sentencia <exp_logica> ::= <exp_simple> <op_relacional> <exp_simple> { IF <exp_simple1>.tipo <><exp_simple2>.tipo THEN error semantico IF <exp_simple1>.clase = constante AND <exp_simple2>.clase = constante THEN error semantico } <exp_simple> ::= <exp_simple> + <operando> { IF <exp_simple2>.tipo<><operando>.tipo THEN error semantico ELSE<exp_simple1>.tipo:= <exp_simple2>.tipo IF <exp_simple2>.clase= variable OR <operando>.clase = variable THEN <exp_simple1>.clase = variable ELSE<exp_simple1>.clase=constante

} <exp_simple> ::= <exp_simple> * <operando>

IF <exp_simple2>.tipo<>numerico OR <operando>.tipo <> numerico THEN error semantico ELSE<exp_simple1>.tipo:= numerico IF <exp_simple2>.clase= variable OR <operando>.clase = variable THEN <exp_simple1>.clase = variable ELSE<exp_simple1>.clase=constante } <exp_simple> ::= <operando> {<exp_simple>.tipo := <operando>.tipo <exp_simple>.clase := <operando>.clase } <operando> ::= cte_numerica { <operando>.tipo::= numerico <operando>.clase:= constante <operando> ::= cte_cadena { <operando>.tipo::= cadena <operando>.clase:= constante <operando> ::= identificador { <operando>.tipo::= identificador.tipo <operando>.clase:= variable <operando> ::= (<exp_simple>) { <operando>.tipo::= (<exp_simple>.tipo <operando>.clase:= <exp_simple>.clase

16

<expresin>::=<termino><resto_expresin> <resto_expresion>::=<op1> termino>><resto_expresin> | <termino>::=<factor><resto_termino> <resto_termino>::=<op2> <factor><resto_termino> | <factor>::=unario><operando> <operando>::=identificador Op1, op2 | cte_ent | ( <expresin> ) entero <op2> ::= * | / Real <op1> ::= + | <unario>::= + | - |

entero entero real

real real real

La semntica asociada a estas reglas de produccin debe cumplir con las siguientes condiciones: Las operaciones solo se podrn realizar con tipos numricos (entero o real). El resultado ser siempre real a no ser que ambos sean enteros en cuyo caso el resultado ser entero <expresin>::=<termino><resto_expresin> { IF <reto_exprezin>.existe =T THEN {IF (<resto_expresion>.tipo<> entero ) AND (<resto_expresin>.tipo <>real OR (<termino>.tipo<>real) AND(<termino>.tipo<>entero THEN error semntico ELSE IF ((<resto_expresin>.tipo= entero AND (<termino>.tipo=entero)) THEN ((<expresin1>.tipo= entero ELSE((<expresin1>.tipo= real } ELSE <expresin>.tipo= <termino>.tipo <resto_expresion>::=<op1> termino>><resto_expresin> { IF <reto_expresin>.existe =T THEN {IF (<resto_expresion>.tipo<> entero ) AND (<resto_expresin>.tipo <>real OR (<termino>.tipo<>real) AND(<termino>.tipo<>entero THEN error semntico ELSE IF ((<resto_expresin>.tipo= entero AND (<termino>.tipo=entero)) THEN ((<expresin1>.tipo= entero ELSE((<expresin1>.tipo= real } ELSE {<resto_expresin1>.tipo= <termino>.tipo; <resto_expresin1>.existe=T } <reto_expresin>::= {<resto_expresion1>.existe=F} <termino>::=<factor><resto_termino> { IF <reto_termino>.existe =T THEN {IF (<resto_termino>.tipo<> entero ) AND (<resto_termino>.tipo <>real OR (<factor>.tipo<>real) AND(<factor>.tipo<>entero THEN error semntico ELSE IF ((<resto_termino>.tipo= entero AND (<factor>.tipo=entero)) THEN ((<termino>.tipo= entero ELSE((<termino>.tipo= real } ELSE <termino>.tipo= <factor>.tipo } <resto_termino>::=<op2> <factor><resto_termino> { IF <reto_termino2>.existe =T THEN 17

{IF (<resto_termino2>.tipo<> entero ) AND (<resto_termino2>.tipo <>real OR (<factor>.tipo<>real) AND(<factor>.tipo<>entero THEN error semntico ELSE IF ((<resto_termino2>.tipo= entero AND (<factor>.tipo=entero)) THEN ((<resto_termino1>.tipo= entero ELSE((<resto_termino1>.tipo= real } ELSE <resto_termino1>.tipo= <factor>.tipo; <resto_termino1>.existe=T

<resto_termino>::= { <resto_termino>.existe::= F } <factor>::=<unario><operando> { <factor>.tipo::=<operando>.tipo} <operando>::=identificador {<operandor>.tipo = obtenerTipo (identificador) } <operando>::= cte_ent {<operandor>.tipo = obtenerTipo (cte) } <operando>::= (<expresin>) {<operando>.tipo ::= <expresin>.tipo }

18

Vous aimerez peut-être aussi