/** * Copyright (C) 2024 T. Zachary Laine * * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ #include #include using namespace boost::parser; struct s0_rule_tag {}; struct s1_rule_a_tag {}; struct s1_rule_b_tag {}; struct s2_rule_a_tag {}; struct s2_rule_b_tag {}; struct s0 { s0() = default; s0(int i, std::string str, std::vector vec) : i_(i), str_(std::move(str)), vec_(std::move(vec)) {} int i() const { return i_; } std::string str() const { return str_; } std::vector vec() const { return vec_; } private: int i_; std::string str_; std::vector vec_; }; using s0_tuple = tuple>; auto s0_parser = "s0" >> int_ >> lexeme[+(char_ - ' ')] >> *int_; callback_rule s0_rule = "s0_rule"; auto s0_rule_def = s0_parser; struct s1 { s1() = default; s1(int i, std::string str, std::vector vec) : i_(i), str_(std::move(str)), vec_(std::move(vec)) {} s1(int i, double str, std::vector vec) : i_(i), str_(str), vec_(std::move(vec)) {} int i() const { return i_; } std::variant str() const { return str_; } std::vector vec() const { return vec_; } private: int i_; std::variant str_; std::vector vec_; }; using s1_tuple = tuple, std::vector>; auto s1_parser_a = "s1" >> int_ >> lexeme[+(char_ - ' ')] >> *int_; auto s1_parser_b = "s1" >> int_ >> double_ >> *int_; callback_rule s1_rule_a = "s1_rule_a"; callback_rule s1_rule_b = "s1_rule_b"; auto s1_rule_a_def = s1_parser_a; auto s1_rule_b_def = s1_parser_b; struct s2 { s2() = default; s2(int i, std::string str, std::optional> vec) : i_(i), str_(std::move(str)), vec_(std::move(vec)) {} int i() const { return i_; } std::string str() const { return str_; } std::optional> vec() const { return vec_; } private: int i_; std::string str_; std::optional> vec_; }; using s2_tuple = tuple>>; auto s2_parser_a = "s2" >> int_ >> lexeme[+(char_ - ' ')] >> *int_; auto s2_parser_b = "s2" >> int_ >> lexeme[+(char_ - ' ')] >> -+int_; callback_rule s2_rule_a = "s2_rule_a"; callback_rule s2_rule_b = "s2_rule_b"; auto s2_rule_a_def = s2_parser_a; auto s2_rule_b_def = s2_parser_b; BOOST_PARSER_DEFINE_RULES(s0_rule, s1_rule_a, s1_rule_b, s2_rule_a, s2_rule_b); struct callbacks_t { void operator()(s0_rule_tag, s0 s) const { s0s.push_back(std::move(s)); } void operator()(s1_rule_a_tag, s1 s) const { s1s.push_back(std::move(s)); } void operator()(s1_rule_b_tag, s1 s) const { s1s.push_back(std::move(s)); } void operator()(s2_rule_a_tag, s2 s) const { s2s.push_back(std::move(s)); } void operator()(s2_rule_b_tag, s2 s) const { s2s.push_back(std::move(s)); } mutable std::vector s0s; mutable std::vector s1s; mutable std::vector s2s; }; int main() { // std_type_from_tuple { { constexpr auto parser = lexeme[+(char_ - ' ')] >> uint_ >> uint_; std::string out; auto result = parse("something 4 5", parser, ws, out); BOOST_TEST(result); BOOST_TEST(out == "thing"); } { constexpr auto p = lexeme[+(char_ - ' ')] >> uint_ >> uint_; constexpr auto parser = +p >> -p; std::vector out; auto result = parse("something 4 5 some 0 2", parser, ws, out); BOOST_TEST(result); BOOST_TEST(out.size() == 2u); BOOST_TEST(out[0] == "thing"); BOOST_TEST(out[1] == "so"); } { constexpr auto p = lexeme[+(char_ - ' ')] >> uint_ >> uint_; constexpr auto parser = -p; std::optional out; auto result = parse("something 4 5", parser, ws, out); BOOST_TEST(result); BOOST_TEST(out); BOOST_TEST(*out == "thing"); } { constexpr auto parser = lexeme[+(char_ - ' ')] >> uint_ >> uint_; std::optional out; auto result = parse("something 4 5", parser, ws, out); BOOST_TEST(result); BOOST_TEST(out); BOOST_TEST(*out == "thing"); } { constexpr auto parser = uint_ >> char_ >> char_; std::vector out; auto result = parse("4 ab", parser, ws, out); BOOST_TEST(result); BOOST_TEST(out == std::vector({"ab", "ab", "ab", "ab"})); } } // seq_parser_struct_rule { //////////////////////////////////////////////////////////////////////////// // Parse-generated attribute. { std::optional result = parse("s0 42 text 1 2 3", s0_rule, ws); BOOST_TEST(result); s0 & struct_ = *result; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional const result = parse("s1 42 text 1 2 3", s1_rule_a, ws); BOOST_TEST(result); s1 const & struct_ = *result; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional const result = parse("s1 42 13.0 1 2 3", s1_rule_b, ws); BOOST_TEST(result); s1 const & struct_ = *result; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional const result = parse("s2 42 text 1 2 3", s2_rule_a, ws); BOOST_TEST(result); s2 const & struct_ = *result; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional const result = parse("s2 42 text 1 2 3", s2_rule_b, ws); BOOST_TEST(result); s2 const & struct_ = *result; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } // Use the rule as part of a larger parse. { std::optional> const result = parse("99 s0 42 text 1 2 3", int_ >> s0_rule, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(*result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional> const result = parse("99 s1 42 text 1 2 3", int_ >> s1_rule_a, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(*result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional> const result = parse("99 s1 42 13.0 1 2 3", int_ >> s1_rule_b, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(*result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional> const result = parse("99 s2 42 text 1 2 3", int_ >> s2_rule_a, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(*result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { std::optional> const result = parse("99 s2 42 text 1 2 3", int_ >> s2_rule_b, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(*result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } //////////////////////////////////////////////////////////////////////////// // Pass attribute to parse. { s0 struct_; BOOST_TEST(parse("s0 42 text 1 2 3", s0_rule, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s1 struct_; BOOST_TEST(parse("s1 42 text 1 2 3", s1_rule_a, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s1 struct_; BOOST_TEST(parse("s1 42 13.0 1 2 3", s1_rule_b, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s2 struct_; BOOST_TEST(parse("s2 42 text 1 2 3", s2_rule_a, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s2 struct_; BOOST_TEST(parse("s2 42 text 1 2 3", s2_rule_b, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } // Use the rule as part of a larger parse. { tuple result; BOOST_TEST(parse("99 s0 42 text 1 2 3", int_ >> s0_rule, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { tuple result; BOOST_TEST(parse("99 s1 42 text 1 2 3", int_ >> s1_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { tuple result; BOOST_TEST(parse("99 s1 42 13.0 1 2 3", int_ >> s1_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { tuple result; BOOST_TEST(parse("99 s2 42 text 1 2 3", int_ >> s2_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { tuple result; BOOST_TEST(parse("99 s2 42 text 1 2 3", int_ >> s2_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto struct_ = get(result, llong<1>{}); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } } // repeated_seq_parser_struct_rule { //////////////////////////////////////////////////////////////////////////// // Parse-generated attribute. { std::optional> result = parse("s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_rule, ws); BOOST_TEST(result); std::vector & structs_ = *result; BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional> const result = parse("s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_rule_a, ws); BOOST_TEST(result); std::vector const & structs_ = *result; BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[0].str()) == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[1].str()) == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional> const result = parse("s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_rule_b, ws); BOOST_TEST(result); std::vector const & structs_ = *result; BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[0].str()) == 13.0); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[1].str()) == 12.0); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional> const result = parse("s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_a, ws); BOOST_TEST(result); std::vector const & structs_ = *result; BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional> const result = parse("s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_b, ws); BOOST_TEST(result); std::vector const & structs_ = *result; BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } // Use the rule as part of a larger parse. { std::optional>> const result = parse("99 s0 42 text 1 2 3 s0 41 texty 1 3 2", int_ >> *s0_rule, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(*result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional>> const result = parse("99 s1 42 text 1 2 3 s1 41 texty 1 3 2", int_ >> *s1_rule_a, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(*result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[0].str()) == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[1].str()) == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional>> const result = parse("99 s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", int_ >> *s1_rule_b, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(*result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[0].str()) == 13.0); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[1].str()) == 12.0); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional>> const result = parse("99 s2 42 text 1 2 3 s2 41 texty 1 3 2", int_ >> *s2_rule_a, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(*result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::optional>> const result = parse("99 s2 42 text 1 2 3 s2 41 texty 1 3 2", int_ >> *s2_rule_b, ws); auto i_ = get(*result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(*result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } //////////////////////////////////////////////////////////////////////////// // Pass attribute to parse. { std::vector structs_; BOOST_TEST(parse( "s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_rule, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_rule_a, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[0].str()) == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[1].str()) == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_rule_b, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[0].str()) == 13.0); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[1].str()) == 12.0); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_a, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_b, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } // Use the rule as part of a larger parse. { tuple> result; BOOST_TEST(parse( "99 s0 42 text 1 2 3 s0 41 texty 1 3 2", int_ >> *s0_rule, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { tuple> result; BOOST_TEST(parse( "99 s1 42 text 1 2 3 s1 41 texty 1 3 2", int_ >> *s1_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[0].str()) == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[1].str()) == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { tuple> result; BOOST_TEST(parse( "99 s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", int_ >> *s1_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[0].str()) == 13.0); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[1].str()) == 12.0); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { tuple> result; BOOST_TEST(parse( "99 s2 42 text 1 2 3 s2 41 texty 1 3 2", int_ >> *s2_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { tuple> result; BOOST_TEST(parse( "99 s2 42 text 1 2 3 s2 41 texty 1 3 2", int_ >> *s2_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); BOOST_TEST(i_ == 99); auto structs_ = get(result, llong<1>{}); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } } // seq_parser_struct_cb_rule { { callbacks_t callbacks; BOOST_TEST(callback_parse("s0 42 text 1 2 3", s0_rule, ws, callbacks)); BOOST_TEST(callbacks.s0s.size() == 1u); s0 const & struct_ = callbacks.s0s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse("s1 42 text 1 2 3", s1_rule_a, ws, callbacks)); BOOST_TEST(callbacks.s1s.size() == 1u); s1 const & struct_ = callbacks.s1s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse("s1 42 13.0 1 2 3", s1_rule_b, ws, callbacks)); BOOST_TEST(callbacks.s1s.size() == 1u); s1 const & struct_ = callbacks.s1s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse("s2 42 text 1 2 3", s2_rule_a, ws, callbacks)); BOOST_TEST(callbacks.s2s.size() == 1u); s2 const & struct_ = callbacks.s2s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse("s2 42 text 1 2 3", s2_rule_b, ws, callbacks)); BOOST_TEST(callbacks.s2s.size() == 1u); s2 const & struct_ = callbacks.s2s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } // Use the rule as part of a larger parse. { callbacks_t callbacks; BOOST_TEST(callback_parse( "99 s0 42 text 1 2 3", int_ >> s0_rule, ws, callbacks)); BOOST_TEST(callbacks.s0s.size() == 1u); s0 const & struct_ = callbacks.s0s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse( "99 s1 42 text 1 2 3", int_ >> s1_rule_a, ws, callbacks)); BOOST_TEST(callbacks.s1s.size() == 1u); s1 const & struct_ = callbacks.s1s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse( "99 s1 42 13.0 1 2 3", int_ >> s1_rule_b, ws, callbacks)); BOOST_TEST(callbacks.s1s.size() == 1u); s1 const & struct_ = callbacks.s1s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse( "99 s2 42 text 1 2 3", int_ >> s2_rule_a, ws, callbacks)); BOOST_TEST(callbacks.s2s.size() == 1u); s2 const & struct_ = callbacks.s2s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { callbacks_t callbacks; BOOST_TEST(callback_parse( "99 s2 42 text 1 2 3", int_ >> s2_rule_b, ws, callbacks)); BOOST_TEST(callbacks.s2s.size() == 1u); s2 const & struct_ = callbacks.s2s[0]; BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } } // parse_into_struct { { s0 struct_; BOOST_TEST(parse("s0 42 text 1 2 3", s0_parser, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s1 struct_; BOOST_TEST(parse("s1 42 text 1 2 3", s1_parser_a, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 0u); BOOST_TEST(std::get<0>(struct_.str()) == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s1 struct_; BOOST_TEST(parse("s1 42 13.0 1 2 3", s1_parser_b, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str().index() == 1u); BOOST_TEST(std::get<1>(struct_.str()) == 13.0); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s2 struct_; BOOST_TEST(parse("s2 42 text 1 2 3", s2_parser_a, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } { s2 struct_; BOOST_TEST(parse("s2 42 text 1 2 3", s2_parser_b, ws, struct_)); BOOST_TEST(struct_.i() == 42); BOOST_TEST(struct_.str() == "text"); BOOST_TEST(struct_.vec() == std::vector({1, 2, 3})); } } // repeated_parse_into_struct { { std::vector structs_; BOOST_TEST(parse( "s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_parser, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_parser_a, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[0].str()) == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 0u); BOOST_TEST(std::get<0>(structs_[1].str()) == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_parser_b, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[0].str()) == 13.0); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str().index() == 1u); BOOST_TEST(std::get<1>(structs_[1].str()) == 12.0); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_parser_a, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } { std::vector structs_; BOOST_TEST(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_parser_b, ws, structs_)); BOOST_TEST(structs_[0].i() == 42); BOOST_TEST(structs_[0].str() == "text"); BOOST_TEST(structs_[0].vec() == std::vector({1, 2, 3})); BOOST_TEST(structs_[1].i() == 41); BOOST_TEST(structs_[1].str() == "texty"); BOOST_TEST(structs_[1].vec() == std::vector({1, 3, 2})); } } return boost::report_errors(); }