Bison 中的 std::shared_ptr 导致成员错误

Tom*_*Tom 1 c++ smart-pointers bison flex-lexer

我正在尝试通过使用来提高野牛的内存效率std::shared_ptr。我不想使用原始指针。我使用节点系统作为解析树,所以我定义YYTYPEstd::shared_ptr<Node>。用一些简单的语法运行它后,我得到编译错误:

C2039 'blockNode':不是 'std::shared_ptr' 的成员

我觉得这很奇怪,因为在 C++ 中运行的等效代码工作得很好

std::shared_ptr<Node> test = std::make_shared<BlockNode>();

我缺少什么?

需要

%code requires {
    typedef void* yyscan_t;
    #include "node.h"
    #include <memory>
    #define YYSTYPE std::shared_ptr<Node>
}
Run Code Online (Sandbox Code Playgroud)

联盟

%union {
    std::shared_ptr<BlockNode> blockNode;
    std::shared_ptr<TestNode> testNode;
}

%type <blockNode> input
%type <testNode> expr
Run Code Online (Sandbox Code Playgroud)

语法

%start program

%%

program : input { *result = $1; } // <- error here
        ;

input: '\n'      { $$ = std::make_shared<BlockNode>();} // <- error here
     ;

%%

Run Code Online (Sandbox Code Playgroud)

节点.h

class Node /*: public std::enable_shared_from_this<Node>*/ {
public:
    std::string myString;
    Node() {}
    ~Node() { std::cout << "destoryed" << myString << std::endl; }
};

class BlockNode : public  Node {
public:
    BlockNode() {
        myString = "block node";
        std::cout << "created" << myString << std::endl;
    }

};

Run Code Online (Sandbox Code Playgroud)

ric*_*ici 5

您应该知道的第一件事是这种设计行不通。如果您使用 bison 的默认 C API,则不能使用不可简单复制的语义类型,因为如果需要重新分配它, bison 会按字节复制其堆栈(并且我相信还有其他问题与覆盖字节而无需调用析构函数)。如果你想使用共享指针,你应该弄清楚如何使用 C++ API,我认为它已经达到了某种成熟度(尽管我还没有使用它太多)。您可能会对结果感到更加满意。

\n

不管怎样,您的代码还存在一些其他问题。

\n

首先,现代野牛应用程序不应该这样做#define YYSTYPE,即使在%code requires块内也不应该。你应该使用

\n
 %define api.value.type { /* SemanticType */ }\n
Run Code Online (Sandbox Code Playgroud)\n

如果你这样做了,bison 就会告诉你不能同时使用%union声明和固定api.value.type。如果语义类型是联合,那么它就是联合。它也不可能是一个shared_pointer. 由于您似乎希望它是一个成员都是共享指针的联合,那么它就是一个联合,您不想以其他方式定义它。

\n

如果您确实使用#define YYSTYPE, 并且也使用%union,那么您会发现%union永远不会应用。插入(as )%union的默认定义,但您的显式定义会覆盖它。但是 bison 不知道您已经这样做了——直到 C 编译器实际编译生成的代码时它才变得明显——因此它使用您在声明中提供的标签重写语义值引用。换句话说,当您说 时,bison 将通过添加字段引用来自动更改对引用实例的任何引用,就像您已经编写的那样(当然,您不能这样做,因为 bison 已经添加了现场参考)。但 -overridden不是联合体,而是 a ,并且没有成员,如 C++ 编译器错误消息所示。YYSTYPEunion YYSTYPEYYSTYPE%type%type <blockNode> input$ninput non-terminal$n.blockNode#defineYYSTYPEshared_pointer<Node>shared_pointer<Node>blockNode

\n

类似地,在 的规则中input%type声明会导致 bison 发出代码,该代码将分配给(不存在的)blockNode成员。

\n

为了说明我的第一点——您不能将shared_pointer其用作 C 代码生成器的语义类型或联合成员——我通过应用上面的建议“修复”了您的代码(即删除#define YYSTYPE, 并制作了更多或减少最小的更改集以避免其他野牛和编译器错误,从而导致以下减少的可重现示例

\n

文件 tom.yy

\n
%code requires {\n    #include "tom_node.h"\n    #include <memory>\n}\n\n%code {\n    std::shared_ptr<Node> result;\n    void yyerror(const char* msg) {\n      std::cerr << msg << \'\\n\';\n    }\n    int yylex();\n}\n\n%union {\n    std::shared_ptr<BlockNode> blockNode;\n    std::shared_ptr<Node> testNode;\n}\n\n%type <blockNode> input\n\n%%\n\nprogram : input  { *result = *$1; /* ?? I don\'t know the actual intent */ }\n\ninput: \'\\n\'      { $$ = std::make_shared<BlockNode>();}\n
Run Code Online (Sandbox Code Playgroud)\n

文件 tom_node.h

\n
#ifndef TOM_NODE_H\n#define TOM_NODE_H\n\n#include <iostream>\n#include <string>\n\nclass Node /*: public std::enable_shared_from_this<Node>*/ {\npublic:\n    std::string myString;\n    Node() {}\n    ~Node() { std::cout << "destroyed" << myString << std::endl; }\n};\n\nclass BlockNode : public  Node {\npublic:\n    BlockNode() {\n        myString = "block node";\n        std::cout << "created" << myString << std::endl;\n    }\n\n};\n#endif\n
Run Code Online (Sandbox Code Playgroud)\n

结果是一系列类似的错误,所有这些错误都涉及到std::shared_pointer一个不简单的类型。这是前几个:

\n
$ bison -o tom.cc tom.yy\n$ gcc -Wall -o tom tom.cc -ly\ntom.cc:956:9: error: use of deleted function \xe2\x80\x98YYSTYPE::YYSTYPE()\xe2\x80\x99\n YYSTYPE yylval;\n         ^~~~~~\ntom.cc:104:7: note: \xe2\x80\x98YYSTYPE::YYSTYPE()\xe2\x80\x99 is implicitly deleted because the default definition would be ill-formed:\n union YYSTYPE\n       ^~~~~~~\ntom.yy:15:32: error: union member \xe2\x80\x98YYSTYPE::blockNode\xe2\x80\x99 with non-trivial \xe2\x80\x98constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = BlockNode]\xe2\x80\x99\n     std::shared_ptr<BlockNode> blockNode;\n                                ^~~~~~~~~\ntom.yy:16:27: error: union member \xe2\x80\x98YYSTYPE::testNode\xe2\x80\x99 with non-trivial \xe2\x80\x98constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = Node]\xe2\x80\x99\n     std::shared_ptr<Node> testNode;\n                           ^~~~~~~~\ntom.cc: In function \xe2\x80\x98int yyparse()\xe2\x80\x99:\ntom.cc:985:30: error: use of deleted function \xe2\x80\x98YYSTYPE::YYSTYPE()\xe2\x80\x99\n     YYSTYPE yyvsa[YYINITDEPTH];\n                              ^\n
Run Code Online (Sandbox Code Playgroud)\n