I have below simple grammar:
namespace parser {
using x3::lexeme;
using x3::lit;
using x3::ascii::char_;
using my_attr = std::pair<boost::optional<std::string>, std::string>;
x3::rule<class ncname_tok, std::string> ncname = "ncname-token";
x3::rule<class qname_tok, my_attr> qname = "qname";
auto ncname_def = lexeme[*(char_ - ':')];
auto qname_def = -( ncname >> ':' ) >> ncname;
BOOST_SPIRIT_DEFINE (ncname, qname);
}
The expectation is to parse strings like prefix:data
and noprefix
. In the first case ("prefix:data"), with the above grammar I am expecting both members of my_attr
to be populated and this works as expected.
But in the second case ("noprefix"), I expect only my_attr.second
to be populated. But, I am seeing that both first
and second
is populated with the same data i.e. "noprefix". Is this how its supposed to work ? The behaviour is not intuitive.
Full source:
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <string>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace x3 = boost::spirit::x3;
namespace parser {
using x3::lexeme;
using x3::lit;
using x3::ascii::char_;
using my_attr = std::pair<boost::optional<std::string>, std::string>;
x3::rule<class ncname_tok, std::string> ncname = "ncname-token";
x3::rule<class qname_tok, my_attr> qname = "qname";
auto ncname_def = lexeme[*(char_ - ':')];
auto qname_def = -( ncname >> ':' ) >> ncname;
BOOST_SPIRIT_DEFINE (ncname, qname);
}
int main() {
std::string input("just-go");
std::string::iterator strbegin = input.begin();
parser::my_attr p;
x3::parse(strbegin, input.end(),
parser::qname,
p);
if (p.first) {
std::cout << "There should be no prefix: " << p.first << std::endl;
}
std::cout << "local name: " << p.second << std::endl;
return 0;
}