parsing - example - yacc python
yylval y unión (2)
¿Cuál es el propósito de la unión en el archivo yacc? ¿Está directamente relacionado con yylval en el archivo flexible? Si no usa yylval, ¿no necesita usar union?
La declaración %union
modifica el tipo de yylval
.
El manual del bison
explica :
En un analizador ordinario (no original), el valor semántico del token debe almacenarse en la variable global
yylval
. Cuando usa solo un tipo de datos para valores semánticos,yylval
tiene ese tipo. Por lo tanto, si el tipo esint
(el valor predeterminado), puede escribir esto enyylex
:
... yylval = value; /* Put value onto Bison stack. */ return INT; /* Return the type of the token. */ ...
Cuando está utilizando múltiples tipos de datos, el tipo de
yylval
es una unión hecha a partir de la declaración%union
(consulte la sección Colección de tipos de valores). Por lo tanto, cuando almacena el valor de un token, debe usar el miembro adecuado de la unión. Si la declaración%union
tiene este aspecto:
%union { int intval; double val; symrec *tptr; }
entonces el código en
yylex
podría verse así:
... yylval.intval = value; /* Put value onto Bison stack. */ return INT; /* Return the type of the token. */ ...
El propósito de la union
es permitir el almacenamiento de diferentes tipos de objetos en nodos emitidos por flex.
Para explicar mejor, puede tener, por ejemplo:
%union
{
int intValue;
float floatValue;
char *stringValue;
}
en .y
si quieres proporcionar soporte básico para int
, float
y tipos de string
. ¿Qué puedes hacer con esto?
Dos cosas:
Primero, puede establecer automáticamente los valores correctos al generar tokens. Piensa en el archivo .l
del ejemplo anterior, puedes tener:
[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;
}
Además, puede usar el valor directamente en su gramática flexible :
nexp: nexp ''+'' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }
Finalmente, si planea usar un árbol de sintaxis de OOP, puede definir la unión como
%union
{
class ASTNode *node;
}
en el que ASTNode
es la clase antecesora de cualquier tipo de nodo de sintaxis.