yylval和union

时间:2009-12-05 19:35:57

标签: parsing yacc bison lexical-analysis

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

2 个答案:

答案 0 :(得分:26)

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

为了更好地解释,例如:

%union
{
    int intValue;
    float floatValue;
    char *stringValue;
}
如果您想为.yintfloat类型提供基本支持,请在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语法中使用值:

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

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

%union
{
    class ASTNode *node;
}

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

答案 1 :(得分:14)

%union声明会修改yylval的类型。

bison手册explains

  

在普通(非重入)解析器中,必须将令牌的语义值存储到全局变量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. */
...