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.