如何在 x3 中用 qi::_1/qi::_N 重写 qi 解析器?
How to rewrite qi parsers with qi::_1/qi::_N in x3?
假设我们要解析一个内积表达式并得到结果。
"SUM({1, 2, 3} .* {4, 5, 6})"
qi::_1
和qi::_2
非常方便在解析器中引用第i个属性。
void Test(std::string const& input) {
qi::rule<decltype(boost::begin(input)), int(), qi::ascii::space_type> ruleSum =
(
qi::lit("SUM") >> '(' >>
'{' >> (qi::int_ % ',') >> '}' >>
".*" >>
'{' >> (qi::int_ % ',') >> '}' >>
')'
)[qi::_pass=phx::bind(
[](std::vector<int> const& vec1, std::vector<int> const& vec2, int& result) {
if(vec1.size() != vec2.size())
return false;
result = std::inner_product(boost::begin(vec1), boost::end(vec1), boost::begin(vec2), 0);
return true;
},
qi::_1, qi::_2, qi::_val
)];
int attr = 0;
if( qi::phrase_parse(boost::begin(input), boost::end(input), ruleSum >> qi::eoi, qi::ascii::space, attr) ) {
std::cout<<"Match! result = "<<attr<<std::endl;
} else {
std::cout<<"Not match!"<<std::endl;
}
}
精神x3,没有这样的qi::_1 ... qi::_N。我应该使用一对向量作为属性吗?解析类似这种内积的推荐方法是什么?
namespace inner_product {
x3::rule<struct idInnerProduct, int> const ruleInnerProduct("InnerProduct");
auto const ruleInnerProduct_def =
(
x3::rule<struct _, std::pair<std::vector<int>, std::vector<int>>>{} =
x3::lit("SUM") >> '(' >>
'{' >> (x3::int_ % ',') >> '}' >>
".*" >>
'{' >> (x3::int_ % ',') >> '}' >>
')'
)[([](auto& ctx){
if(_attr(ctx).first.size() != _attr(ctx).second.size()) {
_pass(ctx) = false;
} else {
x3::_val(ctx) = std::inner_product(
boost::begin(x3::_attr(ctx).first),
boost::end(x3::_attr(ctx).first),
boost::begin(x3::_attr(ctx).second),
0
);
}
})];
BOOST_SPIRIT_DEFINE(ruleInnerProduct)
}
该属性是一个融合序列。它的成员是 vector<int>
.
融合序列不是一对,所以不能使用.first
或.second
。
我会写:
void Test(std::string const& input) {
namespace x3 = boost::spirit::x3;
auto ruleSum = x3::rule<struct _, int> {} =
(
x3::lit("SUM") >> '(' >>
'{' >> (x3::int_ % ',') >> '}' >> ".*" >>
'{' >> (x3::int_ % ',') >> '}' >>
')'
)[( [](auto& ctx) {
using boost::fusion::at_c;
// dissect context
auto& pass = x3::_pass(ctx);
auto& result = x3::_val(ctx);
std::vector<int> const& vec1 = at_c<0>(x3::_attr(ctx));
std::vector<int> const& vec2 = at_c<1>(x3::_attr(ctx));
// do the work
pass = (vec1.size() == vec2.size());
if (pass)
result = std::inner_product(boost::begin(vec1), boost::end(vec1), boost::begin(vec2), 0);
})
];
int attr = 0;
if( x3::phrase_parse(boost::begin(input), boost::end(input), ruleSum >> x3::eoi, x3::ascii::space, attr) ) {
std::cout<<"Match! result = "<<attr<<std::endl;
} else {
std::cout<<"Not match!"<<std::endl;
}
}
打印:
Match! result = 32
假设我们要解析一个内积表达式并得到结果。
"SUM({1, 2, 3} .* {4, 5, 6})"
qi::_1
和qi::_2
非常方便在解析器中引用第i个属性。
void Test(std::string const& input) {
qi::rule<decltype(boost::begin(input)), int(), qi::ascii::space_type> ruleSum =
(
qi::lit("SUM") >> '(' >>
'{' >> (qi::int_ % ',') >> '}' >>
".*" >>
'{' >> (qi::int_ % ',') >> '}' >>
')'
)[qi::_pass=phx::bind(
[](std::vector<int> const& vec1, std::vector<int> const& vec2, int& result) {
if(vec1.size() != vec2.size())
return false;
result = std::inner_product(boost::begin(vec1), boost::end(vec1), boost::begin(vec2), 0);
return true;
},
qi::_1, qi::_2, qi::_val
)];
int attr = 0;
if( qi::phrase_parse(boost::begin(input), boost::end(input), ruleSum >> qi::eoi, qi::ascii::space, attr) ) {
std::cout<<"Match! result = "<<attr<<std::endl;
} else {
std::cout<<"Not match!"<<std::endl;
}
}
精神x3,没有这样的qi::_1 ... qi::_N。我应该使用一对向量作为属性吗?解析类似这种内积的推荐方法是什么?
namespace inner_product {
x3::rule<struct idInnerProduct, int> const ruleInnerProduct("InnerProduct");
auto const ruleInnerProduct_def =
(
x3::rule<struct _, std::pair<std::vector<int>, std::vector<int>>>{} =
x3::lit("SUM") >> '(' >>
'{' >> (x3::int_ % ',') >> '}' >>
".*" >>
'{' >> (x3::int_ % ',') >> '}' >>
')'
)[([](auto& ctx){
if(_attr(ctx).first.size() != _attr(ctx).second.size()) {
_pass(ctx) = false;
} else {
x3::_val(ctx) = std::inner_product(
boost::begin(x3::_attr(ctx).first),
boost::end(x3::_attr(ctx).first),
boost::begin(x3::_attr(ctx).second),
0
);
}
})];
BOOST_SPIRIT_DEFINE(ruleInnerProduct)
}
该属性是一个融合序列。它的成员是 vector<int>
.
融合序列不是一对,所以不能使用.first
或.second
。
我会写:
void Test(std::string const& input) {
namespace x3 = boost::spirit::x3;
auto ruleSum = x3::rule<struct _, int> {} =
(
x3::lit("SUM") >> '(' >>
'{' >> (x3::int_ % ',') >> '}' >> ".*" >>
'{' >> (x3::int_ % ',') >> '}' >>
')'
)[( [](auto& ctx) {
using boost::fusion::at_c;
// dissect context
auto& pass = x3::_pass(ctx);
auto& result = x3::_val(ctx);
std::vector<int> const& vec1 = at_c<0>(x3::_attr(ctx));
std::vector<int> const& vec2 = at_c<1>(x3::_attr(ctx));
// do the work
pass = (vec1.size() == vec2.size());
if (pass)
result = std::inner_product(boost::begin(vec1), boost::end(vec1), boost::begin(vec2), 0);
})
];
int attr = 0;
if( x3::phrase_parse(boost::begin(input), boost::end(input), ruleSum >> x3::eoi, x3::ascii::space, attr) ) {
std::cout<<"Match! result = "<<attr<<std::endl;
} else {
std::cout<<"Not match!"<<std::endl;
}
}
打印:
Match! result = 32