c++ - spirit x3: locally defined rule definition must have an attribute attached? -
simple x3 code cannot compile because nothing attached 2nd ruletest or whole parser. if put x3::omit[ruletest]
around second ruletest
still cannot compile.
void test(std::string const& str) { auto const ruletest = x3::rule<struct _, std::string>{} = *(x3::char_ - ' ')[([](auto& ctx){x3::_val(ctx)+='x';})]; x3::parse(boost::begin(str), boost::end(str), ruletest[([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >> ' ' >> ruletest ); }
only when attach lambda or attribute x3::parse or define ruletest globally boost_spirit_define solve problem.
void test(std::string const& str) { auto const ruletest = x3::rule<struct _, std::string>{} = *(x3::char_ - ' ')[([](auto& ctx){x3::_val(ctx)+='x';})]; std::string attr; x3::parse(boost::begin(str), boost::end(str), ruletest[([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >> ' ' >> ruletest, attr); }
the crux of error appears be
test.cpp|9 col 59| error: no match ‘operator+=’ (operand types ‘boost::spirit::x3::unused_type’ , ‘char’)
this because compiler sees actual type of bound attribute (none) x3::unused_type
, therefore semantic action doesn't compile.
i'm not sure how want work since cannot update characters 'x'
in attribute doesn't exist.
here's proposed "fix":
struct { void operator()(std::string& s, char c) const { s += c; } void operator()(...) const { } } ll; auto const ruletest = x3::rule<struct _, std::string>{} = *(x3::char_ - ' ') [([ll](auto& ctx){ ll(x3::_val(ctx), 'x');})] ;
see live on coliru
#include <boost/spirit/home/x3.hpp> #include <iostream> void test(std::string const& str) { namespace x3 = boost::spirit::x3; struct { void operator()(std::string& s, char c) const { s += c; } void operator()(...) const { } } ll; auto const ruletest = x3::rule<struct _, std::string>{} = *(x3::char_ - ' ') [([ll](auto& ctx){ ll(x3::_val(ctx), 'x');})] ; //std::string attr; auto f = begin(str), l = end(str); bool ok = x3::parse(f, l, ruletest [([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >> ' ' >> ruletest); if (ok) std::cout << "parse success\n"; else std::cout << "parse failed\n"; if (f != l) std::cout << "remaining unparsed: '" << std::string(f,l) << "'\n"; } int main() { test("abc def"); }
Comments
Post a Comment