From 6218dcc51e69da3ebc24fe625c78819ff7cc2170 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Sat, 13 Sep 2025 08:56:59 +0900 Subject: [PATCH] Revert "Merge pull request #826 from saki7/modernize-repeat" This reverts commit 1ef37da85d2d4d1f68dd4045ca504bb52050b113, reversing changes made to b1111dc4af0fae212636f41692eb1873d1c14299. --- .../boost/spirit/home/x3/directive/repeat.hpp | 234 +++++++----------- test/x3/repeat.cpp | 46 ++-- test/x3/utils.hpp | 24 +- 3 files changed, 129 insertions(+), 175 deletions(-) diff --git a/include/boost/spirit/home/x3/directive/repeat.hpp b/include/boost/spirit/home/x3/directive/repeat.hpp index d0dbfd905..d19ea6a52 100644 --- a/include/boost/spirit/home/x3/directive/repeat.hpp +++ b/include/boost/spirit/home/x3/directive/repeat.hpp @@ -3,7 +3,7 @@ Copyright (c) 2001-2011 Hartmut Kaiser Copyright (c) 2014 Thomas Bernard Copyright (c) 2017 wanghan02 - Copyright (c) 2024-2025 Nana Sakisaka + Copyright (c) 2024 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) @@ -15,192 +15,144 @@ #include #include -#include -#include -#include -#include - -namespace boost::spirit::x3::detail +namespace boost { namespace spirit { namespace x3 { namespace detail { - template + template struct exact_count // handles repeat(exact)[p] { - using value_type = T; - [[nodiscard]] constexpr bool got_max(T i) const noexcept { return i >= exact_value; } - [[nodiscard]] constexpr bool got_min(T i) const noexcept { return i >= exact_value; } + typedef T type; + bool got_max(T i) const { return i >= exact_value; } + bool got_min(T i) const { return i >= exact_value; } - T exact_value; + T const exact_value; }; - template + template struct finite_count // handles repeat(min, max)[p] { - using value_type = T; - [[nodiscard]] constexpr bool got_max(T i) const noexcept { return i >= max_value; } - [[nodiscard]] constexpr bool got_min(T i) const noexcept { return i >= min_value; } + typedef T type; + bool got_max(T i) const { return i >= max_value; } + bool got_min(T i) const { return i >= min_value; } - T min_value; - T max_value; + T const min_value; + T const max_value; }; - template + template struct infinite_count // handles repeat(min, inf)[p] { - using value_type = T; - [[nodiscard]] constexpr bool got_max(T /*i*/) const noexcept { return false; } - [[nodiscard]] constexpr bool got_min(T i) const noexcept { return i >= min_value; } + typedef T type; + bool got_max(T /*i*/) const { return false; } + bool got_min(T i) const { return i >= min_value; } - T min_value; + T const min_value; }; -} // boost::spirit::x3::detail +}}}} -namespace boost::spirit::x3 +namespace boost { namespace spirit { namespace x3 { - namespace detail + template + struct repeat_directive : unary_parser> { - template - concept RepeatBounds = requires(std::remove_cvref_t const& bounds) { - typename std::remove_cvref_t::value_type; - { bounds.got_max(std::declval::value_type>()) } -> std::same_as; - { bounds.got_min(std::declval::value_type>()) } -> std::same_as; - }; - } // detail + typedef unary_parser> base_type; + static bool const is_pass_through_unary = true; + static bool const handles_container = true; - template - struct repeat_directive : unary_parser> - { - using base_type = unary_parser>; - static constexpr bool is_pass_through_unary = true; - static constexpr bool handles_container = true; - - template - requires std::is_constructible_v && std::is_constructible_v - constexpr repeat_directive(SubjectT&& subject, BoundsT&& bounds) - noexcept(std::is_nothrow_constructible_v && std::is_nothrow_constructible_v) - : base_type(std::forward(subject)) - , bounds_(std::forward(bounds)) + constexpr repeat_directive(Subject const& subject, RepeatCountLimit const& repeat_limit_) + : base_type(subject) + , repeat_limit(repeat_limit_) {} - template Se, typename Context, typename RContext, typename Attribute> - [[nodiscard]] constexpr bool - parse(It& first, Se const& last, Context const& context, RContext& rcontext, Attribute& attr) const - // never noexcept (requires container insertion) + template + bool parse( + Iterator& first, Iterator const& last + , Context const& context, RContext& rcontext, Attribute& attr) const { - It local_it = first; - typename Bounds::value_type i{}; - for (; !bounds_.got_min(i); ++i) + Iterator local_iterator = first; + typename RepeatCountLimit::type i{}; + for (/**/; !repeat_limit.got_min(i); ++i) { - if (!detail::parse_into_container(this->subject, local_it, last, context, rcontext, attr)) - { + if (!detail::parse_into_container( + this->subject, local_iterator, last, context, rcontext, attr)) return false; - } } - first = local_it; + first = local_iterator; // parse some more up to the maximum specified - for (; !bounds_.got_max(i); ++i) + for (/**/; !repeat_limit.got_max(i); ++i) { - if (!detail::parse_into_container(this->subject, first, last, context, rcontext, attr)) - { + if (!detail::parse_into_container( + this->subject, first, last, context, rcontext, attr)) break; - } } - return !x3::has_expectation_failure(context); + return !has_expectation_failure(context); } - private: - Bounds bounds_; + RepeatCountLimit repeat_limit; }; - namespace detail + // Infinite loop tag type + struct inf_type {}; + constexpr inf_type inf = inf_type(); + + struct repeat_gen { - // Infinite loop tag type - struct repeat_inf_type + template + constexpr auto operator[](Subject const& subject) const { - constexpr explicit repeat_inf_type() noexcept = default; - }; - } // detail + return *as_parser(subject); + } - inline namespace cpos - { - // Infinite loop tag type - [[deprecated("Use `x3::repeat_inf`")]] - inline constexpr detail::repeat_inf_type inf{}; - - // Infinite loop tag type - inline constexpr detail::repeat_inf_type repeat_inf{}; - } - - namespace detail - { - struct repeat_gen + template + struct repeat_gen_lvl1 { - template - [[nodiscard, deprecated("`repeat[p]` has the exact same meaning as `*p`. Use `*p` instead.")]] - constexpr auto operator[](Subject&& subject) const - noexcept(noexcept(*as_parser(std::forward(subject)))) + constexpr repeat_gen_lvl1(T&& repeat_limit_) + : repeat_limit(repeat_limit_) + {} + + template + constexpr repeat_directive< typename extension::as_parser::value_type, T> + operator[](Subject const& subject) const { - return *as_parser(std::forward(subject)); + return { as_parser(subject),repeat_limit }; } - template - struct [[nodiscard]] repeat_gen_impl - { - template - [[nodiscard]] constexpr repeat_directive, Bounds> - operator[](Subject&& subject) const - noexcept( - is_parser_nothrow_castable_v && - std::is_nothrow_constructible_v< - repeat_directive, Bounds>, - as_parser_t, - Bounds const& - > - ) - { - return { as_parser(std::forward(subject)), bounds }; - } - - Bounds bounds; - }; - - template - static constexpr repeat_gen_impl> - operator()(T const exact) noexcept - { - return { exact_count{exact} }; - } - - template - static constexpr repeat_gen_impl> - operator()(T const min_val, T const max_val) noexcept - { - return { finite_count{min_val, max_val} }; - } - - template - static constexpr repeat_gen_impl> - operator()(T const min_val, repeat_inf_type const&) noexcept - { - return { infinite_count{min_val} }; - } + T repeat_limit; }; - } // detail - inline namespace cpos - { - inline constexpr detail::repeat_gen repeat{}; - } + template + constexpr repeat_gen_lvl1> + operator()(T const exact) const + { + return { detail::exact_count{exact} }; + } -} // boost::spirit::x3 + template + constexpr repeat_gen_lvl1> + operator()(T const min_val, T const max_val) const + { + return { detail::finite_count{min_val,max_val} }; + } -namespace boost::spirit::x3::traits + template + constexpr repeat_gen_lvl1> + operator()(T const min_val, inf_type const &) const + { + return { detail::infinite_count{min_val} }; + } + }; + + constexpr auto repeat = repeat_gen{}; +}}} + +namespace boost { namespace spirit { namespace x3 { namespace traits { - template - struct attribute_of, Context> - : build_container> - {}; -} // boost::spirit::x3::traits + template + struct attribute_of, Context> + : build_container::type> {}; +}}}} + #endif diff --git a/test/x3/repeat.cpp b/test/x3/repeat.cpp index 7c397dde4..4468c2e66 100644 --- a/test/x3/repeat.cpp +++ b/test/x3/repeat.cpp @@ -1,27 +1,33 @@ /*============================================================================= Copyright (c) 2001-2011 Joel de Guzman - 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) =============================================================================*/ +#include +#include + +#include + +#if defined(__GNUC__) && (__GNUC__ >= 8) +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92539 +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif +#include +#include +#include #include "test.hpp" #include "utils.hpp" -#include - -#include -#include -#include - -int main() +int +main() { using spirit_test::test_attr; using spirit_test::test; - using namespace boost::spirit::x3::standard; + using namespace boost::spirit::x3::ascii; using boost::spirit::x3::repeat; - using boost::spirit::x3::repeat_inf; + using boost::spirit::x3::inf; using boost::spirit::x3::omit; using boost::spirit::x3::int_; using boost::spirit::x3::lexeme; @@ -30,7 +36,7 @@ int main() BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(repeat['x']); BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(repeat(3)['x']); BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(repeat(3, 5)['x']); - BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(repeat(3, repeat_inf)['x']); + BOOST_SPIRIT_ASSERT_CONSTEXPR_CTORS(repeat(3, inf)['x']); { BOOST_TEST(test("aaaaaaaa", repeat[char_])); // kleene synonym @@ -41,10 +47,10 @@ int main() BOOST_TEST(!test("aaaaaa", repeat(3, 5)[char_])); BOOST_TEST(!test("aa", repeat(3, 5)[char_])); - BOOST_TEST(test("aaa", repeat(3, repeat_inf)[char_])); - BOOST_TEST(test("aaaaa", repeat(3, repeat_inf)[char_])); - BOOST_TEST(test("aaaaaa", repeat(3, repeat_inf)[char_])); - BOOST_TEST(!test("aa", repeat(3, repeat_inf)[char_])); + BOOST_TEST(test("aaa", repeat(3, inf)[char_])); + BOOST_TEST(test("aaaaa", repeat(3, inf)[char_])); + BOOST_TEST(test("aaaaaa", repeat(3, inf)[char_])); + BOOST_TEST(!test("aa", repeat(3, inf)[char_])); } { std::string s; @@ -70,18 +76,18 @@ int main() BOOST_TEST(!test("a", repeat(1, 3)[char_ >> char_])); s.clear(); - BOOST_TEST(test_attr("aaaa", repeat(2, repeat_inf)[char_ >> char_], s)); + BOOST_TEST(test_attr("aaaa", repeat(2, inf)[char_ >> char_], s)); BOOST_TEST(s == "aaaa"); s.clear(); - BOOST_TEST(test_attr("aaaaaa", repeat(2, repeat_inf)[char_ >> char_], s)); + BOOST_TEST(test_attr("aaaaaa", repeat(2, inf)[char_ >> char_], s)); BOOST_TEST(s == "aaaaaa"); - BOOST_TEST(!test("aa", repeat(2, repeat_inf)[char_ >> char_])); + BOOST_TEST(!test("aa", repeat(2, inf)[char_ >> char_])); } { // from classic spirit tests - BOOST_TEST(test("", repeat(0, repeat_inf)['x'])); + BOOST_TEST(test("", repeat(0, inf)['x'])); // repeat exact 8 #define rep8 repeat(8)[alpha] >> 'X' @@ -99,7 +105,7 @@ int main() BOOST_TEST(!test("a*", rep28, false)); // repeat 2 or more - #define rep2_ repeat(2, repeat_inf)[alpha] >> '+' + #define rep2_ repeat(2, inf)[alpha] >> '+' BOOST_TEST(test("abcdefg+", rep2_)); BOOST_TEST(test("abcdefgh+", rep2_)); BOOST_TEST(test("abcdefghi+", rep2_)); diff --git a/test/x3/utils.hpp b/test/x3/utils.hpp index 0b31b9f98..588f60dec 100644 --- a/test/x3/utils.hpp +++ b/test/x3/utils.hpp @@ -1,6 +1,5 @@ /*============================================================================= Copyright (c) 2019 Nikita Kniazev - Copyright (c) 2025 Nana Sakisaka Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -10,9 +9,6 @@ #define BOOST_SPIRIT_TEST_X3_UTILS_HPP #include -#include - -#include struct move_only { @@ -21,19 +17,19 @@ struct move_only move_only& operator=(move_only&&) = default; }; + template struct synth_parser : boost::spirit::x3::parser> { - using attribute_type = T; + typedef T attribute_type; - static constexpr bool has_attribute = true; - static constexpr bool handles_container = false; + static bool const has_attribute = true; + static bool const handles_container = false; - template Se, typename Context, typename RContext, typename Attribute> - [[nodiscard]] constexpr bool parse( - It& iter, Se const& last, Context const&, - RContext&, Attribute& attr - ) const + template + bool parse(Iterator& iter, Iterator const& last, Context const&, + RuleContext&, Attribute& attr) const { if (iter != last && *iter == 's') { ++iter; @@ -45,8 +41,8 @@ struct synth_parser : boost::spirit::x3::parser> }; template -constexpr synth_parser synth{}; +synth_parser synth{}; -constexpr synth_parser synth_move_only{}; +synth_parser const synth_move_only{}; #endif