mirror of
https://github.com/boostorg/parser.git
synced 2026-01-19 04:22:13 +00:00
Add a special seq_parser combining rule that makes a std::string ot of two
adjacent char/char32_t values. Partially addresses #55.
This commit is contained in:
@@ -1809,14 +1809,15 @@ for `p`.
|
||||
as `X >> Y -> Z`, where `X` is the type of the current attribute, `Y` is the
|
||||
type of the next attribute, and `Z` is the new current attribute type. In
|
||||
these rules, `C<T>` is a container of `T`; `none` is a special type that
|
||||
indicates that there is no attribute; `T` is a type; and `Ts...` is a
|
||||
parameter pack of one or more types. Note that `T` may be the special type
|
||||
`none`. The current attribute is always a tuple (call it `Tup`), so the
|
||||
"current attribute `X`" refers to the last element of `Tup`, not `Tup` itself,
|
||||
except for those rules that explicitly mention `_bp_tup_<>` as part of `X`'s
|
||||
type.
|
||||
indicates that there is no attribute; `T` is a type; `CHAR` is a character
|
||||
type, either `char` or `char32_t`; and `Ts...` is a parameter pack of one or
|
||||
more types. Note that `T` may be the special type `none`. The current
|
||||
attribute is always a tuple (call it `Tup`), so the "current attribute `X`"
|
||||
refers to the last element of `Tup`, not `Tup` itself, except for those rules
|
||||
that explicitly mention `_bp_tup_<>` as part of `X`'s type.
|
||||
|
||||
* `none >> T -> T`
|
||||
* `CHAR` >> `CHAR` -> `std::string`
|
||||
* `T >> none -> T`
|
||||
* `C<T> >> T -> C<T>`
|
||||
* `T >> C<T> -> C<T>`
|
||||
|
||||
@@ -1120,6 +1120,10 @@ namespace boost { namespace parser {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_char_type_v =
|
||||
std::is_same_v<T, char> || std::is_same_v<T, char32_t>;
|
||||
|
||||
template<typename T>
|
||||
struct optional_of_impl
|
||||
{
|
||||
@@ -3155,6 +3159,17 @@ namespace boost { namespace parser {
|
||||
result,
|
||||
detail::hl::append(
|
||||
indices, detail::hl::size_minus_one(result)));
|
||||
} else if constexpr (
|
||||
detail::is_char_type_v<result_back_type> &&
|
||||
(detail::is_char_type_v<x_type> ||
|
||||
detail::is_char_type_v<unwrapped_optional_x_type>)) {
|
||||
// CHAR >> CHAR -> string
|
||||
return detail::hl::make_tuple(
|
||||
detail::hl::append(
|
||||
detail::hl::drop_back(result),
|
||||
detail::wrapper<std::string>{}),
|
||||
detail::hl::append(
|
||||
indices, detail::hl::size_minus_one(result)));
|
||||
} else if constexpr (
|
||||
detail::
|
||||
container_and_value_type<result_back_type, x_type> ||
|
||||
|
||||
@@ -30,22 +30,22 @@ void compile_seq_attribute()
|
||||
{
|
||||
constexpr auto parser = char_ >> char_;
|
||||
using attr_t = decltype(prefix_parse(first, last, parser));
|
||||
static_assert(std::is_same_v<attr_t, std::optional<tuple<char, char>>>);
|
||||
static_assert(std::is_same_v<attr_t, std::optional<std::string>>);
|
||||
}
|
||||
{
|
||||
constexpr auto parser = eps >> char_ >> char_;
|
||||
using attr_t = decltype(prefix_parse(first, last, parser));
|
||||
static_assert(std::is_same_v<attr_t, std::optional<tuple<char, char>>>);
|
||||
static_assert(std::is_same_v<attr_t, std::optional<std::string>>);
|
||||
}
|
||||
{
|
||||
constexpr auto parser = char_ >> eps >> char_;
|
||||
using attr_t = decltype(prefix_parse(first, last, parser));
|
||||
static_assert(std::is_same_v<attr_t, std::optional<tuple<char, char>>>);
|
||||
static_assert(std::is_same_v<attr_t, std::optional<std::string>>);
|
||||
}
|
||||
{
|
||||
constexpr auto parser = char_ >> char_ >> eps;
|
||||
using attr_t = decltype(prefix_parse(first, last, parser));
|
||||
static_assert(std::is_same_v<attr_t, std::optional<tuple<char, char>>>);
|
||||
static_assert(std::is_same_v<attr_t, std::optional<std::string>>);
|
||||
}
|
||||
{
|
||||
constexpr auto parser = int_ >> char_;
|
||||
|
||||
@@ -92,8 +92,8 @@ TEST(parser, basic)
|
||||
tuple<char, char> result;
|
||||
EXPECT_TRUE(parse(str, parser_1, result));
|
||||
using namespace boost::parser::literals;
|
||||
EXPECT_EQ(get(result, 0_c), 'a');
|
||||
EXPECT_EQ(get(result, 1_c), 'b');
|
||||
EXPECT_EQ(get(result, 0_c), 'b');
|
||||
EXPECT_EQ(get(result, 1_c), '\0');
|
||||
}
|
||||
{
|
||||
std::string str = "abc";
|
||||
@@ -110,9 +110,9 @@ TEST(parser, basic)
|
||||
tuple<char, char, char> result;
|
||||
EXPECT_TRUE(parse(str, parser_2, result));
|
||||
using namespace boost::parser::literals;
|
||||
EXPECT_EQ(get(result, 0_c), 'a');
|
||||
EXPECT_EQ(get(result, 1_c), 'b');
|
||||
EXPECT_EQ(get(result, 2_c), 'c');
|
||||
EXPECT_EQ(get(result, 0_c), 'c');
|
||||
EXPECT_EQ(get(result, 1_c), '\0');
|
||||
EXPECT_EQ(get(result, 2_c), '\0');
|
||||
}
|
||||
{
|
||||
std::string str = "a";
|
||||
@@ -1490,22 +1490,21 @@ TEST(parser, combined_seq_and_or)
|
||||
std::string str = "abc";
|
||||
tuple<char, char, char> chars;
|
||||
EXPECT_TRUE(parse(str, parser, chars));
|
||||
EXPECT_EQ(chars, tup('a', 'b', 'c'));
|
||||
EXPECT_EQ(chars, tup('c', '\0', '\0')); // TODO: Document this behavior.
|
||||
}
|
||||
|
||||
{
|
||||
std::string str = "abc";
|
||||
std::optional<tuple<char, char, char>> const chars =
|
||||
parse(str, parser);
|
||||
std::optional<std::string> const chars = parse(str, parser);
|
||||
EXPECT_TRUE(chars);
|
||||
EXPECT_EQ(*chars, tup('a', 'b', 'c'));
|
||||
EXPECT_EQ(*chars, "abc");
|
||||
}
|
||||
|
||||
{
|
||||
std::string str = "xyz";
|
||||
tup chars;
|
||||
EXPECT_TRUE(parse(str, parser, chars));
|
||||
EXPECT_EQ(chars, tup('x', 'y', 'z'));
|
||||
EXPECT_EQ(chars, tup('z', '\0', '\0'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1553,7 +1552,7 @@ TEST(parser, combined_seq_and_or)
|
||||
std::string str = "xyz";
|
||||
tuple<char, char, char> chars;
|
||||
EXPECT_TRUE(parse(str, parser, chars));
|
||||
EXPECT_EQ(chars, tup('x', 'y', 'z'));
|
||||
EXPECT_EQ(chars, tup('z', '\0', '\0'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -309,8 +309,8 @@ TEST(parser, basic)
|
||||
tuple<char, char> result;
|
||||
EXPECT_TRUE(parse(str, parser_1, result));
|
||||
using namespace boost::parser::literals;
|
||||
EXPECT_EQ(get(result, 0_c), 'a');
|
||||
EXPECT_EQ(get(result, 1_c), 'b');
|
||||
EXPECT_EQ(get(result, 0_c), 'b');
|
||||
EXPECT_EQ(get(result, 1_c), '\0');
|
||||
}
|
||||
{
|
||||
char const * str = "abc";
|
||||
@@ -331,9 +331,9 @@ TEST(parser, basic)
|
||||
tuple<char, char, char> result;
|
||||
EXPECT_TRUE(parse(str, parser_2, result));
|
||||
using namespace boost::parser::literals;
|
||||
EXPECT_EQ(get(result, 0_c), 'a');
|
||||
EXPECT_EQ(get(result, 1_c), 'b');
|
||||
EXPECT_EQ(get(result, 2_c), 'c');
|
||||
EXPECT_EQ(get(result, 0_c), 'c');
|
||||
EXPECT_EQ(get(result, 1_c), '\0');
|
||||
EXPECT_EQ(get(result, 2_c), '\0');
|
||||
}
|
||||
{
|
||||
char const * str = "a";
|
||||
@@ -1751,22 +1751,21 @@ TEST(parser, combined_seq_and_or)
|
||||
char const * str = "abc";
|
||||
tuple<char, char, char> chars;
|
||||
EXPECT_TRUE(parse(str, parser, chars));
|
||||
EXPECT_EQ(chars, tup('a', 'b', 'c'));
|
||||
EXPECT_EQ(chars, tup('c', '\0', '\0'));
|
||||
}
|
||||
|
||||
{
|
||||
char const * str = "abc";
|
||||
std::optional<tuple<char, char, char>> const chars =
|
||||
parse(str, parser);
|
||||
std::optional<std::string> const chars = parse(str, parser);
|
||||
EXPECT_TRUE(chars);
|
||||
EXPECT_EQ(*chars, tup('a', 'b', 'c'));
|
||||
EXPECT_EQ(*chars, "abc");
|
||||
}
|
||||
|
||||
{
|
||||
char const * str = "xyz";
|
||||
tuple<char, char, char> chars;
|
||||
EXPECT_TRUE(parse(str, parser, chars));
|
||||
EXPECT_EQ(chars, tup('x', 'y', 'z'));
|
||||
EXPECT_EQ(chars, tup('z', '\0', '\0'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1814,7 +1813,7 @@ TEST(parser, combined_seq_and_or)
|
||||
char const * str = "xyz";
|
||||
tuple<char, char, char> chars;
|
||||
EXPECT_TRUE(parse(str, parser, chars));
|
||||
EXPECT_EQ(chars, tup('x', 'y', 'z'));
|
||||
EXPECT_EQ(chars, tup('z', '\0', '\0'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user