/*============================================================================= 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 "test.hpp" #include #include #include #include #include #include #include #include #include TEST_CASE("with_local") { using x4::with_local; using x4::as; using x4::_local_var; using x4::_attr; using x4::_as_var; using x4::int_; using x4::eps; // `as` + `with_local` { constexpr auto p = with_local[ as( int_[([](auto&& ctx) { CHECK(_local_var(ctx) == 0); _local_var(ctx) = _attr(ctx) * 100; })] >> eps[([](auto&& ctx) { _as_var(ctx) = _local_var(ctx); })] ) ]; constexpr std::string_view input = "42"; auto first = input.begin(); int i = -1; REQUIRE(p.parse(first, input.end(), unused, i)); CHECK(i == 4200); } // `with_local` with semantic action assignment { int i = -1; auto const p = with_local[ int_[([](auto&& ctx) { CHECK(_local_var(ctx) == 0); _local_var(ctx) = _attr(ctx) * 100; })] >> eps[([&](auto&& ctx) { i = _local_var(ctx); })] ]; constexpr std::string_view input = "42"; auto first = input.begin(); REQUIRE(p.parse(first, input.end(), unused, unused)); CHECK(i == 4200); } // `with_local[with_local[...]]` { int i = -1; auto const p = with_local[ eps[([](auto&& ctx) { CHECK(_local_var(ctx) == 0); })] >> with_local[ eps[([](auto&& ctx) { CHECK(_local_var(ctx) == 0); })] >> int_[([](auto&& ctx) { _local_var(ctx) = _attr(ctx); })] >> eps[([&](auto&& ctx) { i = _local_var(ctx) * 100; })] ] >> eps[([](auto&& ctx) { CHECK(_local_var(ctx) == 0); })] ]; constexpr std::string_view input = "42"; auto first = input.begin(); REQUIRE(p.parse(first, input.end(), unused, unused)); CHECK(i == 4200); } // `with_local[with_local[...]]` { double d = -1.0; auto const p = with_local[ eps[([](auto&& ctx) { static_assert(std::same_as); CHECK(_local_var(ctx) == 0); })] >> with_local[ eps[([](auto&& ctx) { static_assert(std::same_as); CHECK(_local_var(ctx) == 0.0); })] >> int_[([](auto&& ctx) { _local_var(ctx) = _attr(ctx); })] >> eps[([&](auto&& ctx) { d = std::ceil(_local_var(ctx) / 10); })] ] >> eps[([](auto&& ctx) { CHECK(_local_var(ctx) == 0); })] ]; constexpr std::string_view input = "42"; auto first = input.begin(); REQUIRE(p.parse(first, input.end(), unused, unused)); CHECK(d == 5); } // `with_local[with_local[...]]` { std::tuple res{}; struct A_ID {}; struct B_ID {}; auto const p = with_local[ eps[([](auto&& ctx) { CHECK(x4::get(ctx) == 0); })] >> with_local[ eps[([](auto&& ctx) { CHECK(x4::get(ctx) == 0.0); })] >> int_[([](auto&& ctx) { x4::get(ctx) = _attr(ctx) * 10; x4::get(ctx) = _attr(ctx) * 100; })] >> eps[([&](auto&& ctx) { res = std::make_tuple(x4::get(ctx), x4::get(ctx)); })] ] >> eps[([](auto&& ctx) { CHECK(x4::get(ctx) == 420); })] ]; constexpr std::string_view input = "42"; auto first = input.begin(); REQUIRE(p.parse(first, input.end(), unused, unused)); CHECK(std::get<0>(res) == 420); CHECK(std::get<1>(res) == 4200); } }