yylval和联合体

24

在yacc文件中,联合体的作用是什么?它是否直接与flex文件中的yylval相关?如果您不使用yylval,则不需要使用union吗?

2个回答

39

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

为了更好地解释,您可以举例如下:

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

如果你希望在 .y 文件中为 intfloatstring 类型提供基本支持,可以这样做:

有两件事情:

首先,你可以在生成 token 时自动设置正确的值。考虑上一个示例中的 .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 }

最后,如果您计划使用面向对象编程的语法树,您可以将union定义为:

%union
{
    class ASTNode *node;
}

ASTNode是任何语法节点的祖先类。


7
为什么要定义一个只有一个元素的union?为什么不直接使用#define YYSTYPE class ASTNode *(如果我没记错的话)? - Chris Lutz

20

%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. */
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接