I'm parsing a quite complex grammar with Boost Spirit and I'm facing a problem with a variant that have more than 20 types (21 here):
namespace eddic { namespace ast {
typedef boost::mpl::vector<
Integer,
IntegerSuffix,
Float,
Litteral,
VariableValue,
DereferenceValue,
Expression,
Unary,
Null,
True,
False,
ArrayValue,
FunctionCall,
MemberFunctionCall,
Cast,
BuiltinOperator,
Assignment,
SuffixOperation,
PrefixOperation,
Ternary
> types_initial;
typedef boost::mpl::push_back<types_initial, New>::type types;
typedef boost::make_variant_over<types>::type Value;
}}
Boost Spirit does not recognize the last type (eddic::ast::New) added with push_back. When I parse something that have this element, it fails with this error:
eddic: /usr/include/boost/variant/detail/visitation_impl.hpp:264:
typename Visitor::result_type
boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV,
mpl_::false_, NoBackupFlag, Which*, step0*) [with Which =
mpl_::int_<0>; step0 =
boost::detail::variant::visitation_impl_step,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>,
0>, 0>, 0>, 0>, 0l>,
boost::mpl::v_iter,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
boost::mpl::v_item,
0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>, 0>,
0>, 0>, 0>, 0>, 21l> >; Visitor =
boost::variant, boost::mpl::vector,
eddic::ast::Deferred,
eddic::ast::Deferred, eddic::ast::Null,
eddic::ast::True, eddic::ast::False,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred >, 0> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_>::assigner; VoidPtrCV = const void*;
NoBackupFlag =
boost::variant, boost::mpl::vector,
eddic::ast::Deferred,
eddic::ast::Deferred, eddic::ast::Null,
eddic::ast::True, eddic::ast::False,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred,
eddic::ast::Deferred >, 0> >,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_, boost::detail::variant::void_,
boost::detail::variant::void_>::has_fallback_type_; typename
Visitor::result_type = void; mpl_::false_ = mpl_::bool_]:
Assertion `!"Boost.Variant internal error: 'which' out of range."'
failed.
If I swap two elements (Ternary and New for example), New is correctly recognized, but not Ternary. It is only the last element that fails.
I already tried using push_front or vector21, but it doesn't change anything, it's always the last element that have problem. In my opinion it comes from the fact that Spirit uses a variant internally before copying it to my variant_over type.
Is there a workaround to this problem ?
I could probably reduce the number to 20, but the problem is that I will certainly have more than that in the future.
Thanks a lot for any idea
Define BOOST_MPL_LIMIT_VECTOR_SIZE to whatever new limit you want, but going this high is usually a hint at design problems so it might be worth to give it some consideration.
I am going a bit nuts trying to figure out why the following won't compile:
#include <iostream>
#include <array>
#include <boost/variant.hpp>
#include <forward_list>
typedef unsigned long long very_long;
typedef boost::variant< int, std::string > variants_type;
typedef std::array< variants_type, 5 > row_type;
typedef std::forward_list<row_type> rows_holder_type;
int main() {
rows_holder_type rows;
row_type row_data;
row_data[0] = 0;
row_data[1] = 0;
row_data[2] = 0;
row_data[3] = 0;
row_data[4] = 0;
rows.push_front(row_data);
}
This is the compiler error I am getting:
/usr/include/testing/test_code.o||In function 'std::array<boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>, 5ul>::array(std::array<boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>, 5ul> const&)':|
store.cpp:(.text._ZNSt5arrayIN5boost7variantIiSsNS0_6detail7variant5void_ES4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_EELm5EEC2ERKS6_[_ZNSt5arrayIN5boost7variantIiSsNS0_6detail7variant5void_ES4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_S4_EELm5EEC5ERKS6_]+0x31)||undefined reference to 'boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::variant(boost::variant<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_> const&)'|
||=== Build finished: 1 errors, 0 warnings ===|
If I replace:
typedef boost::variant< int, std::string > variants_type;
with:
typedef boost::any variants_type;
The code compiles, but I do not want to use boost::any for performance reasons.
I tested your code with MSVC and gcc 4.7.0. MSVC compiles and links the code fine (of course with #include <string>), but gcc gives a linker error on the last line rows.push_front(row_data);. If you comment that line out, gcc accepts the code. I see no reason why gcc gives a linker error and am concluding that it is a bug with gcc. One workaround on gcc would be to change std::array to std::vector.
(From the error message I assume you are using Code::Blocks with gcc)
I've eliminated extra code and the following example still gives the linker error:
#include <boost/variant.hpp>
#include <array>
int main()
{
std::array<boost::variant<int, double>, 5> row_type1;
std::array<boost::variant<int, double>, 5> row_type2 = row_type1;
}
You're missing #include <string>; other than that your code is fine.
I'm having issues getting a small spirit/qi grammar to compile. i am using boost 1.43 and g++ 4.4.1.
the input grammar header:
the build error seems to be pointing to the definition of the 'instruction' rule, maybe it is the '[sp::_val = sp::_1]' that somehow brokes it but this is more or less based on what the spirit documentation tutorials are doing with the xml node parser
inputGrammar.h
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
namespace sp = boost::spirit;
namespace qi = boost::spirit::qi;
using namespace boost::spirit::ascii;
//using namespace boost::spirit::arg_names;
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
using phoenix::at_c;
using phoenix::push_back;
template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {
InputGrammar() : InputGrammar::base_type( block ) {
tag = sp::lexeme[+(alpha) [sp::_val += sp::_1]];//[+(char_ - '<') [_val += _1]];
block = sp::lit("block") [ at_c<0>(sp::_val) = sp::_1]
>> "(" >> *instruction[ push_back( at_c<1>(sp::_val) , sp::_1 ) ]
>> ")";
command = tag [ at_c<0>(sp::_val) = sp::_1]
>> "(" >> *instruction [ push_back( at_c<1>(sp::_val) , sp::_1 )]
>> ")";
instruction = ( command | tag ) [sp::_val = sp::_1]; //build error seems to be happening here
}
qi::rule< Iterator , std::string() , space_type > tag;
qi::rule< Iterator , ExpressionAST() , space_type > block;
qi::rule< Iterator , ExpressionAST() , space_type > function_def;
qi::rule< Iterator , ExpressionAST() , space_type > command;
qi::rule< Iterator , ExpressionAST() , space_type > instruction;
};
the test build program:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//my grammar
#include <InputGrammar.h>
struct MockExpressionNode {
std::string name;
std::vector< MockExpressionNode > operands;
typedef std::vector< MockExpressionNode >::iterator iterator;
typedef std::vector< MockExpressionNode >::const_iterator const_iterator;
iterator begin() { return operands.begin(); }
const_iterator begin() const { return operands.begin(); }
iterator end() { return operands.end(); }
const_iterator end() const { return operands.end(); }
bool is_leaf() const {
return ( operands.begin() == operands.end() );
}
};
BOOST_FUSION_ADAPT_STRUCT(
MockExpressionNode,
(std::string, name)
(std::vector<MockExpressionNode>, operands)
)
int const tabsize = 4;
void tab(int indent)
{
for (int i = 0; i < indent; ++i)
std::cout << ' ';
}
template< typename ExpressionNode >
struct ExpressionNodePrinter
{
ExpressionNodePrinter(int indent = 0)
: indent(indent)
{
}
void operator()(ExpressionNode const& node) const {
cout << " tag: " << node.name << endl;
for (int i=0 ; i < node.operands.size() ; i++ ) {
tab( indent ); cout << " arg "<<i<<": "; ExpressionNodePrinter(indent + 2)( node.operands[i]); cout << endl;
}
}
int indent;
};
int test() {
MockExpressionNode root;
InputGrammar< string::const_iterator , MockExpressionNode > g;
std::string litA = "litA";
std::string litB = "litB";
std::string litC = "litC";
std::string litD = "litD";
std::string litE = "litE";
std::string litF = "litF";
std::string source = litA+"( "+litB+" ,"+litC+" , "+ litD+" ( "+litE+", "+litF+" ) "+ " )";
string::const_iterator iter = source.begin();
string::const_iterator end = source.end();
bool r = qi::phrase_parse( iter , end , g , space , root );
ExpressionNodePrinter< MockExpressionNode > np;
np( root );
};
int main() {
test();
}
finally, the build error is the following:
(the full error trace is 20 times bigger than the allowed size for a stackoverflow question, so i posted the full version of it at http://codepad.org/Q74IVCUc)
/usr/bin/make -f nbproject/Makefile-linux_amd64_devel.mk SUBPROJECTS= .build-conf
make[1]: se ingresa al directorio `/home/mineq/NetBeansProjects/InputParserTests'
/usr/bin/make -f nbproject/Makefile-linux_amd64_devel.mk dist/linux_amd64_devel/GNU-Linux-x86/vpuinputparsertests
make[2]: se ingresa al directorio `/home/mineq/NetBeansProjects/InputParserTests'
mkdir -p build/linux_amd64_devel/GNU-Linux-x86
rm -f build/linux_amd64_devel/GNU-Linux-x86/tests_main.o.d
g++ `llvm-config --cxxflags` `pkg-config --cflags unittest-cpp` `pkg-config --cflags boost-1.43` `pkg-config --cflags boost-coroutines` -c -g -I../InputParser -MMD -MP -MF build/linux_amd64_devel/GNU-Linux-x86/tests_main.o.d -o build/linux_amd64_devel/GNU-Linux-x86/tests_main.o tests_main.cpp
from /home/mineq/third_party/boost_1_43_0/boost/spirit/include/phoenix_operator.hpp:11,
from ../InputParser/InputGrammar.h:14,
from tests_main.cpp:14:
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/operator/self.hpp: In instantiation of ‘const int boost::phoenix::result_of_assign<MockExpressionNode&, boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>::size’:
In file included from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/operator.hpp:16,
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/operator/self.hpp:27: instantiated from ‘const int boost::phoenix::result_of_assign<MockExpressionNode&, boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>::index’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/operator/self.hpp:27: instantiated from ‘boost::phoenix::result_of_assign<MockExpressionNode&, boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>’
/home/mineq/third_party/boost_1_43_0/boost/mpl/eval_if.hpp:38: instantiated from ‘boost::mpl::eval_if<boost::mpl::or_<boost::phoenix::is_actor<MockExpressionNode&>, boost::phoenix::is_actor<boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >, boost::phoenix::re_curry<boost::phoenix::assign_eval, MockExpressionNode&, boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>, boost::phoenix::result_of_assign<MockExpressionNode&, boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/operator/self.hpp:69: instantiated from ‘boost::phoenix::assign_eval::result<boost::phoenix::basic_environment<boost::fusion::vector1<boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>, boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, bool, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_>, boost::spirit::attribute<0>, boost::spirit::argument<0> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/core/detail/composite_eval.hpp:89: instantiated from ‘boost::phoenix::detail::composite_eval<2>::result<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::phoenix::basic_environment<boost::fusion::vector1<boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>, boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, bool, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/core/composite.hpp:61: instantiated from ‘boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >::result<boost::phoenix::basic_environment<boost::fusion::vector1<boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>, boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, bool, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/core/actor.hpp:56: instantiated from ‘boost::phoenix::eval_result<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::phoenix::basic_environment<boost::fusion::vector1<boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>, boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, bool, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/phoenix/core/actor.hpp:65: instantiated from ‘boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >::result<boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >(boost::fusion::vector1<boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>&>&, boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >&, bool&)>’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/support/action_dispatch.hpp:44: instantiated from ‘bool boost::spirit::traits::action_dispatch<Component>::operator()(const boost::phoenix::actor<Eval>&, Attribute&, Context&) [with Eval = boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, Attribute = boost::variant<MockExpressionNode, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>, Context = boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, Component = boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::string(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::nil> > >]’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/action/action.hpp:62: instantiated from ‘bool boost::spirit::qi::action<Subject, Action>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Context = boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, Attribute = const boost::fusion::unused_type, Subject = boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::string(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::nil> > >, Action = boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >]’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:33: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::true_) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, Context = boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, Parser = boost::spirit::qi::action<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::string(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::nil> > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, Auto = mpl_::bool_<false>]’
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::operator()(Iterator&, const Iterator&, Context&, const Skipper&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, Context = boost::spirit::context<boost::fusion::cons<MockExpressionNode&, boost::fusion::nil>, boost::fusion::vector0<void> >, Parser = boost::spirit::qi::action<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::string(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::fusion::unused_type, boost::fusion::unused_type> >, boost::fusion::nil> > >,
...
... more errors but i had to truncate to fit the 30k limit
make[2]: *** [build/linux_amd64_devel/GNU-Linux-x86/tests_main.o] Error 1
make[2]: se sale del directorio `/home/mineq/NetBeansProjects/InputParserTests'
make[1]: *** [.build-conf] Error 2
make[1]: se sale del directorio `/home/mineq/NetBeansProjects/InputParserTests'
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 2m 13s)
Your error message tells you that you want to assign a variant<MockExpressionNode, basic_string> to a MockExpressionNode
The relevant lines are 33 and 34;
[...] error: no match for ‘operator=’ [...] boost::variant<MockExpressionNode, std::basic_string [...]
[...] candidates are: MockExpressionNode& MockExpressionNode::operator=(const MockExpressionNode&) [...]
To understand why this happens we have to look at the definitions. From the definition of a Qi rule, the signature of the returned value is defined by a template parameter. Hence
qi::rule< Iterator , ExpressionAST() , space_type > command;
means that the returned type of a command will be an ExpressionAST (i.e. a MockExpressionNode in your case). Similarly
qi::rule< Iterator , std::string() , space_type > tag;
means that tag will be of type string. Combining this with instruction = (command | tag) means that an instruction is either a string or a MockExpressionNode. This is internally stored as a variant<MockExpressionNode, string>. Finally,
qi::rule< Iterator , ExpressionAST() , space_type > instruction;
implies that the returned type of instruction is again an ExpressionAST (i.e. a MockExpressionNode). This requires the failing assignment from the variant held internally to a MockExpressionNode.
To sum up, you have to provide types in your qi::rules that somewhat "match" the types implied by your grammar in the sense that assignment is possible. Despite all the Boost.Spirit magic, C++ is still a statically typed language after all. For the issue at hand, you either have to supply a fitting operator=, or you have to assign the results of the different rules to different types that support implicit conversion. BTW, you have similar type issues for block and command at the moment. Take a careful look at the mini_xml example in the documentation: how to define types for a recursive structure and how different rules assign to different types depending on the defined grammar (especially rules xml and node).