X3: Comment créer un parsingur pour lire dans des ensembles?

Comment créer une règle pour lire des nombres entiers par ensembles de 3. C’est-à-dire, …

1 2 3 OK, 1 set of 3 ints 1 2 3 4 5 6 OK, 2 sets of 3 ints 1 2 3 4 5 ERROR, 1 set of 3 ints, 1 short for 2nd 1 2 3 4 5 6 7 8 9 OK, 3 sets of 3 ints 1 2 3 4 5 6 7 8 9 10 ERROR, 3 sets of 3 ints, 1 short for 4th 

Je rencontre un problème avec la structure fusion adapt (comment faire en sorte que le nombre de arguments soit variable)

 BOOST_FUSION_ADAPT_STRUCT(client::ast::number, n1, n2, n3, n4, n5, n6) 

Et je ne sais pas pourquoi cette règle ne fonctionnerait pas.

 ... = *(int_ >> int_ >> int_); 

Voici ma tentative … http://coliru.stacked-crooked.com/a/cb10e8096c95fc55

 //#define BOOST_SPIRIT_X3_DEBUG #include  #include  #include  #include  namespace client { namespace ast { struct number { int n1, n2, n3, n4, n5, n6; }; struct comment { std::ssortingng text; bool dummy; }; struct input { std::vector comments; std::vector numbers; }; } } BOOST_FUSION_ADAPT_STRUCT(client::ast::comment, text, dummy) BOOST_FUSION_ADAPT_STRUCT(client::ast::number, n1, n2, n3) // , n4, n5, n6) error BOOST_FUSION_ADAPT_STRUCT(client::ast::input, comments, numbers) namespace client { namespace parser { namespace x3 = boost::spirit::x3; using namespace x3; typedef std::ssortingng::const_iterator It; using namespace x3; auto const comment = rule {"comment"} = lexeme[*(char_ - eol)] >> attr(false); auto const number = rule {"number"} = int_ >> int_ >> int_; // auto const number = rule {"number"} = *(int_ >> int_ >> int_); error auto lines = [](auto p) { return *(p >> eol); }; auto const input = repeat(1)[comment] >> eol >> lines(number); } } int main() { namespace x3 = boost::spirit::x3; std::ssortingng const iss("any char ssortingng here\n1 2 3\n1 2 3 4 5 6"); auto iter = iss.begin(), eof = iss.end(); client::ast::input types; bool ok = phrase_parse(iter, eof, client::parser::input, x3::blank, types); if (iter != eof) { std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n"; } std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter) / iss.size()) << "%\n"; std::cout << "ok = " << ok << std::endl; for (auto& item : types.comments) { std::cout << "comment: " << boost::fusion::as_deque(item) << "\n"; } for (auto& item : types.numbers) { std::cout << "number: " << boost::fusion::as_deque(item) << "\n"; } } 

Impression

 Parsed: 71.0526% ok = 1 comment: (any char ssortingng here 0) number: (1 2 3) 

L’opérateur Kleene-star synthétise dans un atsortingbut de conteneur (docs show: vector )

Votre number structure n’est pas un atsortingbut conteneur. Alors.

En outre, ce que vous voulez réaliser n’est pas clair. Votre structure est supposée être de 6 ints, mais vous voulez parsingr des groupes de 3? Quel est le sens des groupes? Je ferais probablement:

 struct number { struct group { int n1, n2, n3; }; std::vector groups; }; BOOST_FUSION_ADAPT_STRUCT(client::ast::number::group, n1, n2, n3) BOOST_FUSION_ADAPT_STRUCT(client::ast::number, groups) 

Ceci est alors compatible avec l’expression de l’parsingur

  *(int_ >> int_ >> int_) 

Démo en direct

Deux notes:

  1. l’attibrute factice était à nouveau nécessaire (envisagez d’ using number = std::vector; )
  2. \n manquait à la fin de la saisie (pensez à eol | eoi )

Live On Coliru

 //#define BOOST_SPIRIT_X3_DEBUG #include  #include  #include  #include  namespace client { namespace ast { struct number { struct group { int n1, n2, n3; }; std::vector groups; bool dummy; }; struct comment { std::ssortingng text; bool dummy; }; struct input { std::vector comments; std::vector numbers; }; } } BOOST_FUSION_ADAPT_STRUCT(client::ast::comment, text, dummy) BOOST_FUSION_ADAPT_STRUCT(client::ast::number::group, n1, n2, n3) BOOST_FUSION_ADAPT_STRUCT(client::ast::number, groups, dummy) BOOST_FUSION_ADAPT_STRUCT(client::ast::input, comments, numbers) namespace client { namespace parser { namespace x3 = boost::spirit::x3; using namespace x3; typedef std::ssortingng::const_iterator It; using namespace x3; auto const comment = rule {"comment"} = lexeme[*(char_ - eol)] >> attr(false); auto const number = rule {"number"} = *(int_ >> int_ >> int_) >> attr(false); auto lines = [](auto p) { return *(p >> eol); }; auto const input = repeat(1)[comment] >> eol >> lines(number); } } int main() { namespace x3 = boost::spirit::x3; std::ssortingng const iss("any char ssortingng here\n1 2 3\n1 2 3 4 5 6\n"); auto iter = iss.begin(), eof = iss.end(); client::ast::input types; bool ok = phrase_parse(iter, eof, client::parser::input, x3::blank, types); if (iter != eof) { std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n"; } std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter) / iss.size()) << "%\n"; std::cout << "ok = " << ok << std::endl; for (auto &item : types.comments) { std::cout << "comment: " << boost::fusion::as_deque(item) << "\n"; } for (auto& item : types.numbers) { std::cout << "number: "; for (auto& g : item.groups) std::cout << boost::fusion::as_deque(g) << " "; std::cout << "\n"; } } 

Impressions

 Parsed: 100% ok = 1 comment: (any char ssortingng here 0) number: (1 2 3) number: (1 2 3) (4 5 6)