%union
y a las especificaciones de
tipo entre símbolos menor mayor (<tipo>
) en declaraciones token
y
%type
no son usadas por yapp
. Estas declaraciones son
necesarias cuando el código de las acciones semánticas
se escribe en C
como es el caso de yacc y bison.
Sigue un ejemplo de programa yacc
/bison
que usa declaraciones %union
y de tipo para los atributos:
1 %{ 2 #include <stdio.h> 3 4 #define CLASE(x) ((x == 1)?"global":"local") 5 #define TIPO(x) ((x == 1)?"float":"integer") 6 %} 7 8 %union { 9 int n; /* enumerado */ 10 char *s; /* cadena */ 11 } 12 13 %token <n> FLOAT INTEGER 14 %token <n> GLOBAL 15 %token <n> LOCAL 16 %token <s> NAME 17 %type <n> class type 18 19 %%La declaración
%union
de la línea 8 indica que los atributos
son de dos tipos: enteros y punteros a caracteres.
El nombre del campo es posteriormente usado en las
declaraciones de las líneas 13-17 para indicar el tipo
del atributo asociado con la variable o con el terminal.
Así, la declaración de la línea 13 indica
que los terminales FLOAT
e INTEGER
son de tipo entero, mientras que la declaración de la línea 16 nos
dice que el terminal NAME
es de tipo cadena.
29 class 30 : GLOBAL { $$ = 1; } 31 | LOCAL { $$ = 2; } 32 ; 33 34 type 35 : FLOAT { $$ = 1; } 36 | INTEGER { $$ = 2; } 37 ;La información proveída sobre los tipos permite a
yacc
introducir automáticamente en el código C
producido
los typecasting o ahormados
para las asignaciones de las líneas 30-31 y 35-36. Obsérve que
en yacc
el atributo de la variable en la parte izquierda
se denota por $$
.
Otra diferencia entre yacc
y yapp
es que en yacc
los
atributos de la parte derecha no constituyen un vector, denotándose
por $1
, $2
, $3
...
En ocasiones yacc
no puede determinar el tipo de un atributo.
En particular cuando se habla del atributo asociado con una acción
intermedia, ya que esta no tiene variable sintáctica asociada
explícitamente o bien cuando se habla de los atributos
de símbolos que están a la izquierda de la reducción actual
(véase la sección 8.28). Los atributos de símbolos
a la izquierda de la producción actual se denotan en yacc
por números
no positivos $0
, $-1
, $-2
....
En estos casos
el programador deberá especificar explícitamente el tipo del
atributo usando la notación $<tipo>#
. Donde tipo
es
uno de los campos de la union
y #
es el numeral
del símbolo correspondiente:
39 namelist 40 : NAME { printf("%s de clase %s, tipo %s\n",$1,CLASE($<n>-1),TIPO($<n>0)); } 41 | namelist ',' NAME 42 { printf("%s de clase %s, tipo %s\n",$3,CLASE($<n>-1),TIPO($<n>0)); } 43 ; 44 %%