#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;
}
I'm expecting the output of this program is,
n1 = 1
n2 = 2
Match! result = 1+2
But the output is actually very strange for n2,
n1 = 1
n2 = 1+2
Match! result = 1+2
Why is the second number's attribute "1+2" instead of just "2"?
I know there are some other ways to parse this expression such as using qi::int_. I'm just wondering why do I get this strange attribute from it. Thanks!
Backtracking doesn't undo changes to container attributes. Adjacent compatible parser expressions bind to the same container attribute.
Both attributes get bound to the same container attribute (
result
) which means you are printing the same variable twice.If you didn't want that, be explicit, e.g.
Live On Coliru
Prints
Now I don't know what you want to achieve, but this could be close:
Live On Coliru
Prints
BONUS
A little more separation of concern:
Live On Coliru