I'm working on constructing my parse data structure from bison's semantic values. One particular structure is of type std::vector<double>
. I'm curious how the bison internals handle moving semantic values. I tried analyzing the c++.m4 file, and found:
template <typename Base>
inline
void
]b4_parser_class_name[::basic_symbol<Base>::move (basic_symbol& s)
{
super_type::move(s);
]b4_variant_if([b4_symbol_variant([this->type_get ()], [value], [move],
[s.value])],
[value = s.value;])[]b4_locations_if([
location = s.location;])[
}
Unfortunately, I cannot decipher this nearly enough to make out the efficiency of moving a data structure like std::vector, partly owing to my ignorance of the m4 syntax.
Given this in my grammar:
%define api.token.constructor
%define api.value.type variant
%type < std::vector<double> > numlist
...
numlist:
num { $$ = std::vector<double>(); $$.push_back($1); }
| numlist "," num { $$ = $1; $$.push_back($3); }
;
I am uncertain of the performance implications. Note that this will be compiled with a C++98 compiler and not a C++11 compiler; hence there will be no move semantics.
I'm guessing that the $$ = std::vector<double>()
statement could be removed; I assume it would be default-constructed already, but I haven't tested and I'm not sure how bison's internal variant type works. What I'm particularly interested in is the $$ = $1; $$.push_back($3);
Will the vector be copied for every item that is to be added?
I can't determine if this is a case for switching the type to std::vector<double> *
; admittedly, much of the reasoning behind using bison's variant type was to use plain C++ types instead of a union of pointers.
I've also had similar curiosities on a parser that does in fact make use of C++11/14 and in particular std::unique_ptr
. If one line of a left-recursive rule assigned, say $$ = std::make_unique<...>(...)
, would the following be able to do $$ = $1; $$->...
?