0

I want to add struct in union in a yacc file but I found this error:

"error : member 'Info YYSTYPE ::info' with constructor not allowed in union "

%{
#include <cstdio>
#include <iostream>
using namespace std;

 extern "C" int yylex();                         
 extern "C" int yyparse();             
 extern "C" FILE *yyin;                
 struct Info{ int intval; float floatval; string stringval ;int type; } 

void yyerror(const char *s);
%}

%union {  

int ival;
float fval;
char *sval;

struct Info info;

}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • The error tells you pretty much exactly what the problem is: C++ does not allow you to put a struct with a constructor (non-POD type) in a union. Nothing in particular to do with yacc. – Chris Dodd May 13 '16 at 19:29
  • Possible duplicate of [... with constructor not allowed in union problem](http://stackoverflow.com/questions/6014717/with-constructor-not-allowed-in-union-problem) – Schore May 13 '16 at 20:29

3 Answers3

1

You can't put non-POD structs in a union in C++, because there's no way for the compiler to tell which union member to construct or destruct.

One alternative is to use pointers in the union:

%union {
    ...
    Info *info;
};

in which case you need to be careful about explicitly deleting the pointers if/when they are no longer needed. Bison's %destructor can be useful here to avoid leaks if there are errors.

Alternately, don't use %union at all -- just define YYSTYPE as a single type:

%{
#define YYSTYPE struct Info
%}

in which case all your rules need to use the same type (no %type declarations to have different rules produce different things). Something like boost::variant can be useful if you really need to have different types..

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
0

I don't see the point of using both a union and a struct with the same members. You should use one or the other.

If you tell bison to emit a C++ parser, you can choose to use a variant-like semantic type. With either the C or the C++ parser, you can use a union or a struct, but in neither case can you have include a C++ std::string as a union member, even indirectly, precisely for the reason indicated in that error message. This has very little to do with bison; C++ won't let you define a union with a member which has a constructor unless the union itself has a constructor. (aIf you try to write the required constructor, you might see why the language has no way of doing it for you.)

If you don't want to have to mess around with memory management, bison's variant option may be for you. Read the documentation in the manual. Otherwise, you could use a pointer to a std::string (created with the new operator), or you could just use a C-string. In both cases, you will need to allocate and release storage.

rici
  • 234,347
  • 28
  • 237
  • 341
0

Union only allows you to use primitive types and pointers.

If you need to use structure, then in union you can only declare pointer to that structure.

Aleksandar Makragić
  • 1,957
  • 17
  • 32