#include <iostream>
#include <string>
#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.hpp>
namespace qi = boost::spirit::qi;
namespace test {
template< typename Rng,typename Expr >
bool parse(Rng const& rng,Expr const& expr) noexcept {
auto itBegin = boost::begin(rng);
auto itEnd = boost::end(rng);
try {
return qi::parse(itBegin,itEnd,expr);
} catch(qi::expectation_failure<decltype(itBegin)> const& exfail) {
exfail;
return false;
}
}
template< typename Rng,typename Expr,typename Attr >
bool parse(Rng const& rng,Expr const& expr,Attr& attr) noexcept {
auto itBegin = boost::begin(rng);
auto itEnd = boost::end(rng);
try {
return qi::parse(itBegin,itEnd,expr,attr);
} catch(qi::expectation_failure<decltype(itBegin)> const&) {
return false;
}
}
}
void print1(std::string const& s) {
std::cout<<"n1 = "<<s<<std::endl;
}
void print2(std::string const& s) {
std::cout<<"n2 = "<<s<<std::endl;
}
int main() {
qi::rule<std::string::const_iterator, std::string()> number = +qi::digit;
std::string input = "1+2";
std::string result;
if( test::parse(input, number[print1] >> *( qi::char_("+-") >> number[print2]) >> qi::eoi, result) ) {
std::cout<<"Match! result = "<<result<<std::endl;
} else {
std::cout<<"Not match!"<<std::endl;
}
return 0;
}
我期待这个节目的输出是,
n1 = 1
n2 = 2
Match! result = 1+2
但是n2的输出实际上非常奇怪,
n1 = 1
n2 = 1+2
Match! result = 1+2
为什么第二个数字属性&#34; 1 + 2&#34;而不只是&#34; 2&#34;?
我知道有一些其他方法可以解析这个表达式,比如使用qi :: int_。我只是想知道为什么我会从中获得这个奇怪的属性。谢谢!
答案 0 :(得分:3)
回溯不会撤消对容器属性的更改。相邻的兼容解析器表达式绑定到相同的容器属性。
两个属性都绑定到同一个容器属性(result
),这意味着您要打印两次相同的变量。
如果您不想要,请明确,例如
<强> Live On Coliru 强>
std::string result;
std::vector<std::string> v;
if( test::parse(input, number[px::bind(print1, qi::_1)] >> *qi::as_string[qi::char_("+-") >> number[print2]] >> qi::eoi, result, v) ) {
std::cout<<"Match! result = "<<result<<std::endl;
for (auto s : v)
std::cout << s << "\n";
} else {
打印
n1 = 1
n2 = +2
Match! result = 1
+2
现在我不知道你想要达到什么目标,但这可能很接近:
if (test::parse(input, qi::raw [number[print_("n1",_1)] > *(qi::char_("+-") >> number[print_("n2",_1)]) ] >> qi::eoi, result)) {
<强> Live On Coliru 强>
#include <iostream>
#include <string>
#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.hpp>
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
namespace test {
template< typename Rng,typename Expr,typename... Attr >
bool parse(Rng const& rng,Expr const& expr,Attr&... attr) noexcept {
auto itBegin = boost::begin(rng);
auto itEnd = boost::end(rng);
try {
return qi::parse(itBegin,itEnd,expr,attr...);
} catch(qi::expectation_failure<decltype(itBegin)> const&) {
return false;
}
}
}
void printn(std::string const& label, std::string const& s) {
std::cout << label << " = " << s << std::endl;
}
BOOST_PHOENIX_ADAPT_FUNCTION(void, print_, printn, 2)
int main() {
qi::rule<std::string::const_iterator, std::string()> number = +qi::digit;
std::string input = "1+2";
std::string result;
using qi::_1;
if (test::parse(input, qi::raw [number[print_("n1",_1)] > *(qi::char_("+-") >> number[print_("n2",_1)]) ] >> qi::eoi, result)) {
std::cout<<"Match! result = "<<result<<std::endl;
} else {
std::cout<<"Not match!"<<std::endl;
}
return 0;
}
打印
n1 = 1
n2 = 2
Match! result = 1+2
更多关注点分离:
<强> Live On Coliru 强>
void printn(int n, std::string const& s) {
std::cout << "n" << n << " = " << s << std::endl;
}
BOOST_PHOENIX_ADAPT_FUNCTION(void, print_, printn, 2)
int main() {
qi::rule<std::string::const_iterator, std::string()> number;
int n = 1;
number %= qi::as_string[+qi::digit] [print_(px::ref(n)++, qi::_1)];
std::string input = "1+2";
std::string result;
if (test::parse(input, qi::raw [number > *(qi::char_("+-") >> number) ] >> qi::eoi, result)) {
std::cout << "Match! result = " << result << std::endl;
} else {
std::cout << "Not match!" << std::endl;
}
return 0;
}