yylval可能是结构而不是联合吗?

时间:2018-11-25 20:43:15

标签: parsing bison

在Bison上,yylval可能是一个结构而不是一个并集吗?我知道我可以将yylval定义为与%union{}的并集,但是有没有办法将yylval定义为struct?返回示例的行和标识符的字符串并访问 这些信息是关于牛的某些语法规则的作用。

2 个答案:

答案 0 :(得分:1)

是的,您可以#define YYSTYPE成为所需的任何类型,而不使用%union。但是,这样做 1 几乎没有用-如果要获取源位置信息,最好将%position%union结合使用。

%union声明内的 中使用结构也是可能的(也是常见的)。这使某些规则可以轻松地(有效地)返回多个值。


1 主要的问题是,如果使用%type指定使用一个struct字段,那么在同一操作中使用其他字段会很麻烦。您需要手动完成所有操作,从而失去了野牛的工会类型检查的好处

答案 1 :(得分:1)

如果要为令牌保留位置信息(行号和列号),则可以使用Bison的位置工具,该工具将每个令牌和非终端的位置对象与语义值分开保存。在操作中,您将符号的位置称为@n

如果发现您已经在规则中的任何位置引用了位置,那么野牛会自动创建并维护位置堆栈。

默认情况下,位置数据类型为:

typedef struct YYLTYPE {
  int first_line;
  int first_column;
  int last_line;
  int last_column;
} YYLTYPE;

令牌的位置信息必须由词法分析器设置。如果使用的是默认API,它将存储在全局变量yylloc中。解析器将使用从生产的第一个项目的开头到最后一个项目的结尾的范围来创建非终端的位置信息。 (对于空产品,将生成一个长度为零的位置对象,该对象以前瞻标记的起始位置开始和结束。)

如有必要,可以覆盖这两个默认值。有关详细信息,请参见Bison manual

如果用%option yylineno询问,Flex将跟踪行号,但不会跟踪列位置,这有点烦人。另外,yylloc要求起始和结束行号; flex操作中的yylineno将是令牌末尾的行号。最常见的是,您将使用YY_USER_ACTION宏来维护yylloc的值;一个示例实现(取自this answer,如果使用此代码,则应阅读):

%option yylineno
%{
#define YY_USER_ACTION                                       \
  yylloc.first_line = yylloc.last_line;                      \
  yylloc.first_column = yylloc.last_column;                  \
  if (yylloc.first_line == yylineno)                         \
     yylloc.last_column += yyleng;                           \
  else {                                                     \
     int col;                                                \
     for (col = 1; yytext[yyleng - col] != '\n'; ++col) {}   \
     yylloc.last_column = col;                               \
     yylloc.last_line = yylineno;                            \
  }
%}