在yacc文件中使用union

时间:2015-10-27 16:22:24

标签: c yacc unions

我正在尝试开发一个基本的编译器,我使用yylval的联合,如下所示:

%{
#include <string.h>
#include <stdio.h>
struct info {
  int line;
  /* details unimportant */
};
%}

%union{
  char *str;
  struct info *ptr;            
}

在我的词法分析器定义中,我有

%{
#include "parse.tab.h"
%}

但是当我编译生成的词法分析器时,我得到以下错误:

y.tab.h:  unknown type name 'YYSTYPE'.
error: request for a member str in something not a structure or a union.

我还需要#define YYSTYPE吗?

(我编辑了原始问题,从源文件中插入足够的信息,使问题回答。转录中的任何错误都是我的错,我道歉 - Rici。)

3 个答案:

答案 0 :(得分:2)

没有。如果您使用%union声明,则不得#define YYSTYPE;野牛手册清楚地说明了这一点。

但是,任何必要的声明 - 在这种情况下,struct info的声明 - 也必须包含在词法分析器描述文件(parse.l)中。两个生成的文件彼此独立,因此{em>解析器中声明struct info的事实不会使词法分析器自动使用该定义。 / p>

为了避免重复声明,通常最好将它们放在单独的头文件中:

file:info.h(已添加)

#ifndef INFO_H_HEADER_
#define INFO_H_HEADER_
struct info {
  int line;
  /* details unimportant */
};
// ...
#endif

file:parse.y(现在#include&#39; s,而不是内联结构声明)

%{
#include <stdio.h>
#include <string.h>
#include "info.h"
%}
%union{
  char *str;
  struct info *ptr;
}

file:parse.l(也是#includes info.h)

%{
#include <stdio.h>
#include <string.h>
/* This must come *before* including parse.tab.h */
#include "info.h"
#include "parse.tab.h"
%}

答案 1 :(得分:0)

以下是我如何使用YYSTYPE的示例:

typedef union {                         // base type filled by lexical analyzer
    struct {
        int numtype;                    // classval (type; selects into union below)
        union {
            int    ival;                    // integer value
            long   lval;                    // long value
            double dval;                    // double
        } val;
    } numval;
    unsigned char *sval;                    // string value
} lex_baseval;

typedef struct {                            // type returned by lexical analyzer
    int lineno;    
    lex_baseval lexval;
} YYSTYPE;

#define YYSTYPE YYSTYPE

答案 2 :(得分:0)

您的关联代码的问题在于%union 里面的 <。em文件顶部的%{ ... %} - 这意味着yacc只是将其逐字复制到y.tab.c文件中,并且实际上并不处理它。

当您尝试编译%union时,这显然表现为y.tab.c上的语法错误,但也意味着YYSTYPE中没有y.tab.h定义,因为yacc没有'看到%union所以没有创建一个。