2009-12-05 4 views
14

Quel est le but de l'union dans le fichier yacc? Est-il directement lié à yylval dans le fichier flex? Si vous n'utilisez pas yylval, vous n'avez pas besoin d'utiliser union?yylval et union

Répondre

11

La déclaration %union modifie le type yylval.

Le bison manuel explains:

Dans un analyseur ordinaire (non réentrants), la valeur sémantique du jeton doit être stocké dans la variable globale yylval. Lorsque vous utilisez un seul type de données pour les valeurs sémantiques, yylval a ce type. Ainsi, si le type est int (par défaut), vous pouvez écrire ceci dans yylex:

... 
yylval = value; /* Put value onto Bison stack. */ 
return INT;  /* Return the type of the token. */ 
... 

Lorsque vous utilisez plusieurs types de données, le type de yylval est une union fait de la déclaration %union (voir la section La Collection de types de valeur). Ainsi, lorsque vous stockez la valeur d'un jeton, vous devez utiliser le membre approprié de l'union. Si la déclaration %union ressemble à ceci:

%union { 
    int intval; 
    double val; 
    symrec *tptr; 
} 

alors le code yylex pourrait ressembler à ceci:

... 
yylval.intval = value; /* Put value onto Bison stack. */ 
return INT;   /* Return the type of the token. */ 
... 
21

Le but du union est de permettre le stockage différents types d'objets dans les noeuds émis par flex.

Pour expliquer mieux vous pouvez par exemple:

%union 
{ 
    int intValue; 
    float floatValue; 
    char *stringValue; 
} 

dans .y si vous voulez fournir un soutien de base pour int, float et string types. Que pouvez-vous faire avec ça?

Deux choses:

D'abord, vous pouvez définir automatiquement les valeurs de droite lors de la génération de jetons. Pensez à .l fichier de l'exemple précédent, vous pouvez:

[a-zA-Z][a-zA-Z0-9]* { 
yylval.stringValue = strdup(yytext); 
return IDENTIFIER; 
} 

[0-9]+ { 
yylval.intValue = atoi(yytext); 
return INTEGER; 
} 

[0-9]*\.[0-9]+"f"? { 
    yylval.floatValue = new atof(yytext); 
return FLOAT; 
} 

En outre, vous pouvez utiliser la valeur directement dans votre grammaire flex:

nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 } 

Enfin, si vous envisagez d'utiliser une syntaxe POO arbre, vous pouvez définir l'union comme

%union 
{ 
    class ASTNode *node; 
} 

dans lequel ASTNode est la classe ancêtre de toute sorte de s noeud yntax. Pourquoi définir une union d'un élément?

+3

Pourquoi? Pourquoi ne pas simplement '#define YYSTYPE class ASTNode *' (si la mémoire est bonne). –