mirror of
https://github.com/boostorg/parser.git
synced 2026-01-19 04:22:13 +00:00
Add support for parsing into attributes whose types are optionals or variants
other than the ones from std:: (e.g. boost::optional, boost::variant, and boost::variant2::variant). Fixes #53.
This commit is contained in:
@@ -23,6 +23,23 @@
|
||||
|
||||
namespace boost { namespace parser {
|
||||
|
||||
/** A variable template that indicates that type `T` is an optional-like
|
||||
type. */
|
||||
template<typename T>
|
||||
constexpr bool enable_optional = false;
|
||||
|
||||
/** A variable template that indicates that type `T` is an variant-like
|
||||
type. */
|
||||
template<typename T>
|
||||
constexpr bool enable_variant = false;
|
||||
|
||||
#ifndef BOOST_PARSER_DOXYGEN
|
||||
template<typename T>
|
||||
constexpr bool enable_optional<std::optional<T>> = true;
|
||||
template<typename... Ts>
|
||||
constexpr bool enable_variant<std::variant<Ts...>> = true;
|
||||
#endif
|
||||
|
||||
/** A placeholder type used to represent the absence of information,
|
||||
value, etc., inside semantic actions. For instance, calling
|
||||
`_locals(ctx)` in a semantic action associated with a parser that has
|
||||
@@ -906,18 +923,10 @@ namespace boost { namespace parser {
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct is_optional : std::false_type
|
||||
{};
|
||||
template<typename T>
|
||||
struct is_optional<std::optional<T>> : std::true_type
|
||||
{};
|
||||
constexpr bool is_optional_v = enable_optional<T>;
|
||||
|
||||
template<typename T>
|
||||
struct is_variant : std::false_type
|
||||
{};
|
||||
template<typename... T>
|
||||
struct is_variant<std::variant<T...>> : std::true_type
|
||||
{};
|
||||
constexpr bool is_variant_v = enable_variant<T>;
|
||||
|
||||
template<typename T>
|
||||
struct is_utf8_view : std::false_type
|
||||
@@ -1060,7 +1069,7 @@ namespace boost { namespace parser {
|
||||
// for tuple<t> and on for tuple<optional<T>>, is because
|
||||
// MSVC.
|
||||
using type =
|
||||
std::conditional_t<is_optional<T>::value, T, std::optional<T>>;
|
||||
std::conditional_t<is_optional_v<T>, T, std::optional<T>>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -2408,19 +2417,29 @@ namespace boost { namespace parser {
|
||||
remove_cv_ref_t<decltype(parser::get(x, llong<1>{}))>;
|
||||
if constexpr (!T::value) {
|
||||
return std::false_type{};
|
||||
} else if constexpr (
|
||||
is_optional_v<struct_elem> && is_optional_v<tuple_elem>) {
|
||||
using struct_opt_type = optional_type<struct_elem>;
|
||||
using tuple_opt_type = optional_type<tuple_elem>;
|
||||
using retval_t = decltype((*this)(
|
||||
result,
|
||||
detail::hl::make_tuple(
|
||||
std::declval<struct_opt_type &>(),
|
||||
std::declval<tuple_opt_type &>())));
|
||||
return retval_t{};
|
||||
} else if constexpr (std::is_convertible_v<
|
||||
tuple_elem &&,
|
||||
struct_elem>) {
|
||||
return std::true_type{};
|
||||
} else if constexpr (
|
||||
container<struct_elem> && container<tuple_elem>) {
|
||||
return detail::is_struct_compatible<
|
||||
range_value_t<struct_elem>,
|
||||
range_value_t<tuple_elem>>();
|
||||
return detail::is_struct_compatible<
|
||||
range_value_t<struct_elem>,
|
||||
range_value_t<tuple_elem>>();
|
||||
} else {
|
||||
return std::bool_constant<detail::is_struct_compatible<
|
||||
struct_elem,
|
||||
tuple_elem>()>{};
|
||||
return std::bool_constant<detail::is_struct_compatible<
|
||||
struct_elem,
|
||||
tuple_elem>()>{};
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2665,7 +2684,7 @@ namespace boost { namespace parser {
|
||||
: flags,
|
||||
retval);
|
||||
|
||||
if constexpr (detail::is_optional<Attribute>{}) {
|
||||
if constexpr (detail::is_optional_v<Attribute>) {
|
||||
detail::optional_type<Attribute> attr;
|
||||
detail::apply_parser(
|
||||
*this,
|
||||
@@ -3360,7 +3379,7 @@ namespace boost { namespace parser {
|
||||
indices;
|
||||
std::decay_t<decltype(parser::get(temp_result, llong<2>{}))>
|
||||
merged;
|
||||
if constexpr (detail::is_variant<Attribute>{}) {
|
||||
if constexpr (detail::is_variant_v<Attribute>) {
|
||||
detail::apply_parser(
|
||||
*this,
|
||||
use_cbs,
|
||||
@@ -3371,7 +3390,7 @@ namespace boost { namespace parser {
|
||||
detail::set_in_apply_parser(flags),
|
||||
success,
|
||||
retval);
|
||||
} else if constexpr (detail::is_optional<Attribute>{}) {
|
||||
} else if constexpr (detail::is_optional_v<Attribute>) {
|
||||
typename Attribute::value_type attr;
|
||||
call(
|
||||
use_cbs, first_, last, context, skip, flags, success, attr);
|
||||
|
||||
@@ -8,11 +8,23 @@
|
||||
|
||||
#include <boost/parser/parser.hpp>
|
||||
|
||||
#if __has_include(<boost/optional/optional.hpp>)
|
||||
#define TEST_BOOST_OPTIONAL 1
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#else
|
||||
#define TEST_BOOST_OPTIONAL 0
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
using namespace boost::parser;
|
||||
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
template<typename T>
|
||||
constexpr bool boost::parser::enable_optional<boost::optional<T>> = true;
|
||||
#endif
|
||||
|
||||
TEST(parser, basic)
|
||||
{
|
||||
@@ -156,6 +168,27 @@ TEST(parser, basic)
|
||||
first, boost::parser::detail::text::null_sentinel, parser_5, c));
|
||||
EXPECT_EQ(c, std::nullopt);
|
||||
}
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
{
|
||||
std::string str = "a";
|
||||
boost::optional<char> c;
|
||||
EXPECT_TRUE(parse(str, parser_5, c));
|
||||
EXPECT_EQ(c, 'a');
|
||||
}
|
||||
{
|
||||
std::string str = "z";
|
||||
boost::optional<char> c;
|
||||
EXPECT_FALSE(parse(str, parser_5, c));
|
||||
}
|
||||
{
|
||||
std::string str = "z";
|
||||
boost::optional<char> c;
|
||||
auto first = str.c_str();
|
||||
EXPECT_TRUE(prefix_parse(
|
||||
first, boost::parser::detail::text::null_sentinel, parser_5, c));
|
||||
EXPECT_EQ(c, boost::none);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(parser, int_uint)
|
||||
|
||||
@@ -8,11 +8,49 @@
|
||||
|
||||
#include <boost/parser/parser.hpp>
|
||||
|
||||
#if __has_include(<boost/optional/optional.hpp>)
|
||||
#define TEST_BOOST_OPTIONAL 1
|
||||
#include <boost/optional/optional.hpp>
|
||||
#else
|
||||
#define TEST_BOOST_OPTIONAL 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<boost/variant/variant.hpp>)
|
||||
#define TEST_BOOST_VARIANT 1
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#else
|
||||
#define TEST_BOOST_VARIANT 0
|
||||
#endif
|
||||
|
||||
#if __has_include(<boost/variant2/variant.hpp>)
|
||||
#define TEST_BOOST_VARIANT2 1
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#else
|
||||
#define TEST_BOOST_VARIANT2 0
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
using namespace boost::parser;
|
||||
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
template<typename T>
|
||||
constexpr bool boost::parser::enable_optional<boost::optional<T>> = true;
|
||||
#endif
|
||||
|
||||
#if TEST_BOOST_VARIANT
|
||||
template<typename... Ts>
|
||||
constexpr bool boost::parser::enable_optional<boost::variant<Ts...>> = true;
|
||||
#endif
|
||||
|
||||
#if TEST_BOOST_VARIANT2
|
||||
template<typename... Ts>
|
||||
constexpr bool boost::parser::enable_optional<boost::variant2::variant<Ts...>> =
|
||||
true;
|
||||
#endif
|
||||
|
||||
|
||||
struct s0_rule_tag
|
||||
{};
|
||||
@@ -46,6 +84,22 @@ struct s1
|
||||
std::variant<std::string, double> str_;
|
||||
std::vector<int> vec_;
|
||||
};
|
||||
#if TEST_BOOST_VARIANT
|
||||
struct s1_boost_variant
|
||||
{
|
||||
int i_;
|
||||
boost::variant<std::string, double> str_;
|
||||
std::vector<int> vec_;
|
||||
};
|
||||
#endif
|
||||
#if TEST_BOOST_VARIANT
|
||||
struct s1_boost_variant2
|
||||
{
|
||||
int i_;
|
||||
boost::variant2::variant<std::string, double> str_;
|
||||
std::vector<int> vec_;
|
||||
};
|
||||
#endif
|
||||
|
||||
using s1_tuple =
|
||||
tuple<int, std::variant<std::string, double>, std::vector<int>>;
|
||||
@@ -57,6 +111,24 @@ callback_rule<s1_rule_a_tag, s1> s1_rule_a = "s1_rule_a";
|
||||
callback_rule<s1_rule_b_tag, s1> 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<struct s1_bv_rule_a_tag, s1_boost_variant>
|
||||
s1_boost_variant_rule_a = "s1_rule_a";
|
||||
callback_rule<struct s1_bv_rule_b_tag, s1_boost_variant>
|
||||
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<struct s1_bv2_rule_a_tag, s1_boost_variant2>
|
||||
s1_boost_variant2_rule_a = "s1_rule_a";
|
||||
callback_rule<struct s1_bv2_rule_b_tag, s1_boost_variant2>
|
||||
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
|
||||
{
|
||||
@@ -64,6 +136,14 @@ struct s2
|
||||
std::string str_;
|
||||
std::optional<std::vector<int>> vec_;
|
||||
};
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
struct s2_boost_optional
|
||||
{
|
||||
int i_;
|
||||
std::string str_;
|
||||
boost::optional<std::vector<int>> vec_;
|
||||
};
|
||||
#endif
|
||||
|
||||
using s2_tuple = tuple<int, std::string, std::optional<std::vector<int>>>;
|
||||
|
||||
@@ -74,6 +154,15 @@ callback_rule<s2_rule_a_tag, s2> s2_rule_a = "s2_rule_a";
|
||||
callback_rule<s2_rule_b_tag, s2> 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<struct s2_bo_rule_a_tag, s2_boost_optional>
|
||||
s2_boost_optional_rule_a = "s2_rule_a";
|
||||
callback_rule<struct s2_bo_rule_b_tag, s2_boost_optional>
|
||||
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);
|
||||
|
||||
@@ -231,6 +320,50 @@ TEST(struct_tuple, seq_parser_struct_rule)
|
||||
EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<std::string>(get(struct_, llong<1>{})), "text");
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<double>(get(struct_, llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<int>({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<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
s2 struct_;
|
||||
|
||||
@@ -247,6 +380,26 @@ TEST(struct_tuple, seq_parser_struct_rule)
|
||||
EXPECT_EQ(get(struct_, llong<1>{}), "text");
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<int>({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<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use the rule as part of a larger parse.
|
||||
{
|
||||
@@ -284,6 +437,74 @@ TEST(struct_tuple, seq_parser_struct_rule)
|
||||
EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
}
|
||||
#if TEST_BOOST_VARIANT
|
||||
{
|
||||
tuple<int, s1_boost_variant> 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<std::string>(get(struct_, llong<1>{})), "text");
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
}
|
||||
{
|
||||
tuple<int, s1_boost_variant> 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<double>(get(struct_, llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
#if TEST_BOOST_VARIANT2
|
||||
{
|
||||
tuple<int, s1_boost_variant2> 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<int>({1, 2, 3}));
|
||||
}
|
||||
{
|
||||
tuple<int, s1_boost_variant2> 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<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
tuple<int, s2> result;
|
||||
|
||||
@@ -306,6 +527,38 @@ TEST(struct_tuple, seq_parser_struct_rule)
|
||||
EXPECT_EQ(get(struct_, llong<1>{}), "text");
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
}
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
{
|
||||
tuple<int, s2_boost_optional> 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<int>({1, 2, 3}));
|
||||
}
|
||||
{
|
||||
tuple<int, s2_boost_optional> 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<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(struct_tuple, repeated_seq_parser_struct_rule)
|
||||
@@ -492,6 +745,82 @@ TEST(struct_tuple, repeated_seq_parser_struct_rule)
|
||||
EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0);
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
#if TEST_BOOST_VARIANT
|
||||
{
|
||||
std::vector<s1_boost_variant> 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<std::string>(get(structs_[0], llong<1>{})), "text");
|
||||
EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
EXPECT_EQ(get(structs_[1], llong<0>{}), 41);
|
||||
EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 0u);
|
||||
EXPECT_EQ(
|
||||
boost::get<std::string>(get(structs_[1], llong<1>{})), "texty");
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
{
|
||||
std::vector<s1_boost_variant> 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<double>(get(structs_[0], llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
EXPECT_EQ(get(structs_[1], llong<0>{}), 41);
|
||||
EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 1u);
|
||||
EXPECT_EQ(boost::get<double>(get(structs_[1], llong<1>{})), 12.0);
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
#endif
|
||||
#if TEST_BOOST_VARIANT2
|
||||
{
|
||||
std::vector<s1_boost_variant2> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
{
|
||||
std::vector<s1_boost_variant2> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
std::vector<s2> structs_;
|
||||
|
||||
@@ -516,6 +845,38 @@ TEST(struct_tuple, repeated_seq_parser_struct_rule)
|
||||
EXPECT_EQ(get(structs_[1], llong<1>{}), "texty");
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
{
|
||||
std::vector<s2_boost_optional> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
{
|
||||
std::vector<s2_boost_optional> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use the rule as part of a larger parse.
|
||||
{
|
||||
@@ -576,6 +937,94 @@ TEST(struct_tuple, repeated_seq_parser_struct_rule)
|
||||
EXPECT_EQ(std::get<1>(get(structs_[1], llong<1>{})), 12.0);
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
#if TEST_BOOST_VARIANT
|
||||
{
|
||||
tuple<int, std::vector<s1_boost_variant>> 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<std::string>(get(structs_[0], llong<1>{})), "text");
|
||||
EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
EXPECT_EQ(get(structs_[1], llong<0>{}), 41);
|
||||
EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 0u);
|
||||
EXPECT_EQ(
|
||||
boost::get<std::string>(get(structs_[1], llong<1>{})), "texty");
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
{
|
||||
tuple<int, std::vector<s1_boost_variant>> 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<double>(get(structs_[0], llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(structs_[0], llong<2>{}), std::vector<int>({1, 2, 3}));
|
||||
EXPECT_EQ(get(structs_[1], llong<0>{}), 41);
|
||||
EXPECT_EQ(get(structs_[1], llong<1>{}).which(), 1u);
|
||||
EXPECT_EQ(boost::get<double>(get(structs_[1], llong<1>{})), 12.0);
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
#endif
|
||||
#if TEST_BOOST_VARIANT2
|
||||
{
|
||||
tuple<int, std::vector<s1_boost_variant2>> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
{
|
||||
tuple<int, std::vector<s1_boost_variant2>> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
tuple<int, std::vector<s2>> result;
|
||||
|
||||
@@ -612,6 +1061,44 @@ TEST(struct_tuple, repeated_seq_parser_struct_rule)
|
||||
EXPECT_EQ(get(structs_[1], llong<1>{}), "texty");
|
||||
EXPECT_EQ(get(structs_[1], llong<2>{}), std::vector<int>({1, 3, 2}));
|
||||
}
|
||||
#if TEST_BOOST_OPTIONAL
|
||||
{
|
||||
tuple<int, std::vector<s2_boost_optional>> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
{
|
||||
tuple<int, std::vector<s2_boost_optional>> 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<int>({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<int>({1, 3, 2}));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct callbacks_t
|
||||
@@ -732,6 +1219,17 @@ TEST(struct_tuple, seq_parser_struct_cb_rule)
|
||||
}
|
||||
}
|
||||
|
||||
// This only exists to unbreak the printing of
|
||||
// boost::optional<std::vector<int>> in the trace logic.
|
||||
namespace boost {
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, boost::optional<std::vector<int>> const & vec)
|
||||
{
|
||||
return os;
|
||||
}
|
||||
}
|
||||
// TODO: Document that boost::optional badly breaks the tracing logic.
|
||||
|
||||
TEST(struct_tuple, parse_into_struct)
|
||||
{
|
||||
// tuples
|
||||
@@ -813,6 +1311,46 @@ TEST(struct_tuple, parse_into_struct)
|
||||
EXPECT_EQ(std::get<1>(get(struct_, llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<std::string>(get(struct_, llong<1>{})), "text");
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<double>(get(struct_, llong<1>{})), 13.0);
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<int>({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<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
s2 struct_;
|
||||
|
||||
@@ -829,6 +1367,24 @@ TEST(struct_tuple, parse_into_struct)
|
||||
EXPECT_EQ(get(struct_, llong<1>{}), "text");
|
||||
EXPECT_EQ(get(struct_, llong<2>{}), std::vector<int>({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<int>({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<int>({1, 2, 3}));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(struct_tuple, repeated_parse_into_struct)
|
||||
|
||||
Reference in New Issue
Block a user