对结构使用%union

问题描述 投票:0回答:1

我进行了很多搜索,但似乎找不到关于如何使用%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(***$2->name***)){errorDef(yylineno, ID_ptr->name);exit(1);}}

但是很明显,$ 2->名称不会返回它。 %union在结构中的正确用法是什么?如何正确获取名称的值?

谢谢你。

c++ struct bison
1个回答
1
投票

没有“在结构中正确使用%union”,因为%union用于声明union。 (当然,您可以声明只有一个成员的union,但这几乎没有意义。)

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

%define api.value.type { Node* }

但是那不会让您想要,因为您想要的既不是union也不是固定类型,而是隐式动态类型转换或类似内容。那不在野牛的选项菜单上。 (很容易理解为什么不这样做。动态类型转换不是左值,因此Bison必须知道何时应用它,何时不应用它。)

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

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

如果生成的是C ++解析器而不是C ++解析器,而C解析器恰好在C ++中工作,那么您还有其他选择,对于您的应用程序而言,这可能是更好的解决方案,也可能不是。 C解析器的选项在Bison手册的Language Semantics章中进行了说明,C ++选项的名称为their own chapter,尽管如果您要使用C ++接口,则需要阅读整个C ++部分。

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

© www.soinside.com 2019 - 2024. All rights reserved.