/** * Copyright (C) 2023 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 #if __has_include() #define TEST_BOOST_OPTIONAL 1 #include #else #define TEST_BOOST_OPTIONAL 0 #endif #if __has_include() #define TEST_BOOST_VARIANT 1 #include #include #else #define TEST_BOOST_VARIANT 0 #endif #if __has_include() #define TEST_BOOST_VARIANT2 1 #include #else #define TEST_BOOST_VARIANT2 0 #endif #include using namespace boost::parser; #if TEST_BOOST_OPTIONAL template constexpr bool boost::parser::enable_optional> = true; #endif 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 { 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 { int i_; std::variant str_; std::vector vec_; }; #if TEST_BOOST_VARIANT struct s1_boost_variant { int i_; boost::variant str_; std::vector vec_; }; #endif #if TEST_BOOST_VARIANT struct s1_boost_variant2 { int i_; boost::variant2::variant str_; std::vector vec_; }; #endif 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; #if TEST_BOOST_VARIANT callback_rule s1_boost_variant_rule_a = "s1_rule_a"; callback_rule s1_boost_variant_rule_b = "s1_rule_b"; auto s1_boost_variant_rule_a_def = s1_parser_a; auto s1_boost_variant_rule_b_def = s1_parser_b; BOOST_PARSER_DEFINE_RULES(s1_boost_variant_rule_a, s1_boost_variant_rule_b); #endif #if TEST_BOOST_VARIANT2 callback_rule s1_boost_variant2_rule_a = "s1_rule_a"; callback_rule s1_boost_variant2_rule_b = "s1_rule_b"; auto s1_boost_variant2_rule_a_def = s1_parser_a; auto s1_boost_variant2_rule_b_def = s1_parser_b; BOOST_PARSER_DEFINE_RULES(s1_boost_variant2_rule_a, s1_boost_variant2_rule_b); #endif struct s2 { int i_; std::string str_; std::optional> vec_; }; #if TEST_BOOST_OPTIONAL struct s2_boost_optional { int i_; std::string str_; boost::optional> vec_; }; #endif 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; #if TEST_BOOST_OPTIONAL callback_rule s2_boost_optional_rule_a = "s2_rule_a"; callback_rule s2_boost_optional_rule_b = "s2_rule_b"; auto s2_boost_optional_rule_a_def = s2_parser_a; auto s2_boost_optional_rule_b_def = s2_parser_b; BOOST_PARSER_DEFINE_RULES(s2_boost_optional_rule_a, s2_boost_optional_rule_b); #endif BOOST_PARSER_DEFINE_RULES(s0_rule, s1_rule_a, s1_rule_b, s2_rule_a, s2_rule_b); struct s0_like { int64_t i_; std::string str_; std::vector vec_; }; TEST(struct_tuple, seq_parser_struct_rule) { //////////////////////////////////////////////////////////////////////////// // Parse-generated attribute. { std::optional result = parse("s0 42 text 1 2 3", s0_rule, ws); EXPECT_TRUE(result); s0 & struct_ = *result; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { std::optional const result = parse("s1 42 text 1 2 3", s1_rule_a, ws); EXPECT_TRUE(result); s1 const & struct_ = *result; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { std::optional const result = parse("s1 42 13.0 1 2 3", s1_rule_b, ws); EXPECT_TRUE(result); s1 const & struct_ = *result; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { std::optional const result = parse("s2 42 text 1 2 3", s2_rule_a, ws); EXPECT_TRUE(result); s2 const & struct_ = *result; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { std::optional const result = parse("s2 42 text 1 2 3", s2_rule_b, ws); EXPECT_TRUE(result); s2 const & struct_ = *result; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto struct_ = get(*result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto struct_ = get(*result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto struct_ = get(*result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto struct_ = get(*result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto struct_ = get(*result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } //////////////////////////////////////////////////////////////////////////// // Pass attribute to parse. { s0 struct_; EXPECT_TRUE(parse("s0 42 text 1 2 3", s0_rule, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1 struct_; EXPECT_TRUE(parse("s1 42 text 1 2 3", s1_rule_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1 struct_; EXPECT_TRUE(parse("s1 42 13.0 1 2 3", s1_rule_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #if TEST_BOOST_VARIANT { s1_boost_variant struct_; EXPECT_TRUE( parse("s1 42 text 1 2 3", s1_boost_variant_rule_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).which(), 0u); EXPECT_EQ(boost::get(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1_boost_variant struct_; EXPECT_TRUE( parse("s1 42 13.0 1 2 3", s1_boost_variant_rule_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif #if TEST_BOOST_VARIANT2 { s1_boost_variant2 struct_; EXPECT_TRUE( parse("s1 42 text 1 2 3", s1_boost_variant2_rule_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(boost::variant2::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1_boost_variant2 struct_; EXPECT_TRUE( parse("s1 42 13.0 1 2 3", s1_boost_variant2_rule_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif { s2 struct_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_rule_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s2 struct_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_rule_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #if TEST_BOOST_OPTIONAL { s2_boost_optional struct_; EXPECT_TRUE( parse("s2 42 text 1 2 3", s2_boost_optional_rule_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s2_boost_optional struct_; EXPECT_TRUE( parse("s2 42 text 1 2 3", s2_boost_optional_rule_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif // Use the rule as part of a larger parse. { tuple result; EXPECT_TRUE(parse("99 s0 42 text 1 2 3", int_ >> s0_rule, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { tuple result; EXPECT_TRUE(parse("99 s1 42 text 1 2 3", int_ >> s1_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { tuple result; EXPECT_TRUE(parse("99 s1 42 13.0 1 2 3", int_ >> s1_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #if TEST_BOOST_VARIANT { tuple result; EXPECT_TRUE(parse( "99 s1 42 text 1 2 3", int_ >> s1_boost_variant_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).which(), 0u); EXPECT_EQ(boost::get(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { tuple result; EXPECT_TRUE(parse( "99 s1 42 13.0 1 2 3", int_ >> s1_boost_variant_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif #if TEST_BOOST_VARIANT2 { tuple result; EXPECT_TRUE(parse( "99 s1 42 text 1 2 3", int_ >> s1_boost_variant2_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(boost::variant2::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { tuple result; EXPECT_TRUE(parse( "99 s1 42 13.0 1 2 3", int_ >> s1_boost_variant2_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif { tuple result; EXPECT_TRUE(parse("99 s2 42 text 1 2 3", int_ >> s2_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { tuple result; EXPECT_TRUE(parse("99 s2 42 text 1 2 3", int_ >> s2_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #if TEST_BOOST_OPTIONAL { tuple result; EXPECT_TRUE(parse( "99 s2 42 text 1 2 3", int_ >> s2_boost_optional_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { tuple result; EXPECT_TRUE(parse( "99 s2 42 text 1 2 3", int_ >> s2_boost_optional_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto struct_ = get(result, llong<1>{}); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif } TEST(struct_tuple, 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); EXPECT_TRUE(result); std::vector & structs_ = *result; EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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); EXPECT_TRUE(result); std::vector const & structs_ = *result; EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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); EXPECT_TRUE(result); std::vector const & structs_ = *result; EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), 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); EXPECT_TRUE(result); std::vector const & structs_ = *result; EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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); EXPECT_TRUE(result); std::vector const & structs_ = *result; EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(*result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(*result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(*result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(*result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), 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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(*result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } //////////////////////////////////////////////////////////////////////////// // Pass attribute to parse. { std::vector structs_; EXPECT_TRUE(parse( "s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_rule, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_rule_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_rule_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #if TEST_BOOST_VARIANT { std::vector structs_; EXPECT_TRUE(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_boost_variant_rule_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).which(), 0u); EXPECT_EQ( boost::get(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 0u); EXPECT_EQ( boost::get(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_boost_variant_rule_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #endif #if TEST_BOOST_VARIANT2 { std::vector structs_; EXPECT_TRUE(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_boost_variant2_rule_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ( boost::variant2::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ( boost::variant2::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_boost_variant2_rule_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #endif { std::vector structs_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #if TEST_BOOST_OPTIONAL { std::vector structs_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_boost_optional_rule_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_boost_optional_rule_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #endif // Use the rule as part of a larger parse. { tuple> result; EXPECT_TRUE(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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { tuple> result; EXPECT_TRUE(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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { tuple> result; EXPECT_TRUE(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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #if TEST_BOOST_VARIANT { tuple> result; EXPECT_TRUE(parse( "99 s1 42 text 1 2 3 s1 41 texty 1 3 2", int_ >> *s1_boost_variant_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).which(), 0u); EXPECT_EQ( boost::get(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 0u); EXPECT_EQ( boost::get(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { tuple> result; EXPECT_TRUE(parse( "99 s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", int_ >> *s1_boost_variant_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #endif #if TEST_BOOST_VARIANT2 { tuple> result; EXPECT_TRUE(parse( "99 s1 42 text 1 2 3 s1 41 texty 1 3 2", int_ >> *s1_boost_variant2_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ( boost::variant2::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ( boost::variant2::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { tuple> result; EXPECT_TRUE(parse( "99 s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", int_ >> *s1_boost_variant2_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #endif { tuple> result; EXPECT_TRUE(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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { tuple> result; EXPECT_TRUE(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>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #if TEST_BOOST_OPTIONAL { tuple> result; EXPECT_TRUE(parse( "99 s2 42 text 1 2 3 s2 41 texty 1 3 2", int_ >> *s2_boost_optional_rule_a, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { tuple> result; EXPECT_TRUE(parse( "99 s2 42 text 1 2 3 s2 41 texty 1 3 2", int_ >> *s2_boost_optional_rule_b, ws, result)); auto i_ = get(result, llong<0>{}); EXPECT_EQ(i_, 99); auto structs_ = get(result, llong<1>{}); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } #endif } 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; }; TEST(struct_tuple, seq_parser_struct_cb_rule) { { callbacks_t callbacks; EXPECT_TRUE(callback_parse("s0 42 text 1 2 3", s0_rule, ws, callbacks)); EXPECT_EQ(callbacks.s0s.size(), 1u); s0 const & struct_ = callbacks.s0s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse("s1 42 text 1 2 3", s1_rule_a, ws, callbacks)); EXPECT_EQ(callbacks.s1s.size(), 1u); s1 const & struct_ = callbacks.s1s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse("s1 42 13.0 1 2 3", s1_rule_b, ws, callbacks)); EXPECT_EQ(callbacks.s1s.size(), 1u); s1 const & struct_ = callbacks.s1s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse("s2 42 text 1 2 3", s2_rule_a, ws, callbacks)); EXPECT_EQ(callbacks.s2s.size(), 1u); s2 const & struct_ = callbacks.s2s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse("s2 42 text 1 2 3", s2_rule_b, ws, callbacks)); EXPECT_EQ(callbacks.s2s.size(), 1u); s2 const & struct_ = callbacks.s2s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } // Use the rule as part of a larger parse. { callbacks_t callbacks; EXPECT_TRUE(callback_parse( "99 s0 42 text 1 2 3", int_ >> s0_rule, ws, callbacks)); EXPECT_EQ(callbacks.s0s.size(), 1u); s0 const & struct_ = callbacks.s0s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse( "99 s1 42 text 1 2 3", int_ >> s1_rule_a, ws, callbacks)); EXPECT_EQ(callbacks.s1s.size(), 1u); s1 const & struct_ = callbacks.s1s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse( "99 s1 42 13.0 1 2 3", int_ >> s1_rule_b, ws, callbacks)); EXPECT_EQ(callbacks.s1s.size(), 1u); s1 const & struct_ = callbacks.s1s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse( "99 s2 42 text 1 2 3", int_ >> s2_rule_a, ws, callbacks)); EXPECT_EQ(callbacks.s2s.size(), 1u); s2 const & struct_ = callbacks.s2s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { callbacks_t callbacks; EXPECT_TRUE(callback_parse( "99 s2 42 text 1 2 3", int_ >> s2_rule_b, ws, callbacks)); EXPECT_EQ(callbacks.s2s.size(), 1u); s2 const & struct_ = callbacks.s2s[0]; EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } } TEST(struct_tuple, parse_into_struct) { // tuples { s0_tuple tuple_; EXPECT_TRUE(parse("s0 42 text 1 2 3", s0_parser, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s1_tuple tuple_; EXPECT_TRUE(parse("s1 42 text 1 2 3", s1_parser_a, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(tuple_, llong<1>{})), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s1_tuple tuple_; EXPECT_TRUE(parse("s1 42 13.0 1 2 3", s1_parser_b, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(tuple_, llong<1>{})), 13.0); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s2_tuple tuple_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_parser_a, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s2_tuple tuple_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_parser_b, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } // structs { s0 struct_; EXPECT_TRUE(parse("s0 42 text 1 2 3", s0_parser, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s0_like struct_; EXPECT_TRUE(parse("s0 42 text 1 2 3", s0_parser, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1 struct_; EXPECT_TRUE(parse("s1 42 text 1 2 3", s1_parser_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1 struct_; EXPECT_TRUE(parse("s1 42 13.0 1 2 3", s1_parser_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #if TEST_BOOST_VARIANT { s1_boost_variant struct_; EXPECT_TRUE(parse("s1 42 text 1 2 3", s1_parser_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).which(), 0u); EXPECT_EQ(boost::get(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1_boost_variant struct_; EXPECT_TRUE(parse("s1 42 13.0 1 2 3", s1_parser_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).which(), 1u); EXPECT_EQ(boost::get(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif #if TEST_BOOST_VARIANT2 { s1_boost_variant2 struct_; EXPECT_TRUE(parse("s1 42 text 1 2 3", s1_parser_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 0u); EXPECT_EQ(boost::variant2::get<0>(get(struct_, llong<1>{})), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s1_boost_variant2 struct_; EXPECT_TRUE(parse("s1 42 13.0 1 2 3", s1_parser_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}).index(), 1u); EXPECT_EQ(boost::variant2::get<1>(get(struct_, llong<1>{})), 13.0); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif { s2 struct_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_parser_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s2 struct_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_parser_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #if TEST_BOOST_OPTIONAL { s2_boost_optional struct_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_parser_a, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(*get(struct_, llong<2>{}), std::vector({1, 2, 3})); } { s2_boost_optional struct_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_parser_b, ws, struct_)); EXPECT_EQ(get(struct_, llong<0>{}), 42); EXPECT_EQ(get(struct_, llong<1>{}), "text"); EXPECT_EQ(*get(struct_, llong<2>{}), std::vector({1, 2, 3})); } #endif } TEST(struct_tuple, repeated_parse_into_struct) { // tuples { std::vector tuples_; EXPECT_TRUE(parse( "s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_parser, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_parser_a, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(tuples_[0], llong<1>{})), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(tuples_[1], llong<1>{})), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_parser_b, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(tuples_[0], llong<1>{})), 13.0); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(tuples_[1], llong<1>{})), 12.0); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_parser_a, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_parser_b, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } // structs { std::vector structs_; EXPECT_TRUE(parse( "s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_parser, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_parser, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_parser_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[0], llong<1>{})), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(structs_[1], llong<1>{})), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_parser_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[0], llong<1>{})), 13.0); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_parser_a, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector structs_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_parser_b, ws, structs_)); EXPECT_EQ(get(structs_[0], llong<0>{}), 42); EXPECT_EQ(get(structs_[0], llong<1>{}), "text"); EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(structs_[1], llong<0>{}), 41); EXPECT_EQ(get(structs_[1], llong<1>{}), "texty"); EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector({1, 3, 2})); } } TEST(struct_tuple, parse_into_tuple) { { s0_tuple tuple_; EXPECT_TRUE(parse("s0 42 text 1 2 3", s0_rule, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s1_tuple tuple_; EXPECT_TRUE(parse("s1 42 text 1 2 3", s1_rule_a, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(tuple_, llong<1>{})), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s1_tuple tuple_; EXPECT_TRUE(parse("s1 42 13.0 1 2 3", s1_rule_b, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(tuple_, llong<1>{})), 13.0); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s2_tuple tuple_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_rule_a, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } { s2_tuple tuple_; EXPECT_TRUE(parse("s2 42 text 1 2 3", s2_rule_b, ws, tuple_)); EXPECT_EQ(get(tuple_, llong<0>{}), 42); EXPECT_EQ(get(tuple_, llong<1>{}), "text"); EXPECT_EQ(get(tuple_, llong<2>{}), std::vector({1, 2, 3})); } } TEST(struct_tuple, repeated_parse_into_tuple) { { std::vector tuples_; EXPECT_TRUE( parse("s0 42 text 1 2 3 s0 41 texty 1 3 2", *s0_rule, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s1 42 text 1 2 3 s1 41 texty 1 3 2", *s1_rule_a, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(tuples_[0], llong<1>{})), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}).index(), 0u); EXPECT_EQ(std::get<0>(get(tuples_[1], llong<1>{})), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s1 42 13.0 1 2 3 s1 41 12.0 1 3 2", *s1_rule_b, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(tuples_[0], llong<1>{})), 13.0); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}).index(), 1u); EXPECT_EQ(std::get<1>(get(tuples_[1], llong<1>{})), 12.0); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_a, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } { std::vector tuples_; EXPECT_TRUE(parse( "s2 42 text 1 2 3 s2 41 texty 1 3 2", *s2_rule_b, ws, tuples_)); EXPECT_EQ(get(tuples_[0], llong<0>{}), 42); EXPECT_EQ(get(tuples_[0], llong<1>{}), "text"); EXPECT_EQ(get(tuples_[0], llong<2>{}), std::vector({1, 2, 3})); EXPECT_EQ(get(tuples_[1], llong<0>{}), 41); EXPECT_EQ(get(tuples_[1], llong<1>{}), "texty"); EXPECT_EQ(get(tuples_[1], llong<2>{}), std::vector({1, 3, 2})); } }