Первое, что вы должны знать, это то, что этот дизайн не может работать. Если вы используете API-интерфейс C по умолчанию для bison, вы не можете использовать тип semanti c, который нельзя тривиально копировать, потому что bison будет побайтно копировать свой стек, если ему нужно перераспределить его (и я считаю, что есть другие проблемы, связанные с делать перезапись байтов без вызова деструкторов). Если вы хотите использовать общие указатели, вам следует понять, как использовать C ++ API, который, как мне кажется, достигает некоторой степени зрелости (хотя я мало использовал его). Вы, вероятно, будете намного более довольны результатом.
Независимо от этого, есть некоторые другие проблемы с вашим кодом.
Во-первых, современные приложения bison не должны #define YYSTYPE
, даже внутри блок %code requires
. Вместо этого вы должны использовать
%define api.value.type { /* SemanticType */ }
Если бы вы это сделали, bison смог бы сказать вам, что вы не можете использовать одновременно объявление %union
и фиксированный api.value.type
. Если тип semanti c является объединением, это объединение. Это также не может быть shared_pointer
. Поскольку вы, кажется, хотите, чтобы это было объединение, члены которого являются общими указателями, тогда это объединение, и вы не хотите определять его иначе.
Если вы действительно используете #define YYSTYPE
, а также %union
, тогда вы обнаружите, что %union
никогда не применяется. %union
вставляет определение по умолчанию YYSTYPE
(как union YYSTYPE
), но ваше явное определение YYSTYPE
отменяет это. Но bison не знает, что вы это сделали - это не станет очевидным, пока компилятор C не скомпилирует сгенерированный код - поэтому он переписывает ссылки на значения semanti c, используя теги, которые вы указали в %type
декларации. Другими словами, когда вы говорите %type <blockNode> input
, bison автоматически изменит любую ссылку на $n
, где это относится к экземпляру input non-terminal
, добавив ссылку на поле, как если бы вы написали $n.blockNode
(который, из Конечно, вы не должны этого делать, потому что bison уже добавил ссылку на поле). Но #define
-определяемый YYSTYPE
не является объединением, это shared_pointer<Node>
, а shared_pointer<Node>
не имеет члена blockNode
, как указано в сообщении об ошибке компилятора C ++.
Аналогично, в правилах для input
объявление %type
заставляет bison генерировать код, который будет назначен (несуществующему) члену blockNode
.
В качестве иллюстрации моего первого пункта - что вы не может использовать shared_pointer
как тип семанти c или член объединения с генератором кода C - я "исправил" ваш код, применив предложенное выше (то есть удалил #define YYSTYPE
и сделал больше или меньший минимальный набор изменений, чтобы избежать других ошибок bison и компилятора, в результате получился следующий уменьшенный воспроизводимый пример :
Файл tom.yy
%code requires {
#include "tom_node.h"
#include <memory>
}
%code {
std::shared_ptr<Node> result;
void yyerror(const char* msg) {
std::cerr << msg << '\n';
}
int yylex();
}
%union {
std::shared_ptr<BlockNode> blockNode;
std::shared_ptr<Node> testNode;
}
%type <blockNode> input
%%
program : input { *result = *$1; /* ?? I don't know the actual intent */ }
input: '\n' { $$ = std::make_shared<BlockNode>();}
Файл tom_node.h
#ifndef TOM_NODE_H
#define TOM_NODE_H
#include <iostream>
#include <string>
class Node /*: public std::enable_shared_from_this<Node>*/ {
public:
std::string myString;
Node() {}
~Node() { std::cout << "destroyed" << myString << std::endl; }
};
class BlockNode : public Node {
public:
BlockNode() {
myString = "block node";
std::cout << "created" << myString << std::endl;
}
};
#endif
Результатом является последовательность похожих ошибок, все из которых связаны с тем, что std::shared_pointer
не является тривиальным типом. Вот несколько первых:
$ bison -o tom.cc tom.yy
$ gcc -Wall -o tom tom.cc -ly
tom.cc:956:9: error: use of deleted function ‘YYSTYPE::YYSTYPE()’
YYSTYPE yylval;
^~~~~~
tom.cc:104:7: note: ‘YYSTYPE::YYSTYPE()’ is implicitly deleted because the default definition would be ill-formed:
union YYSTYPE
^~~~~~~
tom.yy:15:32: error: union member ‘YYSTYPE::blockNode’ with non-trivial ‘constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = BlockNode]’
std::shared_ptr<BlockNode> blockNode;
^~~~~~~~~
tom.yy:16:27: error: union member ‘YYSTYPE::testNode’ with non-trivial ‘constexpr std::shared_ptr<_Tp>::shared_ptr() [with _Tp = Node]’
std::shared_ptr<Node> testNode;
^~~~~~~~
tom.cc: In function ‘int yyparse()’:
tom.cc:985:30: error: use of deleted function ‘YYSTYPE::YYSTYPE()’
YYSTYPE yyvsa[YYINITDEPTH];
^