yylval voor gevorderden: %unionMomenteel moeten we *het* type van yylval definiëren. Dit is echter
niet altijd toepasselijk. Er zijn tijden dat we meerdere datatypen moeten
kunnen verwerken. Terugkerend naar onze hypothetische thermostaat, willen we
misschien een verwarming die we willen beheersen uitkiezen, als volgt:Verwarming hoofdgebouw
`hoofdgebouw' verwarming geselecteerd
doel temperatuur 23
`hoofdgebouw' verwarming doel temperatuur nu 23Hiervoor moet yylval een union wezen, die zowel strings als integers kan
bevatten - maar niet tegelijk.Bedenk dat we YACC eerder verteld hebben welk type yylval was door YYSTYPE
te definiëren. We zouden YYSTYPE op deze manier als union kunnen
definiëren, maar YACC heeft hier een gemakkelijker methode voor: het
%union statement.Gebaseerd op Voorbeeld 4, schrijven we nu de YACC grammatica van Voorbeeld
7. Eerst de intro:
%token TOKVERWARMING TOKWARMTE TOKDOEL TOKTEMPERATUUR
%union
{
int number;
char *string;
}
%token <number> TOESTAND
%token <number> NUMMER
%token <string> WOORDWe definiëren onze union, die alleen een nummer en een string bevat.
Dan leggen we YACC met een uitgebreide %token syntax uit welk deel van de
union ieder token moet benaderen.In dit geval laten we het TOESTAND token een integer gebruiken, net als zonet.
Hetzelfde geldt voor het NUMMER token, dat we gebruiken om temperaturen te
lezen.Nieuw is het WOORD token, dat gedeclareerd is om een string te gebruiken.Het lexerbestand verandert ook een beetje:
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
%}
%%
[0-9]+ yylval.number=atoi(yytext); return NUMMER;
verwarming return TOKVERWARMING;
warmte return TOKWARMTE;
aan|uit yylval.number=!strcmp(yytext,"aan"); return TOESTAND;
doel return TOKDOEL;
temperatuur return TOKTEMPERATUUR;
[a-z0-9]+ yylval.string=strdup(yytext);return WOORD;
\n /* negeer einde regel */;
[ \t]+ /* negeer whitespace */;
%%
Zoals je ziet benaderen we de yylval niet meer direct, we voegen een suffix
toe om aan te geven welk deel we willen benaderen. In de YACC grammatica
hoeft dat echter niet, want YACC doet het voor ons:heater_select:
TOKVERWARMING WOORD
{
printf("\tVerwarming '%s' geselecteerd\n",$2);
heater=$2;
}
;Vanwege de %token declaratie hierboven kiest YACC automatisch het `string'
lid uit onze union. Merk ook op dat we een kopie van $2 opslaan, die later
gebruikt wordt om de gebruiker te vertellen naar welke verwarming hij
commando's stuurt:target_set:
TOKDOEL TOKTEMPERATUUR NUMMER
{
printf("\tTemperatuur van verwarming '%s' ingesteld op %d\n",heater,$3);
}
;
Lees voor meer details example7.y.