2

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;
}
Arunmu
  • 6,837
  • 1
  • 24
  • 46
  • `ncname` is allowed to match nothing and consider itself a successful match. I.e., it can _never_ fail. You probably want to use `+` rather than `*` when defining it. ;-] – ildjarn Mar 26 '17 at 13:37
  • @ildjarn That makes sense. Thanks. – Arunmu Mar 26 '17 at 13:47

0 Answers0