spirit x3:本地定义的规则定义必须附加一个属性?
spirit x3: locally defined rule definition must have an attribute attached?
简单的 x3 代码无法编译,因为没有任何内容附加到第二个 ruleTest 或整个解析器。即使我们将 x3::omit[ruleTest]
放在第二个 ruleTest
周围,它仍然无法编译。
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
);
}
只有当我们将lambda或属性附加到x3::parse或使用BOOST_SPIRIT_DEFINE全局定义ruleTest时才能解决问题。
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);
}
错误的症结似乎是
test.cpp|9 col 59| error: no match for ‘operator+=’ (operand types are ‘boost::spirit::x3::unused_type’ and ‘char’)
这是因为编译器发现绑定属性 (none) 的实际类型是 x3::unused_type
,因此语义操作无法编译。
我什至不确定您希望它如何工作,因为您无法将不存在的属性中的字符更新为 'x'
。
这是一个提议"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');})]
;
#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");
}
简单的 x3 代码无法编译,因为没有任何内容附加到第二个 ruleTest 或整个解析器。即使我们将 x3::omit[ruleTest]
放在第二个 ruleTest
周围,它仍然无法编译。
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
);
}
只有当我们将lambda或属性附加到x3::parse或使用BOOST_SPIRIT_DEFINE全局定义ruleTest时才能解决问题。
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);
}
错误的症结似乎是
test.cpp|9 col 59| error: no match for ‘operator+=’ (operand types are ‘boost::spirit::x3::unused_type’ and ‘char’)
这是因为编译器发现绑定属性 (none) 的实际类型是 x3::unused_type
,因此语义操作无法编译。
我什至不确定您希望它如何工作,因为您无法将不存在的属性中的字符更新为 'x'
。
这是一个提议"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');})]
;
#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");
}