如何使用 %union 并修复 "Semantic value used inside actions but has not declared the type" 警告

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

我在 parser.hpp 文件中为 scanner.lex 定义了 YYSTYPE 使用 :

// parser.hpp
#define YYSTYPE Atom

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

parser.ypp 我在 RetType

上遇到错误

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

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

我想消除错误并使用 %union 但不知道如何:

// 
%union {
  struct atom_t atom;
}

%type <atom> RetType;

你真的不应该使用

#define YYSTYPE Atom

如果你这样做,你将无法使用 %union(或 bison 提供的任何其他方式来声明语义类型),因为将 #define YYSTYPE 放入外部头文件完全绕过了 bison 自己设置语义类型的尝试。

你应该做的是使用

%define api.value.type { Atom } 

在你的野牛序言中。这会将 YYSTYPE 的声明复制到 bison 生成的头文件中,因此您无需在自己的头文件中担心它。

当然,这假设您满足于所有终端和非终端使用相同的语义值类型,因此根本不需要使用 %type。但是,bison 允许您将 %type 声明与 api.value.type 声明结合使用,前提是如果您在任何地方使用 %type 声明,则必须将它用于值为的所有文法符号引用(这与使用 %union 声明的语法的要求相同)。

如果您为特定语法符号声明 %type <atom>,则 bison 会翻译对该符号语义值的任何引用($$$n,具体取决于该符号是否在:) 的左侧或右侧变成有效的 $$.atom。这是一个简单的文本替换,因为 bison 对语义类型本身一无所知,并且它不要求选择器是一个简单的词;如果愿意,您可以使用 %type <atom.node>,在这种情况下,所有对这些符号值的引用都将附加 .atom.node。这在联合之外通常不是很有用,因为您不再有任何方式引用基值,但您可能有一个适合的用例。