Search code examples
compilationbisonsemanticslex

How to use %union and fix "Semantic value used inside actions but has not declared the type" warning


I have YYSTYPE defined in parser.hpp file for scanner.lex use:

// parser.hpp
#define YYSTYPE Atom

typedef struct Atom
{
  int i_value;
  TypeEnum e_type;
  string *str_value;
  Node *node;
} atom_t;

In parser.ypp I'm getting an error on RetType

"Semantic value used inside actions but has not declared the type"

RetType:
    Type                            {}
    |   VOID                        {
      debugPrint("Here");
      $$.e_type = TYPE_VOID;
    }
;

I want to get rid of the error and use %union but couldn't figure out how to:

// 
%union {
  struct atom_t atom;
}

%type <atom> RetType;

Solution

  • You really should not be using

    #define YYSTYPE Atom
    

    And if you do so, you will not be able to use %union (or any of the other ways bison provides to declare the semantic type), because putting a #define YYSTYPE into an external header file completely bypasses bison's attempt to set the semantic type itself.

    What you should instead do is use

    %define api.value.type { Atom } 
    

    in your bison prologue. That will copy the declaration of YYSTYPE into the bison-generated header, so you don't need to worry about it in your own header files.

    Of course, that assumes that you are content for all terminals and non-terminals to use the same semantic value type, so that there is no need to use %type at all. However, bison allows you to use %type declarations in conjunction with api.value.type declarations, with the proviso that if you use a %type declaration anywhere, you must use it for all grammar symbols whose value is referenced (which is the same as the requirement for a grammar which uses the %union declaration).

    If you declare %type <atom> for a particular grammar symbol, then bison translates any reference to that symbol's semantic value ($$ or $n, depending on whether the symbol is on the left- or right-hand side of the :) into what would effectively be $$.atom. It's a simple textual substitution, since bison doesn't know anything about the semantic type itself, and it doesn't require that the selector be a simple word; you could, if you wanted to, use %type <atom.node>, in which case all references to those symbols' values would have .atom.node appended to them. That's not usually very useful outside of unions, because you no longer have any way of referring to the base value, but you might have a use case which fits.