Harsh S. Kulshrestha
Harsh S. Kulshrestha

Reputation: 293

Using union in yacc file

I'm trying to develop a basic compiler and I'm using a union for yylval as follows:

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

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

In my lexer definition, I have

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

But when I compile the generated lexer, I get the following errors:

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

Do I need to #define YYSTYPE as well?

(I edited the original question to insert enough information from the source files to make the question answerable. Any mistakes in the transcription are my fault and I apologize -- Rici.)

Upvotes: 2

Views: 3967

Answers (3)

rici
rici

Reputation: 241861

No. If you use a %union declaration, you must not #define YYSTYPE; the bison manual makes this clear.

However, any necessary declarations -- in this case, the declaration of struct info -- must be included in your lexer description file (parse.l) as well. The two generated files are independent of each other, so the fact that struct info is declared in the parser does not make the definition automatically available to the lexer.

In order to avoid repeating the declarations, it is usually a good idea to put them in a separate header file:

file: info.h (added)

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

file: parse.y (now #include's info.h instead of the in-line struct declaration)

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

file: parse.l (also #includes info.h)

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

Upvotes: 3

Chris Dodd
Chris Dodd

Reputation: 126408

The problem with your linked code is that the %union is inside the %{...%} at the top of your .y file -- which means that yacc just copies it verbatim to the y.tab.c file and does not actually process it.

This manifests most obviously as a syntax error on %union when you try to compile y.tab.c, but also means there's no YYSTYPE definition in y.tab.h, as yacc didn't see the %union so didn't create one.

Upvotes: 0

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

The following is an example of how I use 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

Upvotes: 0

Related Questions