Files
spirit_x4/test/x4/char.cpp
Nana Sakisaka 05bf2eb30b Migrate to Catch2 (#48)
* Migrate to Catch2

* Enable colors in Catch2

* CI: Cache Catch2

* Remove unused variable

* Supply compiler flags to `Catch2WithMain`

* CI: Fix Catch2 cache

* Fix styling
2025-09-25 17:26:35 +09:00

237 lines
8.1 KiB
C++

/*=============================================================================
Copyright (c) 2001-2015 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
Copyright (c) 2019 Christian Mazakas
Copyright (c) 2025 Nana Sakisaka
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)
=============================================================================*/
#define BOOST_SPIRIT_X4_UNICODE
#include "test.hpp"
#include <boost/spirit/x4/char/char.hpp>
#include <boost/spirit/x4/char/char_class.hpp>
#include <boost/spirit/x4/char/unicode_char_class.hpp>
#include <boost/spirit/x4/char/negated_char.hpp>
#include <boost/spirit/x4/operator/plus.hpp>
#include <string>
#include <string_view>
#include <vector>
#include <algorithm>
TEST_CASE("char")
{
static_assert(x4::traits::is_container_v<std::string>);
static_assert(x4::traits::X4Container<std::string>);
static_assert(x4::traits::CategorizedAttr<std::string, x4::traits::container_attr>);
static_assert(!x4::traits::is_container_v<std::string_view>);
static_assert(!x4::traits::X4Container<std::string_view>);
static_assert(x4::traits::CategorizedAttr<std::string_view, x4::traits::plain_attr>);
namespace standard = x4::standard;
namespace standard_wide = x4::standard_wide;
namespace unicode = x4::unicode;
{
std::string_view sv;
auto first = sv.begin();
auto const last = sv.end();
constexpr auto parser = standard::char_('x');
char ch{};
static_assert(noexcept(parser.parse(first, last, unused, ch)));
(void)parser.parse(first, last, unused, ch);
// Make sure this is static
(void)std::remove_const_t<decltype(standard::alnum)>::parse(first, last, unused, ch);
}
{
std::u32string_view sv;
auto first = sv.begin();
auto const last = sv.end();
constexpr auto parser = unicode::char_(U'x');
char32_t ch{};
static_assert(noexcept(parser.parse(first, last, unused, ch)));
(void)parser.parse(first, last, unused, ch);
// Make sure this is static
(void)std::remove_const_t<decltype(unicode::alnum)>::parse(first, last, unused, ch);
}
{
using namespace x4::standard;
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_);
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_('x'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_('a', 'z'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_('x'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_('a', 'z'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_('x'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_('a', 'z'));
CHECK(parse("x", 'x'));
CHECK(parse(L"x", L'x'));
CHECK(!parse("y", 'x'));
CHECK(!parse(L"y", L'x'));
CHECK(parse("x", char_));
CHECK(parse("x", char_('x')));
CHECK(!parse("x", char_('y')));
CHECK(parse("x", char_('a', 'z')));
CHECK(!parse("x", char_('0', '9')));
CHECK(parse("0", char_('0', '9')));
CHECK(parse("9", char_('0', '9')));
CHECK(!parse("0", ~char_('0', '9')));
CHECK(!parse("9", ~char_('0', '9')));
CHECK(!parse("x", ~char_));
CHECK(!parse("x", ~char_('x')));
CHECK(parse(" ", ~char_('x')));
CHECK(parse("X", ~char_('x')));
CHECK(!parse("x", ~char_('b', 'y')));
CHECK(parse("a", ~char_('b', 'y')));
CHECK(parse("z", ~char_('b', 'y')));
CHECK(parse("x", ~~char_));
CHECK(parse("x", ~~char_('x')));
CHECK(!parse(" ", ~~char_('x')));
CHECK(!parse("X", ~~char_('x')));
CHECK(parse("x", ~~char_('b', 'y')));
CHECK(!parse("a", ~~char_('b', 'y')));
CHECK(!parse("z", ~~char_('b', 'y')));
}
{
using namespace x4::standard_wide;
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_);
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_(L'x'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(char_(L'a', L'z'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_(L'x'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~char_(L'a', L'z'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_(L'x'));
BOOST_SPIRIT_X4_ASSERT_CONSTEXPR_CTORS(~~char_(L'a', L'z'));
CHECK(parse(L"x", char_));
CHECK(parse(L"x", char_(L'x')));
CHECK(!parse(L"x", char_(L'y')));
CHECK(parse(L"x", char_(L'a', L'z')));
CHECK(!parse(L"x", char_(L'0', L'9')));
CHECK(!parse(L"x", ~char_));
CHECK(!parse(L"x", ~char_(L'x')));
CHECK(parse(L" ", ~char_(L'x')));
CHECK(parse(L"X", ~char_(L'x')));
CHECK(!parse(L"x", ~char_(L'b', L'y')));
CHECK(parse(L"a", ~char_(L'b', L'y')));
CHECK(parse(L"z", ~char_(L'b', L'y')));
CHECK(parse(L"x", ~~char_));
CHECK(parse(L"x", ~~char_(L'x')));
CHECK(!parse(L" ", ~~char_(L'x')));
CHECK(!parse(L"X", ~~char_(L'x')));
CHECK(parse(L"x", ~~char_(L'b', L'y')));
CHECK(!parse(L"a", ~~char_(L'b', L'y')));
CHECK(!parse(L"z", ~~char_(L'b', L'y')));
}
{
using namespace x4::standard;
CHECK(parse(" x", 'x', space));
CHECK(parse(" x", char_, space));
CHECK(parse(" x", char_('x'), space));
CHECK(!parse(" x", char_('y'), space));
CHECK(parse(" x", char_('a', 'z'), space));
CHECK(!parse(" x", char_('0', '9'), space));
}
{
using namespace x4::standard_wide;
CHECK(parse(L" x", L'x', space));
CHECK(parse(L" x", char_, space));
CHECK(parse(L" x", char_(L'x'), space));
CHECK(!parse(L" x", char_(L'y'), space));
CHECK(parse(L" x", char_(L'a', L'z'), space));
CHECK(!parse(L" x", char_(L'0', L'9'), space));
}
// unicode (normal ASCII)
{
using namespace x4::unicode;
CHECK(parse(U"abcd", +char_(U"abcd")));
CHECK(!parse(U"abcd", +char_(U"qwer")));
auto const sub_delims = char_(U"!$&'()*+,;=");
auto const delims = std::vector<std::u32string_view>{
U"!", U"$", U"&", U"'", U"(", U")", U"*", U"+", U",", U";", U"="
};
auto const matched_all_sub_delims =
std::ranges::all_of(delims, [&](auto const delim) -> bool {
return parse(delim, sub_delims).completed();
});
CHECK(matched_all_sub_delims);
}
// unicode (escaped Unicode char literals)
{
using namespace x4::unicode;
auto const chars = char_(U"\u0024\u00a2\u0939\u20ac\U00010348");
auto const test_strings = std::vector<std::u32string_view>{
U"\u0024", U"\u00a2", U"\u0939", U"\u20ac", U"\U00010348"
};
auto const bad_test_strings = std::vector<std::u32string_view>{
U"a", U"B", U"c", U"\u0409"
};
auto const all_matched =
std::ranges::all_of(test_strings, [&](auto const test_str) -> bool {
return parse(test_str, chars).completed();
});
auto const none_matched =
std::ranges::all_of(bad_test_strings, [&](auto const bad_test_str) -> bool {
return !parse(bad_test_str, chars).completed();
});
CHECK(all_matched);
CHECK(none_matched);
}
// single char strings
{
CHECK(parse("x", "x"));
CHECK(parse(L"x", L"x"));
CHECK(parse("x", standard::char_("x")));
CHECK(parse(L"x", standard_wide::char_(L"x")));
CHECK(parse("x", standard::char_('a', 'z')));
CHECK(parse(L"x", standard_wide::char_(L'a', L'z')));
}
// chsets
{
CHECK(parse("x", standard::char_("a-z")));
CHECK(!parse("1", standard::char_("a-z")));
CHECK(parse("1", standard::char_("a-z0-9")));
CHECK(parse(L"x", standard_wide::char_(L"a-z")));
CHECK(!parse(L"1", standard_wide::char_(L"a-z")));
CHECK(parse(L"1", standard_wide::char_(L"a-z0-9")));
CHECK(parse("x", standard::char_(std::string("a-z0-9"))));
}
}