yylval和union

neu*_*cer 17 parsing yacc bison lexical-analysis

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

Jac*_*ack 27

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

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

%union
{
    int intValue;
    float floatValue;
    char *stringValue;
}
Run Code Online (Sandbox Code Playgroud)

.y如果要提供基本的支持int,floatstring类型.你能用这个做什么?

两件事情:

首先,您可以在生成令牌时自动设置正确的值.想想.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;
}
Run Code Online (Sandbox Code Playgroud)

另外,您可以直接在flex语法中使用值:

nexp: nexp '+' nexp { $<floatValue>$ = $<floatValue>1 + $<floatValue>3 }
Run Code Online (Sandbox Code Playgroud)

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

%union
{
    class ASTNode *node;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么要定义一个元素的并集?为什么不只是`#define YYSTYPE class ASTNode*`(如果内存服务). (3认同)

Gre*_*con 14

%union声明修改的类型yylval.

bison手册介绍:

在普通(非重入)解析器中,令牌的语义值必须存储在全局变量中yylval.当您仅使用一种数据类型作为语义值时,yylval具有该类型.因此,如果类型是int(默认值),您可以将其写入yylex:

...
yylval = value;  /* Put value onto Bison stack. */
return INT;      /* Return the type of the token. */
...
Run Code Online (Sandbox Code Playgroud)

当您使用多种数据类型时,yylval类型是由%union声明构成的并集(请参阅值类型集合一节).因此,当您存储令牌的值时,您必须使用联合的正确成员.如果%union声明如下:

%union {
  int intval;
  double val;
  symrec *tptr;
}
Run Code Online (Sandbox Code Playgroud)

然后代码yylex可能如下所示:

...
yylval.intval = value; /* Put value onto Bison stack. */
return INT;          /* Return the type of the token. */
...
Run Code Online (Sandbox Code Playgroud)