22

yacc 文件中 union 的目的是什么?它是否与 flex 文件中的 yylval 直接相关?如果你不使用yylval,那么你不需要使用union?

4

2 回答 2

36

的目的union是允许将不同类型的对象存储到 flex 发出的节点中。

为了更好地解释,你可以有例如:

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

.y如果您想为,intfloat类型string提供基本支持。你能用这个做什么?

两件事情:

首先,您可以在生成令牌时自动设置正确的值。想想.l前面例子的文件,你可以有:

[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;
}

此外,您可以直接在flex 语法中使用 value :

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

最后,如果您打算使用 OOP 语法树,您可以将联合定义为

%union
{
    class ASTNode *node;
}

其中ASTNode是任何一种语法节点的祖先类。

于 2009-12-05T19:45:45.440 回答
19

%union声明修改yylval了.

bison手册解释:_

在普通(不可重入)解析器中,令牌的语义值必须存储到全局变量yylval中。当您只对语义值使用一种数据类型时,请使用yylval该类型。因此,如果类型是int(默认),你可以这样写yylex

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

当您使用多种数据类型时,yylval的类型是由%union声明组成的并集(参见值类型集合部分)。因此,当您存储令牌的值时,您必须使用正确的联合成员。如果%union声明如下所示:

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

那么中的代码yylex可能如下所示:

...
yylval.intval = value; /* Put value onto Bison stack. */
return INT;          /* Return the type of the token. */
...
于 2009-12-05T19:42:59.293 回答