对结构使用 %union

using %union for structs

我搜索了很多但似乎找不到关于如何使用 %union 的明确示例是我的解析器文件。 例如,我想将以下标记保存在名为 classID 的结构中:

[a-zA-Z][a-zA-Z0-9]*            { yylval=new IDClass(yytext); return ID; }

这是我的 .hpp 文件夹中包含的结构:

class Node {
    public:
       Node(){}
    };


    class IDClass : public Node {
    public:
        string name;
        IDClass(string name):
        Node(),name(name)
        {}
    };

& 然后在我的 .ypp 文件中,我想用它来进行某些检查:

Define: Type ID { if(doesIDexists(***->name***)){errorDef(yylineno, ID_ptr->name);exit(1);}}

但显然,$2->name 不会 return 它。 %union 在结构中的正确用法是什么?如何正确获取 name 的值?

提前致谢。

没有"correct use of %union in structs",因为%union用于声明union。 (当然,您可以声明一个只有一个成员的 union,但这几乎毫无意义。)

声明不是 union 的语义类型的正确方法是:

%define api.value.type { Node* }

但这不会得到你想要的,因为你想要的既不是 union 也不是固定类型,而是隐式动态转换或类似的东西。这不在 Bison 的选项菜单上。 (很容易看出为什么不这样做。动态转换不是左值,因此 Bison 必须知道何时应用它,何时不应用它。)

所以你可以使用上面的%define api.value.type然后写出语法动作:

Define: Type ID { if (doesIDexist(dynamic_cast<IDClass>()->name)) {
                        errorDef(@2.first_line,
                                 dynamic_cast<IDClass>()->name);
                        exit(1);
                      }
                }

如果您生成 C++ 解析器而不是恰好在 C++ 中工作的 C 解析器,那么您还有一些其他选项,这可能是也可能不是对您的应用程序更好的修复。 Language Semantics chapter of the Bison manual, and the C++ options have their own chapter 中解释了 C 解析器的选项,但如果您要使用 C++ 接口,则需要阅读整个 C++ 部分。

注意:我将yylineno改为@2.first_line,因为yylineno通常是不准确的; yylineno 通常是与先行标记关联的行号,它通常与错误不在同一行。但是您不能只是进行更改;您还必须确保您的词法分析器正确填写 yylloc。请参阅 Bison 手册中的 Tracking Locations 章节。