From 37f8c737571af56180ea8e017aece8d6e7a87141 Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Sat, 21 Sep 2024 11:09:56 +0200 Subject: [PATCH] Lexy updated --- 3rdparty/lexy/CMakeLists.txt | 74 +++--- 3rdparty/lexy/README.adoc | 5 +- 3rdparty/lexy/cmake/lexyConfig.cmake.in | 2 +- .../lexy/include/lexy/_detail/any_ref.hpp | 2 +- 3rdparty/lexy/include/lexy/_detail/assert.hpp | 2 +- .../include/lexy/_detail/buffer_builder.hpp | 2 +- .../lexy/include/lexy/_detail/code_point.hpp | 74 +++--- 3rdparty/lexy/include/lexy/_detail/config.hpp | 25 +- 3rdparty/lexy/include/lexy/_detail/detect.hpp | 2 +- .../include/lexy/_detail/integer_sequence.hpp | 2 +- 3rdparty/lexy/include/lexy/_detail/invoke.hpp | 2 +- .../lexy/include/lexy/_detail/iterator.hpp | 2 +- .../lexy/include/lexy/_detail/lazy_init.hpp | 38 ++- .../include/lexy/_detail/memory_resource.hpp | 13 +- .../lexy/include/lexy/_detail/nttp_string.hpp | 2 +- .../include/lexy/_detail/stateless_lambda.hpp | 2 +- 3rdparty/lexy/include/lexy/_detail/std.hpp | 61 ++++- .../lexy/include/lexy/_detail/string_view.hpp | 12 +- 3rdparty/lexy/include/lexy/_detail/swar.hpp | 6 +- 3rdparty/lexy/include/lexy/_detail/tuple.hpp | 2 +- .../lexy/include/lexy/_detail/type_name.hpp | 12 +- 3rdparty/lexy/include/lexy/action/base.hpp | 9 +- 3rdparty/lexy/include/lexy/action/match.hpp | 2 +- 3rdparty/lexy/include/lexy/action/parse.hpp | 2 +- .../include/lexy/action/parse_as_tree.hpp | 60 +++-- 3rdparty/lexy/include/lexy/action/scan.hpp | 10 +- 3rdparty/lexy/include/lexy/action/trace.hpp | 6 +- .../lexy/include/lexy/action/validate.hpp | 24 +- 3rdparty/lexy/include/lexy/callback.hpp | 2 +- .../lexy/include/lexy/callback/adapter.hpp | 47 +++- .../lexy/include/lexy/callback/aggregate.hpp | 2 +- 3rdparty/lexy/include/lexy/callback/base.hpp | 10 +- 3rdparty/lexy/include/lexy/callback/bind.hpp | 2 +- .../lexy/include/lexy/callback/bit_cast.hpp | 4 +- .../include/lexy/callback/composition.hpp | 2 +- .../lexy/include/lexy/callback/constant.hpp | 2 +- .../lexy/include/lexy/callback/container.hpp | 22 +- 3rdparty/lexy/include/lexy/callback/fold.hpp | 2 +- .../lexy/include/lexy/callback/forward.hpp | 2 +- .../lexy/include/lexy/callback/integer.hpp | 2 +- 3rdparty/lexy/include/lexy/callback/noop.hpp | 2 +- .../lexy/include/lexy/callback/object.hpp | 2 +- .../lexy/include/lexy/callback/string.hpp | 14 +- 3rdparty/lexy/include/lexy/code_point.hpp | 8 +- 3rdparty/lexy/include/lexy/dsl.hpp | 6 +- 3rdparty/lexy/include/lexy/dsl/any.hpp | 8 +- 3rdparty/lexy/include/lexy/dsl/ascii.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/base.hpp | 19 +- 3rdparty/lexy/include/lexy/dsl/bits.hpp | 12 +- 3rdparty/lexy/include/lexy/dsl/bom.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/brackets.hpp | 5 +- 3rdparty/lexy/include/lexy/dsl/branch.hpp | 8 +- 3rdparty/lexy/include/lexy/dsl/byte.hpp | 146 ++++++++-- 3rdparty/lexy/include/lexy/dsl/capture.hpp | 10 +- .../lexy/include/lexy/dsl/case_folding.hpp | 54 ++-- 3rdparty/lexy/include/lexy/dsl/char_class.hpp | 55 ++-- 3rdparty/lexy/include/lexy/dsl/choice.hpp | 10 +- 3rdparty/lexy/include/lexy/dsl/code_point.hpp | 2 +- .../lexy/include/lexy/dsl/combination.hpp | 6 +- .../lexy/include/lexy/dsl/context_counter.hpp | 2 +- .../lexy/include/lexy/dsl/context_flag.hpp | 2 +- .../include/lexy/dsl/context_identifier.hpp | 11 +- 3rdparty/lexy/include/lexy/dsl/delimited.hpp | 60 +++-- 3rdparty/lexy/include/lexy/dsl/digit.hpp | 88 +++--- 3rdparty/lexy/include/lexy/dsl/eof.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/error.hpp | 26 +- 3rdparty/lexy/include/lexy/dsl/expression.hpp | 23 +- 3rdparty/lexy/include/lexy/dsl/flags.hpp | 10 +- 3rdparty/lexy/include/lexy/dsl/follow.hpp | 11 +- 3rdparty/lexy/include/lexy/dsl/identifier.hpp | 27 +- 3rdparty/lexy/include/lexy/dsl/if.hpp | 4 +- 3rdparty/lexy/include/lexy/dsl/integer.hpp | 21 +- 3rdparty/lexy/include/lexy/dsl/list.hpp | 8 +- 3rdparty/lexy/include/lexy/dsl/literal.hpp | 42 +-- 3rdparty/lexy/include/lexy/dsl/lookahead.hpp | 5 +- 3rdparty/lexy/include/lexy/dsl/loop.hpp | 6 +- 3rdparty/lexy/include/lexy/dsl/member.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/newline.hpp | 5 +- 3rdparty/lexy/include/lexy/dsl/operator.hpp | 41 ++- 3rdparty/lexy/include/lexy/dsl/option.hpp | 4 +- 3rdparty/lexy/include/lexy/dsl/parse_as.hpp | 75 +++--- .../lexy/include/lexy/dsl/parse_tree_node.hpp | 251 ++++++++++++++++++ 3rdparty/lexy/include/lexy/dsl/peek.hpp | 28 +- 3rdparty/lexy/include/lexy/dsl/position.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/production.hpp | 4 +- 3rdparty/lexy/include/lexy/dsl/punctuator.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/recover.hpp | 53 ++-- 3rdparty/lexy/include/lexy/dsl/repeat.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/return.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/scan.hpp | 60 +++-- 3rdparty/lexy/include/lexy/dsl/separator.hpp | 6 +- 3rdparty/lexy/include/lexy/dsl/sequence.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/sign.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/subgrammar.hpp | 4 +- 3rdparty/lexy/include/lexy/dsl/symbol.hpp | 39 +-- 3rdparty/lexy/include/lexy/dsl/terminator.hpp | 4 +- 3rdparty/lexy/include/lexy/dsl/times.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/token.hpp | 27 +- 3rdparty/lexy/include/lexy/dsl/unicode.hpp | 2 +- 3rdparty/lexy/include/lexy/dsl/until.hpp | 18 +- 3rdparty/lexy/include/lexy/dsl/whitespace.hpp | 5 +- 3rdparty/lexy/include/lexy/encoding.hpp | 30 ++- 3rdparty/lexy/include/lexy/error.hpp | 37 ++- 3rdparty/lexy/include/lexy/grammar.hpp | 39 ++- .../lexy/include/lexy/input/argv_input.hpp | 16 +- 3rdparty/lexy/include/lexy/input/base.hpp | 22 +- 3rdparty/lexy/include/lexy/input/buffer.hpp | 42 ++- 3rdparty/lexy/include/lexy/input/file.hpp | 2 +- .../include/lexy/input/parse_tree_input.hpp | 184 +++++++++++++ .../lexy/include/lexy/input/range_input.hpp | 2 +- .../lexy/include/lexy/input/string_input.hpp | 4 +- 3rdparty/lexy/include/lexy/input_location.hpp | 69 +++-- 3rdparty/lexy/include/lexy/lexeme.hpp | 11 +- 3rdparty/lexy/include/lexy/parse_tree.hpp | 226 +++++++++++++--- 3rdparty/lexy/include/lexy/token.hpp | 16 +- 3rdparty/lexy/include/lexy/visualize.hpp | 96 +++++-- .../include/lexy_ext/compiler_explorer.hpp | 2 +- .../include/lexy_ext/parse_tree_algorithm.hpp | 4 +- .../include/lexy_ext/parse_tree_doctest.hpp | 2 +- .../lexy/include/lexy_ext/report_error.hpp | 14 +- 3rdparty/lexy/include/lexy_ext/shell.hpp | 20 +- 3rdparty/lexy/src/CMakeLists.txt | 12 +- 3rdparty/lexy/src/input/file.cpp | 7 +- 123 files changed, 1989 insertions(+), 783 deletions(-) create mode 100644 3rdparty/lexy/include/lexy/dsl/parse_tree_node.hpp create mode 100644 3rdparty/lexy/include/lexy/input/parse_tree_input.hpp diff --git a/3rdparty/lexy/CMakeLists.txt b/3rdparty/lexy/CMakeLists.txt index 1d8cf7964..a76693a9e 100644 --- a/3rdparty/lexy/CMakeLists.txt +++ b/3rdparty/lexy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +# Copyright (C) 2020-2024 Jonathan Müller and lexy contributors # SPDX-License-Identifier: BSL-1.0 cmake_minimum_required(VERSION 3.8) @@ -9,6 +9,42 @@ option(LEXY_FORCE_CPP17 "Whether or not lexy should use C++17 even if compil add_subdirectory(src) +option(LEXY_ENABLE_INSTALL "whether or not to enable the install rule" ON) +if(LEXY_ENABLE_INSTALL) + include(CMakePackageConfigHelpers) + include(GNUInstallDirs) + + install(TARGETS lexy lexy_core lexy_file lexy_unicode lexy_ext _lexy_base lexy_dev + EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE foonathan:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + configure_package_config_file( + cmake/lexyConfig.cmake.in + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + # YYYY.MM.N1 is compatible with YYYY.MM.N2. + write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + COMPATIBILITY SameMinorVersion) + + install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + install(DIRECTORY include/lexy include/lexy_ext + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING + PATTERN "*.hpp") +endif() + if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) cmake_minimum_required(VERSION 3.18) option(LEXY_BUILD_BENCHMARKS "whether or not benchmarks should be built" OFF) @@ -16,7 +52,6 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) option(LEXY_BUILD_TESTS "whether or not tests should be built" ON) option(LEXY_BUILD_DOCS "whether or not docs should be built" OFF) option(LEXY_BUILD_PACKAGE "whether or not the package should be built" ON) - option(LEXY_ENABLE_INSTALL "whether or not to enable the install rule" ON) if(LEXY_BUILD_PACKAGE) set(package_files include/ src/ cmake/ CMakeLists.txt LICENSE) @@ -41,39 +76,4 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if(LEXY_BUILD_DOCS) add_subdirectory(docs EXCLUDE_FROM_ALL) endif() - - if(LEXY_ENABLE_INSTALL) - include(CMakePackageConfigHelpers) - include(GNUInstallDirs) - - install(TARGETS lexy lexy_core lexy_file lexy_unicode lexy_ext _lexy_base lexy_dev - EXPORT ${PROJECT_NAME}Targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - install(EXPORT ${PROJECT_NAME}Targets - NAMESPACE foonathan:: - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - configure_package_config_file( - cmake/lexyConfig.cmake.in - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - # YYYY.MM.N1 is compatible with YYYY.MM.N2. - write_basic_package_version_file( - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - COMPATIBILITY SameMinorVersion) - - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - - install(DIRECTORY include/lexy include/lexy_ext - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING - PATTERN "*.hpp") - endif() endif() diff --git a/3rdparty/lexy/README.adoc b/3rdparty/lexy/README.adoc index 069ab5216..6bc88487f 100644 --- a/3rdparty/lexy/README.adoc +++ b/3rdparty/lexy/README.adoc @@ -113,8 +113,9 @@ Why should I use lexy over XYZ?:: http://boost-spirit.com/home/[Boost.Spirit]::: The main difference: it is not a Boost library. - Otherwise, it is just a different implementation with a different flavor. - Use lexy if you like lexy more. + In addition, Boost.Spirit is quite old and doesn't support e.g. non-common ranges as input. + Boost.Spirit also eagerly creates attributes from the rules, which can lead to nested tuples/variants while lexy uses callbacks which enables zero-copy parsing directly into your own data structure. + However, lexy's grammar is more verbose and designed to parser bigger grammars instead of the small one-off rules that Boost.Spirit is good at. https://github.com/taocpp/PEGTL[PEGTL]::: PEGTL is very similar and was a big inspiration. The biggest difference is that lexy uses an operator based DSL instead of inheriting from templated classes as PEGTL does; diff --git a/3rdparty/lexy/cmake/lexyConfig.cmake.in b/3rdparty/lexy/cmake/lexyConfig.cmake.in index a10ef13fc..e6dc89d30 100644 --- a/3rdparty/lexy/cmake/lexyConfig.cmake.in +++ b/3rdparty/lexy/cmake/lexyConfig.cmake.in @@ -1,4 +1,4 @@ -# Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +# Copyright (C) 2020-2024 Jonathan Müller and lexy contributors # SPDX-License-Identifier: BSL-1.0 # lexy CMake configuration file. diff --git a/3rdparty/lexy/include/lexy/_detail/any_ref.hpp b/3rdparty/lexy/include/lexy/_detail/any_ref.hpp index 11e9c0d31..9eca714b2 100644 --- a/3rdparty/lexy/include/lexy/_detail/any_ref.hpp +++ b/3rdparty/lexy/include/lexy/_detail/any_ref.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_ANY_REF_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/assert.hpp b/3rdparty/lexy/include/lexy/_detail/assert.hpp index 01ccbf6ce..52aa115de 100644 --- a/3rdparty/lexy/include/lexy/_detail/assert.hpp +++ b/3rdparty/lexy/include/lexy/_detail/assert.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_ASSERT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp b/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp index ede3bd324..94ba1fd27 100644 --- a/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp +++ b/3rdparty/lexy/include/lexy/_detail/buffer_builder.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_BUFFER_BUILDER_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/code_point.hpp b/3rdparty/lexy/include/lexy/_detail/code_point.hpp index 969fba5d3..bc805b11e 100644 --- a/3rdparty/lexy/include/lexy/_detail/code_point.hpp +++ b/3rdparty/lexy/include/lexy/_detail/code_point.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_CODE_POINT_HPP_INCLUDED @@ -133,9 +133,9 @@ enum class cp_error template struct cp_result { - char32_t cp; - cp_error error; - typename Reader::iterator end; + char32_t cp; + cp_error error; + typename Reader::marker end; }; template @@ -144,16 +144,16 @@ constexpr cp_result parse_code_point(Reader reader) if constexpr (std::is_same_v) { if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.position()}; + return {{}, cp_error::eof, reader.current()}; auto cur = reader.peek(); reader.bump(); auto cp = static_cast(cur); if (cp <= 0x7F) - return {cp, cp_error::success, reader.position()}; + return {cp, cp_error::success, reader.current()}; else - return {cp, cp_error::out_of_range, reader.position()}; + return {cp, cp_error::out_of_range, reader.current()}; } else if constexpr (std::is_same_v // || std::is_same_v) @@ -176,11 +176,11 @@ constexpr cp_result parse_code_point(Reader reader) { // ASCII character. reader.bump(); - return {first, cp_error::success, reader.position()}; + return {first, cp_error::success, reader.current()}; } else if ((first & ~payload_cont) == pattern_cont) { - return {{}, cp_error::leads_with_trailing, reader.position()}; + return {{}, cp_error::leads_with_trailing, reader.current()}; } else if ((first & ~payload_lead2) == pattern_lead2) { @@ -188,7 +188,7 @@ constexpr cp_result parse_code_point(Reader reader) auto second = uchar_t(reader.peek()); if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); auto result = char32_t(first & payload_lead2); @@ -197,9 +197,9 @@ constexpr cp_result parse_code_point(Reader reader) // C0 and C1 are overlong ASCII. if (first == 0xC0 || first == 0xC1) - return {result, cp_error::overlong_sequence, reader.position()}; + return {result, cp_error::overlong_sequence, reader.current()}; else - return {result, cp_error::success, reader.position()}; + return {result, cp_error::success, reader.current()}; } else if ((first & ~payload_lead3) == pattern_lead3) { @@ -207,12 +207,12 @@ constexpr cp_result parse_code_point(Reader reader) auto second = uchar_t(reader.peek()); if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); auto third = uchar_t(reader.peek()); if ((third & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); auto result = char32_t(first & payload_lead3); @@ -223,11 +223,11 @@ constexpr cp_result parse_code_point(Reader reader) auto cp = result; if (0xD800 <= cp && cp <= 0xDFFF) - return {cp, cp_error::surrogate, reader.position()}; + return {cp, cp_error::surrogate, reader.current()}; else if (first == 0xE0 && second < 0xA0) - return {cp, cp_error::overlong_sequence, reader.position()}; + return {cp, cp_error::overlong_sequence, reader.current()}; else - return {cp, cp_error::success, reader.position()}; + return {cp, cp_error::success, reader.current()}; } else if ((first & ~payload_lead4) == pattern_lead4) { @@ -235,17 +235,17 @@ constexpr cp_result parse_code_point(Reader reader) auto second = uchar_t(reader.peek()); if ((second & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); auto third = uchar_t(reader.peek()); if ((third & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); auto fourth = uchar_t(reader.peek()); if ((fourth & ~payload_cont) != pattern_cont) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); auto result = char32_t(first & payload_lead4); @@ -258,15 +258,15 @@ constexpr cp_result parse_code_point(Reader reader) auto cp = result; if (cp > 0x10'FFFF) - return {cp, cp_error::out_of_range, reader.position()}; + return {cp, cp_error::out_of_range, reader.current()}; else if (first == 0xF0 && second < 0x90) - return {cp, cp_error::overlong_sequence, reader.position()}; + return {cp, cp_error::overlong_sequence, reader.current()}; else - return {cp, cp_error::success, reader.position()}; + return {cp, cp_error::success, reader.current()}; } else // FE or FF { - return {{}, cp_error::eof, reader.position()}; + return {{}, cp_error::eof, reader.current()}; } } else if constexpr (std::is_same_v) @@ -278,18 +278,18 @@ constexpr cp_result parse_code_point(Reader reader) constexpr auto pattern2 = 0b110111 << 10; if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.position()}; + return {{}, cp_error::eof, reader.current()}; auto first = char16_t(reader.peek()); if ((first & ~payload1) == pattern1) { reader.bump(); if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; auto second = char16_t(reader.peek()); if ((second & ~payload2) != pattern2) - return {{}, cp_error::missing_trailing, reader.position()}; + return {{}, cp_error::missing_trailing, reader.current()}; reader.bump(); // We've got a valid code point. @@ -297,34 +297,34 @@ constexpr cp_result parse_code_point(Reader reader) result <<= 10; result |= char32_t(second & payload2); result |= 0x10000; - return {result, cp_error::success, reader.position()}; + return {result, cp_error::success, reader.current()}; } else if ((first & ~payload2) == pattern2) { - return {{}, cp_error::leads_with_trailing, reader.position()}; + return {{}, cp_error::leads_with_trailing, reader.current()}; } else { // Single code unit code point; always valid. reader.bump(); - return {first, cp_error::success, reader.position()}; + return {first, cp_error::success, reader.current()}; } } else if constexpr (std::is_same_v) { if (reader.peek() == Reader::encoding::eof()) - return {{}, cp_error::eof, reader.position()}; + return {{}, cp_error::eof, reader.current()}; auto cur = reader.peek(); reader.bump(); auto cp = cur; if (cp > 0x10'FFFF) - return {cp, cp_error::out_of_range, reader.position()}; + return {cp, cp_error::out_of_range, reader.current()}; else if (0xD800 <= cp && cp <= 0xDFFF) - return {cp, cp_error::surrogate, reader.position()}; + return {cp, cp_error::surrogate, reader.current()}; else - return {cp, cp_error::success, reader.position()}; + return {cp, cp_error::success, reader.current()}; } else { @@ -341,7 +341,7 @@ constexpr void recover_code_point(Reader& reader, cp_result result) { case cp_error::success: // Consume the entire code point. - reader.set_position(result.end); + reader.reset(result.end); break; case cp_error::eof: // We don't need to do anything to "recover" from EOF. @@ -349,7 +349,7 @@ constexpr void recover_code_point(Reader& reader, cp_result result) case cp_error::leads_with_trailing: // Invalid code unit, consume to recover. - LEXY_PRECONDITION(result.end == reader.position()); + LEXY_PRECONDITION(result.end.position() == reader.position()); reader.bump(); break; @@ -358,7 +358,7 @@ constexpr void recover_code_point(Reader& reader, cp_result result) case cp_error::out_of_range: case cp_error::overlong_sequence: // Consume all the invalid code units to recover. - reader.set_position(result.end); + reader.reset(result.end); break; } } diff --git a/3rdparty/lexy/include/lexy/_detail/config.hpp b/3rdparty/lexy/include/lexy/_detail/config.hpp index 0b57dfc5a..4aa40135b 100644 --- a/3rdparty/lexy/include/lexy/_detail/config.hpp +++ b/3rdparty/lexy/include/lexy/_detail/config.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_CONFIG_HPP_INCLUDED @@ -17,6 +17,14 @@ # endif #endif +#ifndef LEXY_HAS_UNICODE_DATABASE +# define LEXY_HAS_UNICODE_DATABASE 0 +#endif + +#ifndef LEXY_EXPERIMENTAL +# define LEXY_EXPERIMENTAL 0 +#endif + //=== utility traits===// #define LEXY_MOV(...) static_cast&&>(__VA_ARGS__) #define LEXY_FWD(...) static_cast(__VA_ARGS__) @@ -90,6 +98,21 @@ using type_or = std::conditional_t, Fallback, T>; # define LEXY_CONSTEVAL constexpr #endif +//=== constexpr ===// +#ifndef LEXY_HAS_CONSTEXPR_DTOR +# if __cpp_constexpr_dynamic_alloc +# define LEXY_HAS_CONSTEXPR_DTOR 1 +# else +# define LEXY_HAS_CONSTEXPR_DTOR 0 +# endif +#endif + +#if LEXY_HAS_CONSTEXPR_DTOR +# define LEXY_CONSTEXPR_DTOR constexpr +#else +# define LEXY_CONSTEXPR_DTOR +#endif + //=== char8_t ===// #ifndef LEXY_HAS_CHAR8_T # if __cpp_char8_t diff --git a/3rdparty/lexy/include/lexy/_detail/detect.hpp b/3rdparty/lexy/include/lexy/_detail/detect.hpp index 8174805c4..7534c44c4 100644 --- a/3rdparty/lexy/include/lexy/_detail/detect.hpp +++ b/3rdparty/lexy/include/lexy/_detail/detect.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_DETECT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/integer_sequence.hpp b/3rdparty/lexy/include/lexy/_detail/integer_sequence.hpp index bc8cba6e1..36e3cb08c 100644 --- a/3rdparty/lexy/include/lexy/_detail/integer_sequence.hpp +++ b/3rdparty/lexy/include/lexy/_detail/integer_sequence.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_INTEGER_SEQUENCE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/invoke.hpp b/3rdparty/lexy/include/lexy/_detail/invoke.hpp index bc683c9bc..8604e582e 100644 --- a/3rdparty/lexy/include/lexy/_detail/invoke.hpp +++ b/3rdparty/lexy/include/lexy/_detail/invoke.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_INVOKE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/iterator.hpp b/3rdparty/lexy/include/lexy/_detail/iterator.hpp index 9d3f46dd9..42ec995a4 100644 --- a/3rdparty/lexy/include/lexy/_detail/iterator.hpp +++ b/3rdparty/lexy/include/lexy/_detail/iterator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_ITERATOR_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/lazy_init.hpp b/3rdparty/lexy/include/lexy/_detail/lazy_init.hpp index 0a08ebcbb..29fcfa308 100644 --- a/3rdparty/lexy/include/lexy/_detail/lazy_init.hpp +++ b/3rdparty/lexy/include/lexy/_detail/lazy_init.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_LAZY_INIT_HPP_INCLUDED @@ -6,6 +6,7 @@ #include #include +#include namespace lexy::_detail { @@ -25,6 +26,12 @@ struct _lazy_init_storage_trivial constexpr _lazy_init_storage_trivial(int, Args&&... args) : _init(true), _value(LEXY_FWD(args)...) {} + + template + constexpr void _construct(Args&&... args) + { + *this = _lazy_init_storage_trivial(0, LEXY_FWD(args)...); + } }; template @@ -40,24 +47,29 @@ struct _lazy_init_storage_non_trivial constexpr _lazy_init_storage_non_trivial() noexcept : _init(false), _empty() {} template - constexpr _lazy_init_storage_non_trivial(int, Args&&... args) - : _init(true), _value(LEXY_FWD(args)...) - {} + LEXY_CONSTEXPR_DTOR void _construct(Args&&... args) + { + _detail::construct_at(&_value, LEXY_FWD(args)...); + _init = true; + } - ~_lazy_init_storage_non_trivial() noexcept + // Cannot add noexcept due to https://github.com/llvm/llvm-project/issues/59854. + LEXY_CONSTEXPR_DTOR ~_lazy_init_storage_non_trivial() /* noexcept */ { if (_init) _value.~T(); } - _lazy_init_storage_non_trivial(_lazy_init_storage_non_trivial&& other) noexcept + LEXY_CONSTEXPR_DTOR _lazy_init_storage_non_trivial( + _lazy_init_storage_non_trivial&& other) noexcept : _init(other._init), _empty() { if (_init) - ::new (static_cast(&_value)) T(LEXY_MOV(other._value)); + _detail::construct_at(&_value, LEXY_MOV(other._value)); } - _lazy_init_storage_non_trivial& operator=(_lazy_init_storage_non_trivial&& other) noexcept + LEXY_CONSTEXPR_DTOR _lazy_init_storage_non_trivial& operator=( + _lazy_init_storage_non_trivial&& other) noexcept { if (_init && other._init) _value = LEXY_MOV(other._value); @@ -68,7 +80,7 @@ struct _lazy_init_storage_non_trivial } else if (!_init && other._init) { - ::new (static_cast(&_value)) T(LEXY_MOV(other._value)); + _detail::construct_at(&_value, LEXY_MOV(other._value)); _init = true; } else @@ -104,9 +116,11 @@ class lazy_init : _lazy_init_storage template constexpr T& emplace(Args&&... args) { - LEXY_PRECONDITION(!*this); + if (*this) + this->_value = T(LEXY_FWD(args)...); + else + this->_construct(LEXY_FWD(args)...); - *this = lazy_init(0, LEXY_FWD(args)...); return this->_value; } @@ -169,7 +183,6 @@ class lazy_init constexpr T& emplace(T& ref) { - LEXY_PRECONDITION(!*this); _ptr = &ref; return ref; } @@ -210,7 +223,6 @@ class lazy_init constexpr void emplace() { - LEXY_PRECONDITION(!*this); _init = true; } template diff --git a/3rdparty/lexy/include/lexy/_detail/memory_resource.hpp b/3rdparty/lexy/include/lexy/_detail/memory_resource.hpp index bc651d208..324a96c84 100644 --- a/3rdparty/lexy/include/lexy/_detail/memory_resource.hpp +++ b/3rdparty/lexy/include/lexy/_detail/memory_resource.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_MEMORY_RESOURCE_HPP_INCLUDED @@ -29,7 +29,7 @@ class default_memory_resource static void* allocate(std::size_t bytes, std::size_t alignment) { if (alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) - return ::operator new (bytes, std::align_val_t{alignment}); + return ::operator new(bytes, std::align_val_t{alignment}); else return ::operator new(bytes); } @@ -47,14 +47,14 @@ class default_memory_resource #ifdef __cpp_sized_deallocation if (alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) - ::operator delete (ptr, bytes, std::align_val_t{alignment}); + ::operator delete(ptr, bytes, std::align_val_t{alignment}); else ::operator delete(ptr, bytes); #else (void)bytes; if (alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) - ::operator delete (ptr, std::align_val_t{alignment}); + ::operator delete(ptr, std::align_val_t{alignment}); else ::operator delete(ptr); #endif @@ -140,9 +140,8 @@ using memory_resource_ptr _memory_resource_ptr>>; // clang-format on -template || std::is_empty_v>> +template + || std::is_empty_v>> constexpr MemoryResource* get_memory_resource() { return nullptr; diff --git a/3rdparty/lexy/include/lexy/_detail/nttp_string.hpp b/3rdparty/lexy/include/lexy/_detail/nttp_string.hpp index 5ef586cd2..7301914a8 100644 --- a/3rdparty/lexy/include/lexy/_detail/nttp_string.hpp +++ b/3rdparty/lexy/include/lexy/_detail/nttp_string.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_NTTP_STRING_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/stateless_lambda.hpp b/3rdparty/lexy/include/lexy/_detail/stateless_lambda.hpp index 75ac77fe1..63c8dc7e5 100644 --- a/3rdparty/lexy/include/lexy/_detail/stateless_lambda.hpp +++ b/3rdparty/lexy/include/lexy/_detail/stateless_lambda.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_STATELESS_LAMBDA_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/std.hpp b/3rdparty/lexy/include/lexy/_detail/std.hpp index f6525bd0b..bb3381f08 100644 --- a/3rdparty/lexy/include/lexy/_detail/std.hpp +++ b/3rdparty/lexy/include/lexy/_detail/std.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_STD_HPP_INCLUDED @@ -6,6 +6,7 @@ #include +//=== iterator tags ===// #if defined(__GLIBCXX__) namespace std @@ -35,5 +36,63 @@ struct bidirectional_iterator_tag; #endif +//=== (constexpr) construct_at ===// +#if !LEXY_HAS_CONSTEXPR_DTOR + +namespace lexy::_detail +{ +// We don't have constexpr dtor's, so this is just a regular function. +template +T* construct_at(T* ptr, Args&&... args) +{ + return ::new ((void*)ptr) T(LEXY_FWD(args)...); +} +} // namespace lexy::_detail + +#elif defined(_MSC_VER) + +namespace lexy::_detail +{ +// MSVC can make it constexpr if marked with an attribute given by a macro. +template +constexpr T* construct_at(T* ptr, Args&&... args) +{ +# if defined(_MSVC_CONSTEXPR) + _MSVC_CONSTEXPR +# endif + return ::new ((void*)ptr) T(LEXY_FWD(args)...); +} +} // namespace lexy::_detail + +#else + +namespace lexy::_detail +{ +struct _construct_at_tag +{}; +} // namespace lexy::_detail + +namespace std +{ +// GCC only allows constexpr placement new inside a function called `std::construct_at`. +// So we write our own. +template +constexpr T* construct_at(lexy::_detail::_construct_at_tag, T* ptr, Args&&... args) +{ + return ::new ((void*)ptr) T(LEXY_FWD(args)...); +} +} // namespace std + +namespace lexy::_detail +{ +template +constexpr T* construct_at(T* ptr, Args&&... args) +{ + return std::construct_at(lexy::_detail::_construct_at_tag{}, ptr, LEXY_FWD(args)...); +} +} // namespace lexy::_detail + +#endif + #endif // LEXY_DETAIL_STD_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/string_view.hpp b/3rdparty/lexy/include/lexy/_detail/string_view.hpp index 1ee3fa015..41d42bc42 100644 --- a/3rdparty/lexy/include/lexy/_detail/string_view.hpp +++ b/3rdparty/lexy/include/lexy/_detail/string_view.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_STRING_VIEW_HPP_INCLUDED @@ -136,10 +136,18 @@ class basic_string_view } } - constexpr bool starts_with(basic_string_view prefix) const + constexpr bool starts_with(basic_string_view prefix) const noexcept { return substr(0, prefix.size()) == prefix; } + constexpr bool try_remove_prefix(basic_string_view prefix) noexcept + { + if (!starts_with(prefix)) + return false; + + remove_prefix(prefix.length()); + return true; + } constexpr std::size_t find(basic_string_view str, std::size_t pos = 0) const noexcept { diff --git a/3rdparty/lexy/include/lexy/_detail/swar.hpp b/3rdparty/lexy/include/lexy/_detail/swar.hpp index 6d8b5e6d6..d7734d0f4 100644 --- a/3rdparty/lexy/include/lexy/_detail/swar.hpp +++ b/3rdparty/lexy/include/lexy/_detail/swar.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_SWAR_HPP_INCLUDED @@ -222,13 +222,13 @@ class swar_reader_base : _swar_base { auto ptr = static_cast(*this).position(); ptr += swar_length; - static_cast(*this).set_position(ptr); + static_cast(*this).reset({ptr}); } void bump_swar(std::size_t char_count) { auto ptr = static_cast(*this).position(); ptr += char_count; - static_cast(*this).set_position(ptr); + static_cast(*this).reset({ptr}); } }; diff --git a/3rdparty/lexy/include/lexy/_detail/tuple.hpp b/3rdparty/lexy/include/lexy/_detail/tuple.hpp index bb8eb86d2..b9c7ebf55 100644 --- a/3rdparty/lexy/include/lexy/_detail/tuple.hpp +++ b/3rdparty/lexy/include/lexy/_detail/tuple.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_TUPLE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/_detail/type_name.hpp b/3rdparty/lexy/include/lexy/_detail/type_name.hpp index 0dd6f652c..8e7ffe250 100644 --- a/3rdparty/lexy/include/lexy/_detail/type_name.hpp +++ b/3rdparty/lexy/include/lexy/_detail/type_name.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DETAIL_TYPE_NAME_HPP_INCLUDED @@ -29,6 +29,7 @@ constexpr auto _full_type_name() auto function = string_view(__PRETTY_FUNCTION__); function.remove_prefix(prefix.length()); function.remove_suffix(suffix.length()); + function.try_remove_prefix("(anonymous namespace)::"); return function; #elif defined(__GNUC__) @@ -46,6 +47,7 @@ constexpr auto _full_type_name() auto function = string_view(__PRETTY_FUNCTION__); function.remove_prefix(prefix.length()); function.remove_suffix(suffix.length()); + function.try_remove_prefix("{anonymous}::"); return function; #elif defined(_MSC_VER) @@ -58,12 +60,8 @@ constexpr auto _full_type_name() auto function = string_view(__FUNCSIG__); function.remove_prefix(prefix.length()); function.remove_suffix(suffix.length()); - - if (auto s = string_view("struct "); function.starts_with(s)) - function.remove_prefix(s.length()); - else if (auto c = string_view("class "); function.starts_with(c)) - function.remove_prefix(c.length()); - + function.try_remove_prefix("struct ") || function.try_remove_prefix("class "); + function.try_remove_prefix("`anonymous-namespace'::"); return function; #else diff --git a/3rdparty/lexy/include/lexy/action/base.hpp b/3rdparty/lexy/include/lexy/action/base.hpp index b74f9e1ce..84cc15f2d 100644 --- a/3rdparty/lexy/include/lexy/action/base.hpp +++ b/3rdparty/lexy/include/lexy/action/base.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ACTION_BASE_HPP_INCLUDED @@ -200,6 +200,7 @@ constexpr void* no_parse_state = nullptr; template constexpr auto _do_action(_pc& context, Reader& reader) { + context.on(parse_events::grammar_start{}, reader.position()); context.on(parse_events::production_start{}, reader.position()); // We parse whitespace, theen the rule, then finish. @@ -209,9 +210,15 @@ constexpr auto _do_action(_pc& context, Reader& read auto rule_result = parser::parse(context, reader); if (rule_result) + { context.on(parse_events::production_finish{}, reader.position()); + context.on(parse_events::grammar_finish{}, reader); + } else + { context.on(parse_events::production_cancel{}, reader.position()); + context.on(parse_events::grammar_cancel{}, reader); + } return rule_result; } diff --git a/3rdparty/lexy/include/lexy/action/match.hpp b/3rdparty/lexy/include/lexy/action/match.hpp index ca885848b..dade7042c 100644 --- a/3rdparty/lexy/include/lexy/action/match.hpp +++ b/3rdparty/lexy/include/lexy/action/match.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ACTION_MATCH_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/action/parse.hpp b/3rdparty/lexy/include/lexy/action/parse.hpp index a5cd9a2ac..ec4241590 100644 --- a/3rdparty/lexy/include/lexy/action/parse.hpp +++ b/3rdparty/lexy/include/lexy/action/parse.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ACTION_PARSE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/action/parse_as_tree.hpp b/3rdparty/lexy/include/lexy/action/parse_as_tree.hpp index dbf865330..b2f54d2c0 100644 --- a/3rdparty/lexy/include/lexy/action/parse_as_tree.hpp +++ b/3rdparty/lexy/include/lexy/action/parse_as_tree.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ACTION_PARSE_AS_TREE_HPP_INCLUDED @@ -18,7 +18,7 @@ class _pth template explicit _pth(Tree& tree, const _detail::any_holder& input, _detail::any_holder& sink) - : _tree(&tree), _depth(0), _validate(input, sink), _reader(input.get()->reader()) + : _tree(&tree), _depth(0), _validate(input, sink) {} class event_handler @@ -28,40 +28,53 @@ class _pth public: event_handler(production_info info) : _validate(info) {} + void on(_pth& handler, parse_events::grammar_start, iterator) + { + LEXY_PRECONDITION(handler._depth == 0); + + handler._builder.emplace(LEXY_MOV(*handler._tree), _validate.get_info()); + } + void on(_pth& handler, parse_events::grammar_finish, Reader& reader) + { + LEXY_PRECONDITION(handler._depth == 0); + + auto begin = reader.position(); + lexy::try_match_token(dsl::any, reader); + auto end = reader.position(); + + *handler._tree = LEXY_MOV(*handler._builder).finish({begin, end}); + } + void on(_pth& handler, parse_events::grammar_cancel, Reader&) + { + LEXY_PRECONDITION(handler._depth == 0); + + handler._tree->clear(); + } + void on(_pth& handler, parse_events::production_start ev, iterator pos) { - if (handler._depth++ == 0) - handler._builder.emplace(LEXY_MOV(*handler._tree), _validate.get_info()); - else + if (handler._depth++ > 0) _marker = handler._builder->start_production(_validate.get_info()); _validate.on(handler._validate, ev, pos); } - void on(_pth& handler, parse_events::production_finish, iterator pos) + void on(_pth& handler, parse_events::production_finish ev, iterator pos) { - if (--handler._depth == 0) - { - auto reader = handler._reader; - reader.set_position(pos); - lexy::try_match_token(dsl::any, reader); - auto end = reader.position(); - - *handler._tree = LEXY_MOV(*handler._builder).finish({pos, end}); - } - else + if (--handler._depth > 0) { + if (handler._builder->current_child_count() == 0) + handler._builder->token(lexy::position_token_kind, _validate.production_begin(), + _validate.production_begin()); handler._builder->finish_production(LEXY_MOV(_marker)); } + + _validate.on(handler._validate, ev, pos); } - void on(_pth& handler, parse_events::production_cancel, iterator pos) + void on(_pth& handler, parse_events::production_cancel ev, iterator pos) { - if (--handler._depth == 0) - { - handler._tree->clear(); - } - else + if (--handler._depth > 0) { // Cancelling the production removes all nodes from the tree. // To ensure that the parse tree remains lossless, we add everything consumed by it @@ -69,6 +82,8 @@ class _pth handler._builder->cancel_production(LEXY_MOV(_marker)); handler._builder->token(lexy::error_token_kind, _validate.production_begin(), pos); } + + _validate.on(handler._validate, ev, pos); } auto on(_pth& handler, lexy::parse_events::operation_chain_start, iterator) @@ -130,7 +145,6 @@ class _pth int _depth; _vh _validate; - Reader _reader; }; template _input; - _detail::any_holder<_error_sink_t> _sink; - _detail::parse_context_control_block<_handler> _cb; - _pc<_handler, State, _production> _context; + _detail::any_holder _input; + _detail::any_holder<_error_sink_t> _sink; + _detail::parse_context_control_block<_handler, State> _cb; + _pc<_handler, State, _production> _context; friend _impl; }; diff --git a/3rdparty/lexy/include/lexy/action/trace.hpp b/3rdparty/lexy/include/lexy/action/trace.hpp index 84417d854..1a38fac64 100644 --- a/3rdparty/lexy/include/lexy/action/trace.hpp +++ b/3rdparty/lexy/include/lexy/action/trace.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ACTION_TRACE_HPP_INCLUDED @@ -319,6 +319,10 @@ class _th public: constexpr event_handler(production_info info) : _info(info) {} + void on(_th&, parse_events::grammar_start, iterator) {} + void on(_th&, parse_events::grammar_finish, lexy::input_reader&) {} + void on(_th&, parse_events::grammar_cancel, lexy::input_reader&) {} + void on(_th& handler, parse_events::production_start, iterator pos) { auto loc = handler.get_location(pos); diff --git a/3rdparty/lexy/include/lexy/action/validate.hpp b/3rdparty/lexy/include/lexy/action/validate.hpp index f3644fa30..ac6b48f0e 100644 --- a/3rdparty/lexy/include/lexy/action/validate.hpp +++ b/3rdparty/lexy/include/lexy/action/validate.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ACTION_VALIDATE_HPP_INCLUDED @@ -196,27 +196,31 @@ class _vh handler._top = _prev; } - template - constexpr void on(_vh& handler, parse_events::error, const error& error) + template + constexpr void on(_vh& handler, parse_events::error, const error& error) { handler._cb.generic(handler._cb.sink, get_info(), handler._cb.input, _begin, error); } - constexpr void on(_vh& handler, parse_events::error, const error& error) + template + constexpr void on(_vh& handler, parse_events::error, const error& error) { handler._cb.generic(handler._cb.sink, get_info(), handler._cb.input, _begin, error); } - constexpr void on(_vh& handler, parse_events::error, - const error& error) + template + constexpr void on(_vh& handler, parse_events::error, + const error& error) { handler._cb.literal(handler._cb.sink, get_info(), handler._cb.input, _begin, error); } - constexpr void on(_vh& handler, parse_events::error, - const error& error) + template + constexpr void on(_vh& handler, parse_events::error, + const error& error) { handler._cb.keyword(handler._cb.sink, get_info(), handler._cb.input, _begin, error); } - constexpr void on(_vh& handler, parse_events::error, - const error& error) + template + constexpr void on(_vh& handler, parse_events::error, + const error& error) { handler._cb.char_class(handler._cb.sink, get_info(), handler._cb.input, _begin, error); } diff --git a/3rdparty/lexy/include/lexy/callback.hpp b/3rdparty/lexy/include/lexy/callback.hpp index 237ebe316..fa65f3ebb 100644 --- a/3rdparty/lexy/include/lexy/callback.hpp +++ b/3rdparty/lexy/include/lexy/callback.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/adapter.hpp b/3rdparty/lexy/include/lexy/callback/adapter.hpp index 29b2750d6..b212fd2ab 100644 --- a/3rdparty/lexy/include/lexy/callback/adapter.hpp +++ b/3rdparty/lexy/include/lexy/callback/adapter.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_ADAPTER_HPP_INCLUDED @@ -16,6 +16,33 @@ struct _callback : _overloaded constexpr explicit _callback(Fns... fns) : _overloaded(LEXY_MOV(fns)...) {} }; +template +struct _callback_with_state : _overloaded +{ + using return_type = ReturnType; + + template + struct _with_state + { + const _callback_with_state& _cb; + State& _state; + + template + constexpr return_type operator()(Args&&... args) const&& + { + return _cb(_state, LEXY_FWD(args)...); + } + }; + + constexpr explicit _callback_with_state(Fns... fns) : _overloaded(LEXY_MOV(fns)...) {} + + template + constexpr auto operator[](State& state) const + { + return _with_state{*this, state}; + } +}; + /// Creates a callback. template constexpr auto callback(Fns&&... fns) @@ -26,14 +53,28 @@ constexpr auto callback(Fns&&... fns) else return _callback...>(LEXY_FWD(fns)...); } - -/// Creates a callback. template constexpr auto callback(Fns&&... fns) { return _callback...>(LEXY_FWD(fns)...); } +/// Creates a callback that also receives the parse state. +template +constexpr auto callback_with_state(Fns&&... fns) +{ + if constexpr ((lexy::is_callback> && ...)) + return _callback_with_state::return_type...>, + std::decay_t...>(LEXY_FWD(fns)...); + else + return _callback_with_state...>(LEXY_FWD(fns)...); +} +template +constexpr auto callback_with_state(Fns&&... fns) +{ + return _callback_with_state...>(LEXY_FWD(fns)...); +} + template struct _cb_from_sink { diff --git a/3rdparty/lexy/include/lexy/callback/aggregate.hpp b/3rdparty/lexy/include/lexy/callback/aggregate.hpp index fbb04688d..97420f146 100644 --- a/3rdparty/lexy/include/lexy/callback/aggregate.hpp +++ b/3rdparty/lexy/include/lexy/callback/aggregate.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_AGGREGATE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/base.hpp b/3rdparty/lexy/include/lexy/callback/base.hpp index 8edaa86a5..915afdd7d 100644 --- a/3rdparty/lexy/include/lexy/callback/base.hpp +++ b/3rdparty/lexy/include/lexy/callback/base.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_BASE_HPP_INCLUDED @@ -27,6 +27,13 @@ template constexpr bool is_callback_state = _detail::is_detected<_detect_callback_state, T, std::decay_t>; +template +using _detect_callback_with_state_for + = decltype(LEXY_DECLVAL(const T)[LEXY_DECLVAL(State&)](LEXY_DECLVAL(Args)...)); +template +constexpr bool is_callback_with_state_for + = _detail::is_detected<_detect_callback_with_state_for, std::decay_t, State, Args...>; + /// Returns the type of the `.sink()` function. template using sink_callback = decltype(LEXY_DECLVAL(Sink).sink(LEXY_DECLVAL(Args)...)); @@ -82,4 +89,3 @@ constexpr auto _make_overloaded(Op&&... op) } // namespace lexy #endif // LEXY_CALLBACK_BASE_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/callback/bind.hpp b/3rdparty/lexy/include/lexy/callback/bind.hpp index 520e62853..a73851ad4 100644 --- a/3rdparty/lexy/include/lexy/callback/bind.hpp +++ b/3rdparty/lexy/include/lexy/callback/bind.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_BIND_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/bit_cast.hpp b/3rdparty/lexy/include/lexy/callback/bit_cast.hpp index dbb488f01..9401c00f5 100644 --- a/3rdparty/lexy/include/lexy/callback/bit_cast.hpp +++ b/3rdparty/lexy/include/lexy/callback/bit_cast.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_BIT_CAST_HPP_INCLUDED @@ -16,7 +16,7 @@ #ifndef LEXY_HAS_BITCAST # if defined(__has_include) -# if __has_include() +# if __has_include() && __cplusplus >= 202002L # include # ifdef __cpp_lib_bit_cast # define LEXY_HAS_BITCAST 1 diff --git a/3rdparty/lexy/include/lexy/callback/composition.hpp b/3rdparty/lexy/include/lexy/callback/composition.hpp index b072b4dd6..0936c541b 100644 --- a/3rdparty/lexy/include/lexy/callback/composition.hpp +++ b/3rdparty/lexy/include/lexy/callback/composition.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_COMPOSITION_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/constant.hpp b/3rdparty/lexy/include/lexy/callback/constant.hpp index 0421edc78..4ffbd61ca 100644 --- a/3rdparty/lexy/include/lexy/callback/constant.hpp +++ b/3rdparty/lexy/include/lexy/callback/constant.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_CONSTANT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/container.hpp b/3rdparty/lexy/include/lexy/callback/container.hpp index d35dbf32c..a96c64bab 100644 --- a/3rdparty/lexy/include/lexy/callback/container.hpp +++ b/3rdparty/lexy/include/lexy/callback/container.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_CONTAINER_HPP_INCLUDED @@ -16,7 +16,7 @@ template constexpr auto _has_reserve = _detail::is_detected<_detect_reserve, Container>; template -using _detect_append = decltype(LEXY_DECLVAL(Container&).append(LEXY_DECLVAL(Container &&))); +using _detect_append = decltype(LEXY_DECLVAL(Container&).append(LEXY_DECLVAL(Container&&))); template constexpr auto _has_append = _detail::is_detected<_detect_append, Container>; } // namespace lexy @@ -32,18 +32,19 @@ struct _list_sink using return_type = Container; template - auto operator()(U&& obj) -> decltype(LEXY_DECLVAL(C&).push_back(LEXY_FWD(obj))) + constexpr auto operator()(U&& obj) -> decltype(LEXY_DECLVAL(C&).push_back(LEXY_FWD(obj))) { return _result.push_back(LEXY_FWD(obj)); } template - auto operator()(Args&&... args) -> decltype(LEXY_DECLVAL(C&).emplace_back(LEXY_FWD(args)...)) + constexpr auto operator()(Args&&... args) + -> decltype(LEXY_DECLVAL(C&).emplace_back(LEXY_FWD(args)...)) { return _result.emplace_back(LEXY_FWD(args)...); } - Container&& finish() && + constexpr Container&& finish() && { return LEXY_MOV(_result); } @@ -171,18 +172,19 @@ struct _collection_sink using return_type = Container; template - auto operator()(U&& obj) -> decltype(LEXY_DECLVAL(C&).insert(LEXY_FWD(obj))) + constexpr auto operator()(U&& obj) -> decltype(LEXY_DECLVAL(C&).insert(LEXY_FWD(obj))) { return _result.insert(LEXY_FWD(obj)); } template - auto operator()(Args&&... args) -> decltype(LEXY_DECLVAL(C&).emplace(LEXY_FWD(args)...)) + constexpr auto operator()(Args&&... args) + -> decltype(LEXY_DECLVAL(C&).emplace(LEXY_FWD(args)...)) { return _result.emplace(LEXY_FWD(args)...); } - Container&& finish() && + constexpr Container&& finish() && { return LEXY_MOV(_result); } @@ -355,7 +357,7 @@ struct _concat using return_type = Container; - void operator()(Container&& container) + constexpr void operator()(Container&& container) { if (_result.empty()) { @@ -389,7 +391,7 @@ struct _concat } } - Container&& finish() && + constexpr Container&& finish() && { return LEXY_MOV(_result); } diff --git a/3rdparty/lexy/include/lexy/callback/fold.hpp b/3rdparty/lexy/include/lexy/callback/fold.hpp index 478bc5482..b58e80dc7 100644 --- a/3rdparty/lexy/include/lexy/callback/fold.hpp +++ b/3rdparty/lexy/include/lexy/callback/fold.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_FOLD_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/forward.hpp b/3rdparty/lexy/include/lexy/callback/forward.hpp index f4342816c..2655af45b 100644 --- a/3rdparty/lexy/include/lexy/callback/forward.hpp +++ b/3rdparty/lexy/include/lexy/callback/forward.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_FORWARD_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/integer.hpp b/3rdparty/lexy/include/lexy/callback/integer.hpp index de2f94cdc..ab7500210 100644 --- a/3rdparty/lexy/include/lexy/callback/integer.hpp +++ b/3rdparty/lexy/include/lexy/callback/integer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_INTEGER_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/noop.hpp b/3rdparty/lexy/include/lexy/callback/noop.hpp index 03485d9e3..a36e0dc30 100644 --- a/3rdparty/lexy/include/lexy/callback/noop.hpp +++ b/3rdparty/lexy/include/lexy/callback/noop.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_NOOP_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/object.hpp b/3rdparty/lexy/include/lexy/callback/object.hpp index a99dfbf3f..eb87e841d 100644 --- a/3rdparty/lexy/include/lexy/callback/object.hpp +++ b/3rdparty/lexy/include/lexy/callback/object.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_OBJECT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/callback/string.hpp b/3rdparty/lexy/include/lexy/callback/string.hpp index 954c56e14..984f1e1ba 100644 --- a/3rdparty/lexy/include/lexy/callback/string.hpp +++ b/3rdparty/lexy/include/lexy/callback/string.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CALLBACK_STRING_HPP_INCLUDED @@ -149,39 +149,39 @@ struct _as_string using return_type = String; template - void operator()(CharT c) + constexpr void operator()(CharT c) { _result.push_back(c); } - void operator()(String&& str) + constexpr void operator()(String&& str) { _result.append(LEXY_MOV(str)); } template - auto operator()(Iterator begin, Iterator end) + constexpr auto operator()(Iterator begin, Iterator end) -> decltype(void(LEXY_DECLVAL(Str).append(begin, end))) { _result.append(begin, end); } template - void operator()(lexeme lex) + constexpr void operator()(lexeme lex) { static_assert(lexy::char_type_compatible_with_reader, "cannot convert lexeme to this string type"); _result.append(lex.begin(), lex.end()); } - void operator()(code_point cp) + constexpr void operator()(code_point cp) { typename Encoding::char_type buffer[4] = {}; auto size = _detail::encode_code_point(cp.value(), buffer, 4); _result.append(buffer, buffer + size); } - String&& finish() && + constexpr String&& finish() && { return _case_folding(LEXY_MOV(_result)); } diff --git a/3rdparty/lexy/include/lexy/code_point.hpp b/3rdparty/lexy/include/lexy/code_point.hpp index d77d73fbd..a67b3bdbe 100644 --- a/3rdparty/lexy/include/lexy/code_point.hpp +++ b/3rdparty/lexy/include/lexy/code_point.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_CODE_POINT_HPP_INCLUDED @@ -8,10 +8,6 @@ #include #include -#ifndef LEXY_HAS_UNICODE_DATABASE -# define LEXY_HAS_UNICODE_DATABASE 0 -#endif - #if LEXY_HAS_UNICODE_DATABASE # define LEXY_UNICODE_CONSTEXPR constexpr #else @@ -89,7 +85,7 @@ class code_point LEXY_UNICODE_CATEGORY(Lo, other_letter), LEXY_UNICODE_CATEGORY(Mn, nonspacing_mark), - LEXY_UNICODE_CATEGORY(Mc, spaing_mark), + LEXY_UNICODE_CATEGORY(Mc, spacing_mark), LEXY_UNICODE_CATEGORY(Me, enclosing_mark), LEXY_UNICODE_CATEGORY(Nd, decimal_number), diff --git a/3rdparty/lexy/include/lexy/dsl.hpp b/3rdparty/lexy/include/lexy/dsl.hpp index 2cc8a21cc..b41eeceb1 100644 --- a/3rdparty/lexy/include/lexy/dsl.hpp +++ b/3rdparty/lexy/include/lexy/dsl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_HPP_INCLUDED @@ -60,5 +60,9 @@ #include #include +#if LEXY_EXPERIMENTAL +# include +#endif + #endif // LEXY_DSL_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/any.hpp b/3rdparty/lexy/include/lexy/dsl/any.hpp index 734ec611c..2b30e39ef 100644 --- a/3rdparty/lexy/include/lexy/dsl/any.hpp +++ b/3rdparty/lexy/include/lexy/dsl/any.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_ANY_HPP_INCLUDED @@ -15,9 +15,9 @@ struct _any : token_base<_any, unconditional_branch_base> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr std::true_type try_parse(Reader reader) { @@ -32,7 +32,7 @@ struct _any : token_base<_any, unconditional_branch_base> while (reader.peek() != encoding::eof()) reader.bump(); - end = reader.position(); + end = reader.current(); return {}; } }; diff --git a/3rdparty/lexy/include/lexy/dsl/ascii.hpp b/3rdparty/lexy/include/lexy/dsl/ascii.hpp index 16613f8db..7bc237034 100644 --- a/3rdparty/lexy/include/lexy/dsl/ascii.hpp +++ b/3rdparty/lexy/include/lexy/dsl/ascii.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_ASCII_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/base.hpp b/3rdparty/lexy/include/lexy/dsl/base.hpp index 918e447a8..ea965b0b6 100644 --- a/3rdparty/lexy/include/lexy/dsl/base.hpp +++ b/3rdparty/lexy/include/lexy/dsl/base.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_BASE_HPP_INCLUDED @@ -12,6 +12,19 @@ //=== parse_events ===// namespace lexy::parse_events { +/// Parsing started. +/// Arguments: position +struct grammar_start +{}; +/// Parsing finished succesfully. +/// Arguments: the reader at the final parse position. +struct grammar_finish +{}; +/// Parsing finished unsuccesfully. +/// Arguments: the reader at the final parse position. +struct grammar_cancel +{}; + /// Start of the current production. /// Arguments: position struct production_start @@ -237,7 +250,7 @@ LEXY_FORCE_INLINE constexpr auto try_match_token(TokenRule, Reader& reader) if constexpr (std::is_same_v) { parser.try_parse(reader); - reader.set_position(parser.end); + reader.reset(parser.end); return std::true_type{}; } else if constexpr (std::is_same_v) @@ -250,7 +263,7 @@ LEXY_FORCE_INLINE constexpr auto try_match_token(TokenRule, Reader& reader) if (!parser.try_parse(reader)) return false; - reader.set_position(parser.end); + reader.reset(parser.end); return true; } } diff --git a/3rdparty/lexy/include/lexy/dsl/bits.hpp b/3rdparty/lexy/include/lexy/dsl/bits.hpp index adce85bf4..ab6d484c0 100644 --- a/3rdparty/lexy/include/lexy/dsl/bits.hpp +++ b/3rdparty/lexy/include/lexy/dsl/bits.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_BITS_HPP_INCLUDED @@ -104,13 +104,13 @@ struct _bits : token_base<_bits> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { - static_assert(std::is_same_v); + static_assert(lexy::is_byte_encoding); auto byte = reader.peek(); if (byte == Reader::encoding::eof() @@ -118,14 +118,14 @@ struct _bits : token_base<_bits> return false; reader.bump(); - end = reader.position(); + end = reader.current(); return true; } template constexpr void report_error(Context& context, const Reader&) { - auto err = lexy::error(end, "bits"); + auto err = lexy::error(end.position(), "bits"); context.on(_ev::error{}, err); } }; diff --git a/3rdparty/lexy/include/lexy/dsl/bom.hpp b/3rdparty/lexy/include/lexy/dsl/bom.hpp index e19fa7e55..a3010cc37 100644 --- a/3rdparty/lexy/include/lexy/dsl/bom.hpp +++ b/3rdparty/lexy/include/lexy/dsl/bom.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_BOM_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/brackets.hpp b/3rdparty/lexy/include/lexy/dsl/brackets.hpp index cde68ffee..7e461c929 100644 --- a/3rdparty/lexy/include/lexy/dsl/brackets.hpp +++ b/3rdparty/lexy/include/lexy/dsl/brackets.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_BRACKETS_HPP_INCLUDED @@ -100,7 +100,8 @@ struct _brackets template constexpr auto brackets(Open, Close) { - static_assert(lexy::is_branch_rule && lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Open, "brackets()"); + LEXY_REQUIRE_BRANCH_RULE(Close, "brackets()"); return _brackets{}; } diff --git a/3rdparty/lexy/include/lexy/dsl/branch.hpp b/3rdparty/lexy/include/lexy/dsl/branch.hpp index 2156c9d75..1bbd7fd18 100644 --- a/3rdparty/lexy/include/lexy/dsl/branch.hpp +++ b/3rdparty/lexy/include/lexy/dsl/branch.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_BRANCH_HPP_INCLUDED @@ -31,19 +31,19 @@ struct _br : _copy_base template constexpr auto operator>>(Condition, Then) { - static_assert(lexy::is_branch_rule, "condition must be a branch"); + LEXY_REQUIRE_BRANCH_RULE(Condition, "Left-hand-side of >>"); return _br{}; } template constexpr auto operator>>(Condition, _seq) { - static_assert(lexy::is_branch_rule, "condition must be a branch"); + LEXY_REQUIRE_BRANCH_RULE(Condition, "Left-hand-side of >>"); return _br{}; } template constexpr auto operator>>(Condition, _br) { - static_assert(lexy::is_branch_rule, "condition must be a branch"); + LEXY_REQUIRE_BRANCH_RULE(Condition, "Left-hand-side of >>"); return _br{}; } diff --git a/3rdparty/lexy/include/lexy/dsl/byte.hpp b/3rdparty/lexy/include/lexy/dsl/byte.hpp index 804dba1be..32df8597b 100644 --- a/3rdparty/lexy/include/lexy/dsl/byte.hpp +++ b/3rdparty/lexy/include/lexy/dsl/byte.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_BYTE_HPP_INCLUDED @@ -7,58 +7,140 @@ #include #include #include +#include #include //=== byte ===// namespace lexyd { -template -struct _b : token_base<_b> +template +struct _b : token_base<_b> { static_assert(N > 0); + static constexpr bool _match(lexy::byte_encoding::int_type cur) + { + if (cur == lexy::byte_encoding::eof()) + return false; + + if constexpr (!std::is_void_v) + { + constexpr auto predicate = Predicate{}; + return predicate(static_cast(cur)); + } + else + { + return true; + } + } + template > struct tp; + template struct tp> { - typename Reader::iterator end; + static_assert(lexy::is_byte_encoding); + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { - static_assert(std::is_same_v); - // Bump N times. - auto result = ((reader.peek() == Reader::encoding::eof() ? ((void)Idx, false) - : (reader.bump(), true)) - && ...); - end = reader.position(); + auto result + = ((_match(reader.peek()) ? (reader.bump(), true) : ((void)Idx, false)) && ...); + end = reader.current(); return result; } template constexpr void report_error(Context& context, const Reader&) { - auto err = lexy::error(end, "byte"); + constexpr auto name + = std::is_void_v ? "byte" : lexy::_detail::type_name(); + auto err = lexy::error(end.position(), name); context.on(_ev::error{}, err); } }; + + //=== dsl ===// + template + constexpr auto if_() const + { + static_assert(std::is_void_v); + return _b{}; + } + + template + constexpr auto range() const + { + struct predicate + { + static LEXY_CONSTEVAL auto name() + { + return "byte.range"; + } + + constexpr bool operator()(unsigned char byte) const + { + return Low <= byte && byte <= High; + } + }; + + return if_(); + } + + template + constexpr auto set() const + { + struct predicate + { + static LEXY_CONSTEVAL auto name() + { + return "byte.set"; + } + + constexpr bool operator()(unsigned char byte) const + { + return ((byte == Bytes) || ...); + } + }; + + return if_(); + } + + constexpr auto ascii() const + { + struct predicate + { + static LEXY_CONSTEVAL auto name() + { + return "byte.ASCII"; + } + + constexpr bool operator()(unsigned char byte) const + { + return byte <= 0x7F; + } + }; + + return if_(); + } }; /// Matches an arbitrary byte. -constexpr auto byte = _b<1>{}; +constexpr auto byte = _b<1, void>{}; /// Matches N arbitrary bytes. template -constexpr auto bytes = _b{}; +constexpr auto bytes = _b{}; } // namespace lexyd namespace lexy { template -constexpr auto token_kind_of> = lexy::any_token_kind; +constexpr auto token_kind_of> = lexy::any_token_kind; } // namespace lexy //=== padding bytes ===// @@ -84,13 +166,14 @@ struct _pb : branch_base template struct bp { - typename Reader::iterator end; + static_assert(lexy::is_byte_encoding); + typename Reader::marker end; constexpr auto try_parse(const void*, const Reader& reader) { - lexy::token_parser_for<_b, Reader> parser(reader); - auto result = parser.try_parse(reader); - end = parser.end; + lexy::token_parser_for<_b, Reader> parser(reader); + auto result = parser.try_parse(reader); + end = parser.end; return result; } @@ -102,10 +185,10 @@ struct _pb : branch_base LEXY_PARSER_FUNC auto finish(Context& context, Reader& reader, Args&&... args) { auto begin = reader.position(); - context.on(_ev::token{}, lexy::any_token_kind, begin, end); - reader.set_position(end); + context.on(_ev::token{}, lexy::any_token_kind, begin, end.position()); + reader.reset(end); - _validate(context, reader, begin, end); + _validate(context, reader, begin, end.position()); return lexy::whitespace_parser::parse(context, reader, LEXY_FWD(args)...); } @@ -117,8 +200,9 @@ struct _pb : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_byte_encoding); auto begin = reader.position(); - if (!_b::token_parse(context, reader)) + if (!_b::token_parse(context, reader)) return false; auto end = reader.position(); @@ -167,6 +251,7 @@ auto _bint() return 0; } } + template using bint = decltype(_bint()); } // namespace lexy::_detail @@ -187,10 +272,11 @@ namespace lexyd template struct _bint : branch_base { - using _rule = lexy::_detail::type_or>; + using _rule = lexy::_detail::type_or>; template > struct _pc; + template struct _pc> { @@ -238,7 +324,8 @@ struct _bint : branch_base template struct bp { - typename Reader::iterator end; + static_assert(lexy::is_byte_encoding); + typename Reader::marker end; constexpr auto try_parse(const void*, const Reader& reader) { @@ -256,10 +343,11 @@ struct _bint : branch_base LEXY_PARSER_FUNC auto finish(Context& context, Reader& reader, Args&&... args) { auto begin = reader.position(); - context.on(_ev::token{}, _rule{}, begin, end); - reader.set_position(end); + context.on(_ev::token{}, _rule{}, begin, end.position()); + reader.reset(end); - return _pc::parse(context, reader, begin, end, LEXY_FWD(args)...); + return _pc::parse(context, reader, begin, end.position(), + LEXY_FWD(args)...); } }; @@ -269,6 +357,7 @@ struct _bint : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_byte_encoding); auto begin = reader.position(); if (!_rule::token_parse(context, reader)) return false; @@ -308,4 +397,3 @@ inline constexpr auto big_bint64 = _bint<8, lexy::_detail::bint_big>{}; } // namespace lexyd #endif // LEXY_DSL_BYTE_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/dsl/capture.hpp b/3rdparty/lexy/include/lexy/dsl/capture.hpp index e6fa59520..92d4d8de2 100644 --- a/3rdparty/lexy/include/lexy/dsl/capture.hpp +++ b/3rdparty/lexy/include/lexy/dsl/capture.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CAPTURE_HPP_INCLUDED @@ -16,7 +16,7 @@ struct _cap : _copy_base template struct bp { - typename Reader::iterator end; + typename Reader::marker end; constexpr auto try_parse(const void*, const Reader& reader) { @@ -35,12 +35,12 @@ struct _cap : _copy_base { auto begin = reader.position(); - context.on(_ev::token{}, Token{}, begin, end); - reader.set_position(end); + context.on(_ev::token{}, Token{}, begin, end.position()); + reader.reset(end); using continuation = lexy::whitespace_parser; return continuation::parse(context, reader, LEXY_FWD(args)..., - lexy::lexeme(begin, end)); + lexy::lexeme(begin, end.position())); } }; diff --git a/3rdparty/lexy/include/lexy/dsl/case_folding.hpp b/3rdparty/lexy/include/lexy/dsl/case_folding.hpp index d51647a62..c4beb55dd 100644 --- a/3rdparty/lexy/include/lexy/dsl/case_folding.hpp +++ b/3rdparty/lexy/include/lexy/dsl/case_folding.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CASE_FOLDING_HPP_INCLUDED @@ -45,10 +45,10 @@ struct _cfl : token_base<_cfl>, _lit_base struct tp { lexy::token_parser_for> impl; - typename Reader::iterator end; + typename Reader::marker end; constexpr explicit tp(const Reader& reader) - : impl(CaseFolding{reader}), end(reader.position()) + : impl(CaseFolding{reader}), end(reader.current()) {} constexpr bool try_parse(Reader _reader) @@ -84,6 +84,7 @@ struct _acfr // ascii case folding reader using encoding = typename Reader::encoding; using iterator = typename Reader::iterator; + using marker = typename Reader::marker; constexpr auto peek() const -> typename encoding::int_type { @@ -104,9 +105,13 @@ struct _acfr // ascii case folding reader return _impl.position(); } - constexpr void set_position(iterator new_pos) + constexpr marker current() const noexcept { - _impl.set_position(new_pos); + return _impl.current(); + } + constexpr void reset(marker m) noexcept + { + _impl.reset(m); } }; } // namespace lexy @@ -146,6 +151,7 @@ struct _sucfr32 // simple unicode case folding reader, UTF-32 using encoding = typename Reader::encoding; using iterator = typename Reader::iterator; + using marker = typename Reader::marker; constexpr auto peek() const -> typename encoding::int_type { @@ -163,9 +169,13 @@ struct _sucfr32 // simple unicode case folding reader, UTF-32 return _impl.position(); } - constexpr void set_position(iterator new_pos) + constexpr marker current() const noexcept { - _impl.set_position(new_pos); + return _impl.current(); + } + constexpr void reset(marker m) noexcept + { + _impl.reset(m); } }; @@ -174,22 +184,23 @@ struct _sucfrm // simple unicode case folding reader, UTF-8 and UTF-16 { using encoding = typename Reader::encoding; using iterator = typename Reader::iterator; + using marker = typename Reader::marker; Reader _impl; - typename Reader::iterator _cur_pos; + typename Reader::marker _cur_pos; typename encoding::char_type _buffer[4]; unsigned char _buffer_size; unsigned char _buffer_cur; constexpr explicit _sucfrm(Reader impl) - : _impl(impl), _cur_pos(_impl.position()), _buffer{}, _buffer_size(0), _buffer_cur(0) + : _impl(impl), _cur_pos(_impl.current()), _buffer{}, _buffer_size(0), _buffer_cur(0) { _fill(); } constexpr void _fill() { - _cur_pos = _impl.position(); + _cur_pos = _impl.current(); // We need to read the next code point at this point. auto result = lexy::_detail::parse_code_point(_impl); @@ -200,13 +211,13 @@ struct _sucfrm // simple unicode case folding reader, UTF-8 and UTF-16 _buffer_size = static_cast( lexy::_detail::encode_code_point(folded.value(), _buffer, 4)); _buffer_cur = 0; - _impl.set_position(result.end); + _impl.reset(result.end); } else { // Fill the buffer with the partial code point. _buffer_cur = _buffer_size = 0; - while (_impl.position() != result.end) + while (_impl.position() != result.end.position()) { _buffer[_buffer_size] = static_cast(_impl.peek()); ++_buffer_size; @@ -233,22 +244,23 @@ struct _sucfrm // simple unicode case folding reader, UTF-8 and UTF-16 constexpr iterator position() const { - // We only report the position at a code point boundary. + return current().position(); + } + + constexpr marker current() const noexcept + { + // We only report a marker at a code point boundary. // This has two consequences: // 1. If we don't match a rule, the error token does not include any common start code - // units. - // That's actually nice, and makes it unnecessary to handle that situation in the error - // reporting. The only relevant difference is in the error token. + // units. That's actually nice, and makes it unnecessary to handle that situation in the + // error reporting. The only relevant difference is in the error token. // 2. If the user wants to match partial code unit sequences, the behavior can become buggy. // However, that's not really something we should worry about. return _cur_pos; } - - constexpr void set_position(iterator new_pos) + constexpr void reset(marker m) noexcept { - // It's a code point boundary, so reset. - _impl.set_position(new_pos); - _fill(); + _impl.reset(m); } }; diff --git a/3rdparty/lexy/include/lexy/dsl/char_class.hpp b/3rdparty/lexy/include/lexy/dsl/char_class.hpp index c8e7516f7..cc09ab31e 100644 --- a/3rdparty/lexy/include/lexy/dsl/char_class.hpp +++ b/3rdparty/lexy/include/lexy/dsl/char_class.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CHAR_CLASS_HPP_INCLUDED @@ -204,17 +204,19 @@ struct char_class_base : token_base, _char_class_base template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { + static_assert(lexy::is_char_encoding); + using matcher = lexy::_detail::ascii_set_matcher<_cas>; if (matcher::template match(reader.peek())) { reader.bump(); - end = reader.position(); + end = reader.current(); return true; } @@ -223,38 +225,37 @@ struct char_class_base : token_base, _char_class_base { return false; } - else if constexpr (std::is_same_v // - || std::is_same_v) + else if constexpr (lexy::is_unicode_encoding) { - static_assert(!Derived::char_class_unicode(), - "cannot use this character class with default/byte_encoding"); + static_assert(Derived::char_class_unicode(), + "cannot use this character class with Unicode encoding"); - if (reader.peek() == Reader::encoding::eof()) + // Parse one code point. + auto result = lexy::_detail::parse_code_point(reader); + if (result.error != lexy::_detail::cp_error::success) return false; - auto cp = static_cast(reader.peek()); - reader.bump(); - - if (!Derived::char_class_match_cp(cp)) + if (!Derived::char_class_match_cp(result.cp)) return false; - end = reader.position(); + end = result.end; return true; } else { - static_assert(Derived::char_class_unicode(), - "cannot use this character class with Unicode encoding"); + static_assert(!Derived::char_class_unicode(), + "cannot use this character class with non-Unicode char encodings"); - // Parse one code point. - auto result = lexy::_detail::parse_code_point(reader); - if (result.error != lexy::_detail::cp_error::success) + if (reader.peek() == Reader::encoding::eof()) return false; - if (!Derived::char_class_match_cp(result.cp)) + auto cp = static_cast(reader.peek()); + reader.bump(); + + if (!Derived::char_class_match_cp(cp)) return false; - end = result.end; + end = reader.current(); return true; } } @@ -361,8 +362,8 @@ constexpr auto _make_char_class(C c) return c; } template || std::is_same_v>> + typename = std::enable_if_t + || std::is_same_v>> constexpr auto _make_char_class(_lit) { if constexpr (std::is_same_v) @@ -411,8 +412,8 @@ struct _calt : char_class_base<_calt> static constexpr auto char_class_match_cp(char32_t cp) { - if constexpr ((std::is_same_v && ...)) + if constexpr ((std::is_same_v + && ...)) return std::false_type{}; else return (Cs::char_class_match_cp(cp) || ...); @@ -572,8 +573,8 @@ struct _cand : char_class_base<_cand> static constexpr auto char_class_match_cp(char32_t cp) { - if constexpr ((std::is_same_v && ...)) + if constexpr ((std::is_same_v + && ...)) return std::false_type{}; else return (Cs::char_class_match_cp(cp) && ...); diff --git a/3rdparty/lexy/include/lexy/dsl/choice.hpp b/3rdparty/lexy/include/lexy/dsl/choice.hpp index 22672147a..ed0fbd952 100644 --- a/3rdparty/lexy/include/lexy/dsl/choice.hpp +++ b/3rdparty/lexy/include/lexy/dsl/choice.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CHOICE_HPP_INCLUDED @@ -134,20 +134,20 @@ struct _chc template constexpr auto operator|(R, S) { - static_assert(lexy::is_branch_rule, "choice requires a branch condition"); - static_assert(lexy::is_branch_rule, "choice requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(R, "choice"); + LEXY_REQUIRE_BRANCH_RULE(S, "choice"); return _chc{}; } template constexpr auto operator|(_chc, S) { - static_assert(lexy::is_branch_rule, "choice requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(S, "choice"); return _chc{}; } template constexpr auto operator|(R, _chc) { - static_assert(lexy::is_branch_rule, "choice requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(R, "choice"); return _chc{}; } template diff --git a/3rdparty/lexy/include/lexy/dsl/code_point.hpp b/3rdparty/lexy/include/lexy/dsl/code_point.hpp index 2658be22a..bc09666aa 100644 --- a/3rdparty/lexy/include/lexy/dsl/code_point.hpp +++ b/3rdparty/lexy/include/lexy/dsl/code_point.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CODE_POINT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/combination.hpp b/3rdparty/lexy/include/lexy/dsl/combination.hpp index 0d6b96c71..73db67b97 100644 --- a/3rdparty/lexy/include/lexy/dsl/combination.hpp +++ b/3rdparty/lexy/include/lexy/dsl/combination.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_COMBINATION_HPP_INCLUDED @@ -130,7 +130,7 @@ struct _comb : rule_base template constexpr auto combination(R...) { - static_assert((lexy::is_branch_rule && ...), "combination() requires a branch rule"); + LEXY_REQUIRE_BRANCH_RULE(R..., "combination()"); static_assert((!lexy::is_unconditional_branch_rule && ...), "combination() does not support unconditional branches"); return _comb{}; @@ -141,7 +141,7 @@ constexpr auto combination(R...) template constexpr auto partial_combination(R...) { - static_assert((lexy::is_branch_rule && ...), "partial_combination() requires a branch rule"); + LEXY_REQUIRE_BRANCH_RULE(R..., "partial_combination()"); static_assert((!lexy::is_unconditional_branch_rule && ...), "partial_combination() does not support unconditional branches"); // If the choice no longer matches, we just break. diff --git a/3rdparty/lexy/include/lexy/dsl/context_counter.hpp b/3rdparty/lexy/include/lexy/dsl/context_counter.hpp index 5efe371bc..411ca1ad9 100644 --- a/3rdparty/lexy/include/lexy/dsl/context_counter.hpp +++ b/3rdparty/lexy/include/lexy/dsl/context_counter.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CONTEXT_COUNTER_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/context_flag.hpp b/3rdparty/lexy/include/lexy/dsl/context_flag.hpp index 20d0e6307..6782c5322 100644 --- a/3rdparty/lexy/include/lexy/dsl/context_flag.hpp +++ b/3rdparty/lexy/include/lexy/dsl/context_flag.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CONTEXT_FLAG_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/context_identifier.hpp b/3rdparty/lexy/include/lexy/dsl/context_identifier.hpp index b797c0293..6850904f9 100644 --- a/3rdparty/lexy/include/lexy/dsl/context_identifier.hpp +++ b/3rdparty/lexy/include/lexy/dsl/context_identifier.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_CONTEXT_IDENTIFIER_HPP_INCLUDED @@ -73,7 +73,7 @@ struct _ctx_irem : branch_base template struct bp { - typename Reader::iterator end; + typename Reader::marker end; template constexpr bool try_parse(const ControlBlock* cb, const Reader& reader) @@ -85,7 +85,7 @@ struct _ctx_irem : branch_base end = parser.end; // The two lexemes need to be equal. - auto lexeme = lexy::lexeme(reader.position(), end); + auto lexeme = lexy::lexeme(reader.position(), end.position()); return lexy::_detail::equal_lexemes(_ctx_id::get(cb), lexeme); } @@ -97,8 +97,9 @@ struct _ctx_irem : branch_base LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { // Finish parsing the token. - context.on(_ev::token{}, lexy::identifier_token_kind, reader.position(), end); - reader.set_position(end); + context.on(_ev::token{}, lexy::identifier_token_kind, reader.position(), + end.position()); + reader.reset(end); return lexy::whitespace_parser::parse(context, reader, LEXY_FWD(args)...); } diff --git a/3rdparty/lexy/include/lexy/dsl/delimited.hpp b/3rdparty/lexy/include/lexy/dsl/delimited.hpp index d72dc502f..0b6684d94 100644 --- a/3rdparty/lexy/include/lexy/dsl/delimited.hpp +++ b/3rdparty/lexy/include/lexy/dsl/delimited.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_DELIMITED_HPP_INCLUDED @@ -110,12 +110,33 @@ struct _del_chars else if constexpr (!std::is_same_v) { - // Try to match any code point in default_encoding or byte_encoding. - if constexpr (std::is_same_v // - || std::is_same_v) + if constexpr (lexy::is_unicode_encoding) + { + static_assert(CharClass::char_class_unicode(), + "cannot use this character class with Unicode encoding"); + + auto result = lexy::_detail::parse_code_point(reader); + if (result.error == lexy::_detail::cp_error::success + && CharClass::char_class_match_cp(result.cp)) + { + reader.reset(result.end); + } + else + { + finish(context, sink, reader.position()); + + auto recover_begin = reader.position(); + if (recover_begin == result.end.position()) + reader.bump(); + else + reader.reset(result.end); + _recover(context, recover_begin, reader.position()); + } + } + else { static_assert(!CharClass::char_class_unicode(), - "cannot use this character class with default/byte_encoding"); + "cannot use this character class with non-Unicode char encoding"); LEXY_ASSERT(reader.peek() != encoding::eof(), "EOF should be checked before calling this"); @@ -129,25 +150,6 @@ struct _del_chars _recover(context, recover_begin, reader.position()); } } - // Otherwise, try to match Unicode characters. - else - { - static_assert(CharClass::char_class_unicode(), - "cannot use this character class with Unicode encoding"); - - auto result = lexy::_detail::parse_code_point(reader); - if (result.error == lexy::_detail::cp_error::success - && CharClass::char_class_match_cp(result.cp)) - { - reader.set_position(result.end); - } - else - { - finish(context, sink, reader.position()); - _recover(context, reader.position(), result.end); - reader.set_position(result.end); - } - } } // It doesn't match Unicode characters. else @@ -253,6 +255,7 @@ struct _del : rule_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_char_encoding); auto sink = context.value_callback().sink(); // Parse characters until we have the closing delimiter. @@ -325,7 +328,8 @@ struct _delim_dsl template constexpr auto delimited(Open, Close) { - static_assert(lexy::is_branch_rule && lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Open, "delimited()"); + LEXY_REQUIRE_BRANCH_RULE(Close, "delimited()"); return _delim_dsl{}; } @@ -333,7 +337,7 @@ constexpr auto delimited(Open, Close) template constexpr auto delimited(Delim) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Delim, "delimited()"); return _delim_dsl{}; } @@ -424,7 +428,7 @@ struct _escape : _escape_base template constexpr auto rule(Branch) const { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Branch, "escape()"); return _escape{}; } @@ -432,7 +436,7 @@ struct _escape : _escape_base template constexpr auto capture(Branch branch) const { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Branch, "escape()"); return this->rule(lexy::dsl::capture(branch)); } diff --git a/3rdparty/lexy/include/lexy/dsl/digit.hpp b/3rdparty/lexy/include/lexy/dsl/digit.hpp index 33232cfc2..a3f1dc61d 100644 --- a/3rdparty/lexy/include/lexy/dsl/digit.hpp +++ b/3rdparty/lexy/include/lexy/dsl/digit.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_DIGIT_HPP_INCLUDED @@ -310,7 +310,8 @@ constexpr bool _match_digits(Reader& reader) // ... then manually to get any trailing digits. while (lexy::try_match_token(digit, reader)) - {} + { + } return true; } @@ -355,24 +356,27 @@ struct _digits_st : token_base<_digits_st> template struct tp { - typename Reader::iterator end; - bool forbidden_leading_zero; + typename Reader::marker end; + bool forbidden_leading_zero; constexpr explicit tp(const Reader& reader) - : end(reader.position()), forbidden_leading_zero(false) + : end(reader.current()), forbidden_leading_zero(false) {} constexpr bool try_parse(Reader reader) { using char_type = typename Reader::encoding::char_type; - auto begin = reader.position(); + auto begin = reader.current(); auto result = _match_digits_sep(reader); - end = reader.position(); + end = reader.current(); - if (result && lexy::_detail::next(begin) != end - && *begin == lexy::_detail::transcode_char('0')) + if (result && lexy::_detail::next(begin.position()) != end.position() + && *begin.position() == lexy::_detail::transcode_char('0')) { - end = lexy::_detail::next(begin); + reader.reset(begin); + reader.bump(); + end = reader.current(); + forbidden_leading_zero = true; return false; } @@ -385,14 +389,14 @@ struct _digits_st : token_base<_digits_st> { if (forbidden_leading_zero) { - auto err - = lexy::error(reader.position(), end); + auto err = lexy::error(reader.position(), + end.position()); context.on(_ev::error{}, err); } else { - auto err - = lexy::error(end, Base::char_class_name()); + auto err = lexy::error(end.position(), + Base::char_class_name()); context.on(_ev::error{}, err); } } @@ -405,21 +409,22 @@ struct _digits_s : token_base<_digits_s> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { auto result = _match_digits_sep(reader); - end = reader.position(); + end = reader.current(); return result; } template constexpr void report_error(Context& context, const Reader&) { - auto err = lexy::error(end, Base::char_class_name()); + auto err = lexy::error(end.position(), + Base::char_class_name()); context.on(_ev::error{}, err); } }; @@ -436,24 +441,27 @@ struct _digits_t : token_base<_digits_t> template struct tp { - typename Reader::iterator end; - bool forbidden_leading_zero; + typename Reader::marker end; + bool forbidden_leading_zero; constexpr explicit tp(const Reader& reader) - : end(reader.position()), forbidden_leading_zero(false) + : end(reader.current()), forbidden_leading_zero(false) {} constexpr bool try_parse(Reader reader) { using char_type = typename Reader::encoding::char_type; - auto begin = reader.position(); + auto begin = reader.current(); auto result = _match_digits(reader); - end = reader.position(); + end = reader.current(); - if (result && lexy::_detail::next(begin) != end - && *begin == lexy::_detail::transcode_char('0')) + if (result && lexy::_detail::next(begin.position()) != end.position() + && *begin.position() == lexy::_detail::transcode_char('0')) { - end = lexy::_detail::next(begin); + reader.reset(begin); + reader.bump(); + end = reader.current(); + forbidden_leading_zero = true; return false; } @@ -467,7 +475,7 @@ struct _digits_t : token_base<_digits_t> if (forbidden_leading_zero) { auto err = lexy::error(reader.position(), - this->end); + end.position()); context.on(_ev::error{}, err); } else @@ -493,14 +501,14 @@ struct _digits : token_base<_digits> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { auto result = _match_digits(reader); - end = reader.position(); + end = reader.current(); return result; } @@ -557,16 +565,16 @@ struct _ndigits_s : token_base<_ndigits_s> template struct tp> { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { // Match the Base one time. if (!lexy::try_match_token(digit, reader)) { - end = reader.position(); + end = reader.current(); return false; } @@ -574,14 +582,15 @@ struct _ndigits_s : token_base<_ndigits_s> auto success = (((void)Idx, lexy::try_match_token(Sep{}, reader), lexy::try_match_token(digit, reader)) && ...); - end = reader.position(); + end = reader.current(); return success; } template constexpr void report_error(Context& context, const Reader&) { - auto err = lexy::error(end, Base::char_class_name()); + auto err = lexy::error(end.position(), + Base::char_class_name()); context.on(_ev::error{}, err); } }; @@ -597,22 +606,23 @@ struct _ndigits : token_base<_ndigits> template struct tp> { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { // Match the Base N times. auto success = (((void)Idx, lexy::try_match_token(digit, reader)) && ...); - end = reader.position(); + end = reader.current(); return success; } template constexpr void report_error(Context& context, const Reader&) { - auto err = lexy::error(end, Base::char_class_name()); + auto err = lexy::error(end.position(), + Base::char_class_name()); context.on(_ev::error{}, err); } }; diff --git a/3rdparty/lexy/include/lexy/dsl/eof.hpp b/3rdparty/lexy/include/lexy/dsl/eof.hpp index 3c934357e..beb96cb97 100644 --- a/3rdparty/lexy/include/lexy/dsl/eof.hpp +++ b/3rdparty/lexy/include/lexy/dsl/eof.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_EOF_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/error.hpp b/3rdparty/lexy/include/lexy/dsl/error.hpp index 341e26f7d..7be4fac65 100644 --- a/3rdparty/lexy/include/lexy/dsl/error.hpp +++ b/3rdparty/lexy/include/lexy/dsl/error.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_ERROR_HPP_INCLUDED @@ -10,6 +10,14 @@ namespace lexyd { +template +struct _err_production +{ + static constexpr auto name = ""; + static constexpr auto max_recursion_depth = 0; + static constexpr auto rule = Rule{}; +}; + template struct _err : unconditional_branch_base { @@ -23,9 +31,17 @@ struct _err : unconditional_branch_base auto end = reader.position(); if constexpr (!std::is_same_v) { - lexy::token_parser_for parser(reader); - parser.try_parse(reader); - end = parser.end; + auto backtrack = reader.current(); + + // We match a dummy production that only consists of the rule. + lexy::do_action< + _err_production, + lexy::match_action::template result_type>(lexy::_mh(), + context.control_block + ->parse_state, + reader); + end = reader.position(); + reader.reset(LEXY_MOV(backtrack)); } auto err = lexy::error(begin, end); @@ -102,7 +118,7 @@ struct _must_dsl template constexpr auto must(Branch) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Branch, "must()"); static_assert(!lexy::is_unconditional_branch_rule); return _must_dsl{}; } diff --git a/3rdparty/lexy/include/lexy/dsl/expression.hpp b/3rdparty/lexy/include/lexy/dsl/expression.hpp index 0b8fe505e..a7d4f94fa 100644 --- a/3rdparty/lexy/include/lexy/dsl/expression.hpp +++ b/3rdparty/lexy/include/lexy/dsl/expression.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_EXPRESSION_HPP_INCLUDED @@ -197,7 +197,7 @@ struct operation_list (void)((cur_idx <= op.idx && op.idx < cur_idx + op_of::op_literals::size ? (result = Continuation::parse(context, reader, - parsed_operator{op.pos, + parsed_operator{op.cur, op.idx - cur_idx}, LEXY_FWD(args)...), true) @@ -309,7 +309,7 @@ struct _expr : rule_base if (op.idx >= op_rule::op_literals::size) { // The list ends at this point. - reader.set_position(op.pos); + reader.reset(op.cur); break; } @@ -381,10 +381,11 @@ struct _expr : rule_base if (op.idx < op_rule::op_literals::size) { using tag = typename Context::production::operator_chain_error; - auto err = lexy::error(op.pos, reader.position()); + auto err + = lexy::error(op.cur.position(), reader.position()); context.on(_ev::error{}, err); } - reader.set_position(op.pos); + reader.reset(op.cur); } } else if constexpr (binding_power.is_postfix()) @@ -416,11 +417,11 @@ struct _expr : rule_base if (state.cur_nesting_level++ >= production::max_operator_nesting) { using tag = typename production::operator_nesting_error; - auto err = lexy::error(op.pos, reader.position()); + auto err = lexy::error(op.cur.position(), reader.position()); context.on(_ev::error{}, err); // We do not recover, to prevent stack overflow. - reader.set_position(op.pos); + reader.reset(op.cur); return false; } @@ -437,7 +438,7 @@ struct _expr : rule_base { // Operators can't be grouped. using tag = typename production::operator_group_error; - auto err = lexy::error(op.pos, reader.position()); + auto err = lexy::error(op.cur.position(), reader.position()); context.on(_ev::error{}, err); // Trivially recover, but don't update group: // let the first one stick. @@ -470,11 +471,11 @@ struct _expr : rule_base if (op.idx >= op_list::ops::size) { // We don't have a prefix operator, so it must be an atom. - reader.set_position(op.pos); + reader.reset(op.cur); return atom_parser::parse(context, reader); } - auto start_event = context.on(_ev::operation_chain_start{}, op.pos); + auto start_event = context.on(_ev::operation_chain_start{}, op.cur.position()); auto result = op_list::template apply<_continuation>(context, reader, op, state); context.on(_ev::operation_chain_finish{}, LEXY_MOV(start_event), reader.position()); return result; @@ -507,7 +508,7 @@ struct _expr : rule_base auto op = parse_operator(reader); if (op.idx >= op_list::ops::size) { - reader.set_position(op.pos); + reader.reset(op.cur); break; } diff --git a/3rdparty/lexy/include/lexy/dsl/flags.hpp b/3rdparty/lexy/include/lexy/dsl/flags.hpp index a86f7410a..51cd1f948 100644 --- a/3rdparty/lexy/include/lexy/dsl/flags.hpp +++ b/3rdparty/lexy/include/lexy/dsl/flags.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_FLAGS_HPP_INCLUDED @@ -126,9 +126,15 @@ struct _flag : rule_base template constexpr auto flag(Rule) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Rule, "flag()"); return _flag{}; } + +template +constexpr auto flag(Rule rule) +{ + return flag(rule); +} } // namespace lexyd #endif // LEXY_DSL_FLAGS_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/follow.hpp b/3rdparty/lexy/include/lexy/dsl/follow.hpp index 38abd3539..9d47e09dd 100644 --- a/3rdparty/lexy/include/lexy/dsl/follow.hpp +++ b/3rdparty/lexy/include/lexy/dsl/follow.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_FOLLOW_HPP_INCLUDED @@ -49,11 +49,11 @@ struct _nf : token_base<_nf>, _lit_base struct tp { lexy::token_parser_for impl; - typename Reader::iterator end; + typename Reader::marker end; bool literal_success; constexpr explicit tp(const Reader& reader) - : impl(reader), end(reader.position()), literal_success(false) + : impl(reader), end(reader.current()), literal_success(false) {} constexpr bool try_parse(Reader reader) @@ -67,7 +67,7 @@ struct _nf : token_base<_nf>, _lit_base literal_success = true; // To match, we must not match the char class now. - reader.set_position(end); + reader.reset(end); if constexpr (std::is_void_v) { return !lexy::try_match_token(CharClass{}, reader); @@ -88,7 +88,8 @@ struct _nf : token_base<_nf>, _lit_base } else { - auto err = lexy::error(end, end); + auto err + = lexy::error(end.position(), end.position()); context.on(_ev::error{}, err); } } diff --git a/3rdparty/lexy/include/lexy/dsl/identifier.hpp b/3rdparty/lexy/include/lexy/dsl/identifier.hpp index b388a7bc3..1b780f00f 100644 --- a/3rdparty/lexy/include/lexy/dsl/identifier.hpp +++ b/3rdparty/lexy/include/lexy/dsl/identifier.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_IDENTIFIER_HPP_INCLUDED @@ -36,12 +36,14 @@ struct _idp : token_base<_idp> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { + static_assert(lexy::is_char_encoding); + // Need to match Leading character. if (!lexy::try_match_token(Leading{}, reader)) return false; @@ -61,7 +63,7 @@ struct _idp : token_base<_idp> break; } - end = reader.position(); + end = reader.current(); return true; } @@ -170,7 +172,7 @@ struct _id : branch_base template struct bp { - typename Reader::iterator end; + typename Reader::marker end; constexpr bool try_parse(const void*, const Reader& reader) { @@ -181,7 +183,8 @@ struct _id : branch_base end = parser.end; // We only succeed if it's not a reserved identifier. - [[maybe_unused]] auto input = lexy::partial_input(reader, reader.position(), end); + [[maybe_unused]] auto input + = lexy::partial_input(reader, reader.position(), end.position()); return !(ReservedPredicate::is_reserved(input) || ...); } @@ -194,12 +197,12 @@ struct _id : branch_base { auto begin = reader.position(); - context.on(_ev::token{}, lexy::identifier_token_kind, begin, end); - reader.set_position(end); + context.on(_ev::token{}, lexy::identifier_token_kind, begin, end.position()); + reader.reset(end); using continuation = lexy::whitespace_parser; return continuation::parse(context, reader, LEXY_FWD(args)..., - lexy::lexeme(begin, end)); + lexy::lexeme(begin, end.position())); } }; @@ -341,16 +344,16 @@ struct _kw : token_base<_kw>, _lit_base template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { // Need to match the literal. if (!lexy::_detail::match_literal<0, CharT, C...>(reader)) return false; - end = reader.position(); + end = reader.current(); // To qualify as a keyword, and not just the prefix of an identifier, // we must not have a trailing identifier character. diff --git a/3rdparty/lexy/include/lexy/dsl/if.hpp b/3rdparty/lexy/include/lexy/dsl/if.hpp index 48889a679..ff4f1d4a0 100644 --- a/3rdparty/lexy/include/lexy/dsl/if.hpp +++ b/3rdparty/lexy/include/lexy/dsl/if.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_IF_HPP_INCLUDED @@ -36,7 +36,7 @@ struct _if : rule_base template constexpr auto if_(Branch) { - static_assert(lexy::is_branch_rule, "if_() requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(Branch, "if()"); if constexpr (lexy::is_unconditional_branch_rule) // Branch is always taken, so don't wrap in if_(). return Branch{}; diff --git a/3rdparty/lexy/include/lexy/dsl/integer.hpp b/3rdparty/lexy/include/lexy/dsl/integer.hpp index 435f2adec..95475fa0c 100644 --- a/3rdparty/lexy/include/lexy/dsl/integer.hpp +++ b/3rdparty/lexy/include/lexy/dsl/integer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_INTEGER_HPP_INCLUDED @@ -414,7 +414,7 @@ struct _int : _copy_base template struct bp { - typename Reader::iterator end; + typename Reader::marker end; constexpr auto try_parse(const void*, const Reader& reader) { @@ -432,10 +432,11 @@ struct _int : _copy_base LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { auto begin = reader.position(); - context.on(_ev::token{}, Token{}, begin, end); - reader.set_position(end); + context.on(_ev::token{}, Token{}, begin, end.position()); + reader.reset(end); - return _pc::parse(context, reader, begin, end, LEXY_FWD(args)...); + return _pc::parse(context, reader, begin, end.position(), + LEXY_FWD(args)...); } }; @@ -448,17 +449,19 @@ struct _int : _copy_base auto begin = reader.position(); if (lexy::token_parser_for parser(reader); parser.try_parse(reader)) { - context.on(_ev::token{}, typename Token::token_type{}, begin, parser.end); - reader.set_position(parser.end); + context.on(_ev::token{}, typename Token::token_type{}, begin, + parser.end.position()); + reader.reset(parser.end); } else { parser.report_error(context, reader); - reader.set_position(parser.end); + reader.reset(parser.end); // To recover we try and skip additional digits. while (lexy::try_match_token(digit, reader)) - {} + { + } auto recovery_end = reader.position(); if (begin == recovery_end) diff --git a/3rdparty/lexy/include/lexy/dsl/list.hpp b/3rdparty/lexy/include/lexy/dsl/list.hpp index 861d93177..25b85076d 100644 --- a/3rdparty/lexy/include/lexy/dsl/list.hpp +++ b/3rdparty/lexy/include/lexy/dsl/list.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_LIST_HPP_INCLUDED @@ -132,8 +132,7 @@ struct _lst : _copy_base template constexpr auto list(Item) { - static_assert(lexy::is_branch_rule, - "list() without a separator requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(Item, "list() without a separator"); return _lst{}; } @@ -148,8 +147,7 @@ constexpr auto list(Item, _sep) template constexpr auto list(Item, _tsep) { - static_assert(lexy::is_branch_rule, - "list() without a trailing separator requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(Item, "list() with a trailing separator"); return _lst>{}; } diff --git a/3rdparty/lexy/include/lexy/dsl/literal.hpp b/3rdparty/lexy/include/lexy/dsl/literal.hpp index 4fc1b6066..adc2cf599 100644 --- a/3rdparty/lexy/include/lexy/dsl/literal.hpp +++ b/3rdparty/lexy/include/lexy/dsl/literal.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_LITERAL_HPP_INCLUDED @@ -18,6 +18,7 @@ namespace lexy::_detail template constexpr auto match_literal(Reader& reader) { + static_assert(lexy::is_char_encoding); using char_type = typename Reader::encoding::char_type; if constexpr (CurCharIndex >= sizeof...(Cs)) { @@ -184,11 +185,11 @@ struct _merge_case_folding typename H::lit_case_folding, CurrentCaseFolding>, T...> { - static_assert( - std::is_same_v // - || std::is_void_v || std::is_void_v, - "cannot mix literals with different case foldings in a literal_set"); + static_assert(std::is_same_v // + || std::is_void_v + || std::is_void_v, + "cannot mix literals with different case foldings in a literal_set"); }; template @@ -272,7 +273,7 @@ struct lit_trie_matcher if constexpr (sizeof...(Idx) > 0) { - auto cur_pos = reader.position(); + auto cur = reader.current(); auto cur_char = reader.peek(); auto next_value = Trie.node_no_match; @@ -283,7 +284,7 @@ struct lit_trie_matcher return next_value; // We haven't found a longer match, return our match. - reader.set_position(cur_pos); + reader.reset(cur); } // But first, we might need to check that we don't match that nodes char class. @@ -305,6 +306,7 @@ struct lit_trie_matcher template LEXY_FORCE_INLINE static constexpr std::size_t try_match(Reader& _reader) { + static_assert(lexy::is_char_encoding); if constexpr (std::is_same_v, Reader>) { return _impl<>::try_match(_reader); @@ -313,7 +315,7 @@ struct lit_trie_matcher { CaseFolding reader{_reader}; auto result = _impl<>::try_match(reader); - _reader.set_position(reader.position()); + _reader.reset(reader.current()); return result; } } @@ -350,14 +352,14 @@ struct _lit template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr auto try_parse(Reader reader) { auto result = lexy::_detail::match_literal<0, CharT, C...>(reader); - end = reader.position(); + end = reader.current(); return result; } @@ -368,7 +370,7 @@ struct _lit constexpr auto str = lexy::_detail::type_string::template c_str; auto begin = reader.position(); - auto index = lexy::_detail::range_size(begin, this->end); + auto index = lexy::_detail::range_size(begin, end.position()); auto err = lexy::error(begin, str, index, sizeof...(C)); context.on(_ev::error{}, err); } @@ -445,9 +447,9 @@ struct _lcp : token_base<_lcp>, _lit_base template struct tp> { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { @@ -455,7 +457,7 @@ struct _lcp : token_base<_lcp>, _lit_base auto result = lexy::_detail::match_literal<0, typename encoding::char_type, _string.data[Idx]...>(reader); - end = reader.position(); + end = reader.current(); return result; } @@ -465,7 +467,7 @@ struct _lcp : token_base<_lcp>, _lit_base using encoding = typename Reader::encoding; auto begin = reader.position(); - auto index = lexy::_detail::range_size(begin, end); + auto index = lexy::_detail::range_size(begin, end.position()); auto err = lexy::error(begin, _string.data, index, _string.length); context.on(_ev::error{}, err); @@ -537,9 +539,9 @@ struct _lset : token_base<_lset>, _lset_base template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { @@ -547,7 +549,7 @@ struct _lset : token_base<_lset>, _lset_base using matcher = lexy::_detail::lit_trie_matcher<_t, 0>; auto result = matcher::try_match(reader); - end = reader.position(); + end = reader.current(); return result != _t.node_no_match; } diff --git a/3rdparty/lexy/include/lexy/dsl/lookahead.hpp b/3rdparty/lexy/include/lexy/dsl/lookahead.hpp index 37c69d611..3ee995a18 100644 --- a/3rdparty/lexy/include/lexy/dsl/lookahead.hpp +++ b/3rdparty/lexy/include/lexy/dsl/lookahead.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_LOOKAHEAD_HPP_INCLUDED @@ -50,6 +50,8 @@ struct _look : branch_base template struct bp { + static_assert(lexy::is_char_encoding); + typename Reader::iterator begin; typename Reader::iterator end; @@ -102,6 +104,7 @@ struct _look : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_char_encoding); bp impl{}; if (!impl.try_parse(context.control_block, reader)) { diff --git a/3rdparty/lexy/include/lexy/dsl/loop.hpp b/3rdparty/lexy/include/lexy/dsl/loop.hpp index 68a433ff2..e7988d270 100644 --- a/3rdparty/lexy/include/lexy/dsl/loop.hpp +++ b/3rdparty/lexy/include/lexy/dsl/loop.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_LOOP_HPP_INCLUDED @@ -94,7 +94,7 @@ struct _whl : rule_base template constexpr auto while_(Rule) { - static_assert(lexy::is_branch_rule, "while() requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(Rule, "while()"); return _whl{}; } } // namespace lexyd @@ -105,7 +105,7 @@ namespace lexyd template constexpr auto while_one(Rule rule) { - static_assert(lexy::is_branch_rule, "while_one() requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(Rule, "while_one()"); return rule >> while_(rule); } } // namespace lexyd diff --git a/3rdparty/lexy/include/lexy/dsl/member.hpp b/3rdparty/lexy/include/lexy/dsl/member.hpp index afc6bf3e5..a478ef2dd 100644 --- a/3rdparty/lexy/include/lexy/dsl/member.hpp +++ b/3rdparty/lexy/include/lexy/dsl/member.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_MEMBER_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/newline.hpp b/3rdparty/lexy/include/lexy/dsl/newline.hpp index fc34556c7..24078f032 100644 --- a/3rdparty/lexy/include/lexy/dsl/newline.hpp +++ b/3rdparty/lexy/include/lexy/dsl/newline.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_NEWLINE_HPP_INCLUDED @@ -36,6 +36,8 @@ struct _eol : branch_base template struct bp { + static_assert(lexy::is_char_encoding); + constexpr bool try_parse(const void*, Reader reader) { return reader.peek() == Reader::encoding::eof() @@ -70,6 +72,7 @@ struct _eol : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_char_encoding); return bp{}.template finish(context, reader, LEXY_FWD(args)...); } }; diff --git a/3rdparty/lexy/include/lexy/dsl/operator.hpp b/3rdparty/lexy/include/lexy/dsl/operator.hpp index b992e31df..188ebf19a 100644 --- a/3rdparty/lexy/include/lexy/dsl/operator.hpp +++ b/3rdparty/lexy/include/lexy/dsl/operator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_OPERATOR_HPP_INCLUDED @@ -75,8 +75,8 @@ struct op_lit_list template struct parsed_operator { - typename Reader::iterator pos; - std::size_t idx; + typename Reader::marker cur; + std::size_t idx; }; template @@ -85,7 +85,7 @@ constexpr auto parse_operator(Reader& reader) using encoding = typename Reader::encoding; using op_matcher = lexy::_detail::lit_trie_matcher, 0>; - auto begin = reader.position(); + auto begin = reader.current(); auto op = op_matcher::try_match(reader); return parsed_operator{begin, op}; } @@ -96,6 +96,11 @@ namespace lexyd template using _detect_op_tag_ctor = decltype(Tag(LEXY_DECLVAL(Reader).position())); +template +using _detect_op_tag_ctor_with_state + = decltype(Tag(*LEXY_DECLVAL(Context).control_block->parse_state, + LEXY_DECLVAL(Reader).position())); + template struct _op : branch_base { @@ -107,15 +112,20 @@ struct _op : branch_base lexy::_detail::parsed_operator op, Args&&... args) { - context.on(_ev::token{}, typename Literal::token_type{}, op.pos, reader.position()); + context.on(_ev::token{}, typename Literal::token_type{}, op.cur.position(), + reader.position()); using continuation = lexy::whitespace_parser, NextParser>>; if constexpr (std::is_void_v) return continuation::parse(context, reader, LEXY_FWD(args)...); + else if constexpr (lexy::_detail::is_detected<_detect_op_tag_ctor_with_state, op_tag_type, + Reader, Context>) + return continuation::parse(context, reader, LEXY_FWD(args)..., + op_tag_type(*context.control_block->parse_state, op.pos)); else if constexpr (lexy::_detail::is_detected<_detect_op_tag_ctor, op_tag_type, Reader>) return continuation::parse(context, reader, LEXY_FWD(args)..., - op_tag_type(reader.position())); + op_tag_type(op.cur.position())); else return continuation::parse(context, reader, LEXY_FWD(args)..., op_tag_type{}); } @@ -144,6 +154,12 @@ struct _op : branch_base if constexpr (std::is_void_v) return impl.template finish(context, reader, LEXY_FWD(args)...); + else if constexpr (lexy::_detail::is_detected<_detect_op_tag_ctor_with_state, + op_tag_type, Reader, Context>) + return impl + .template finish(context, reader, LEXY_FWD(args)..., + op_tag_type(*context.control_block->parse_state, + reader.position())); else if constexpr (lexy::_detail::is_detected<_detect_op_tag_ctor, op_tag_type, Reader>) return impl.template finish(context, reader, LEXY_FWD(args)..., op_tag_type(reader.position())); @@ -165,6 +181,10 @@ struct _op : branch_base = lexy::parser_for, NextParser>>; if constexpr (std::is_void_v) return continuation::parse(context, reader, LEXY_FWD(args)...); + else if constexpr (lexy::_detail::is_detected<_detect_op_tag_ctor_with_state, + op_tag_type, Reader, Context>) + return continuation::parse(context, reader, LEXY_FWD(args)..., + op_tag_type(*context.control_block->parse_state, pos)); else if constexpr (lexy::_detail::is_detected<_detect_op_tag_ctor, op_tag_type, Reader>) return continuation::parse(context, reader, LEXY_FWD(args)..., op_tag_type(pos)); else @@ -246,12 +266,12 @@ struct _opc : branch_base struct bp { lexy::_detail::parsed_operator op; - typename Reader::iterator end; + typename Reader::marker end; constexpr auto try_parse(const void*, Reader reader) { op = lexy::_detail::parse_operator(reader); - end = reader.position(); + end = reader.current(); return op.idx < op_literals::size; } @@ -262,7 +282,7 @@ struct _opc : branch_base template LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { - reader.set_position(end); + reader.reset(end); return op_finish(context, reader, op, LEXY_FWD(args)...); } }; @@ -276,7 +296,7 @@ struct _opc : branch_base bp impl{}; if (!impl.try_parse(context.control_block, reader)) { - auto err = lexy::error(impl.op.pos); + auto err = lexy::error(impl.op.cur.position()); context.on(_ev::error{}, err); return false; } @@ -311,4 +331,3 @@ constexpr auto operator/(_opc, _opc) } // namespace lexyd #endif // LEXY_DSL_OPERATOR_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/dsl/option.hpp b/3rdparty/lexy/include/lexy/dsl/option.hpp index 9ef1f7cc0..0ba0c7404 100644 --- a/3rdparty/lexy/include/lexy/dsl/option.hpp +++ b/3rdparty/lexy/include/lexy/dsl/option.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_OPTION_HPP_INCLUDED @@ -80,7 +80,7 @@ struct _opt : rule_base template constexpr auto opt(Rule) { - static_assert(lexy::is_branch_rule, "opt() requires a branch condition"); + LEXY_REQUIRE_BRANCH_RULE(Rule, "opt()"); if constexpr (lexy::is_unconditional_branch_rule) // Branch is always taken, so don't wrap in opt(). return Rule{}; diff --git a/3rdparty/lexy/include/lexy/dsl/parse_as.hpp b/3rdparty/lexy/include/lexy/dsl/parse_as.hpp index 27e8e161a..4efdde15a 100644 --- a/3rdparty/lexy/include/lexy/dsl/parse_as.hpp +++ b/3rdparty/lexy/include/lexy/dsl/parse_as.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_PARSE_AS_HPP_INCLUDED @@ -11,7 +11,7 @@ namespace lexyd { // Custom handler that forwards events but overrides the value callback. -template +template struct _pas_handler { Handler& _handler; @@ -26,31 +26,38 @@ struct _pas_handler return static_cast(_handler); } - // For child productions, use ::value to get a value. + // We use ::value to get a value. + // We can't use it unconditionally, as the initial production that contains the parse_as might + // not have one. So we silently fallback if that's the case - this might cause worse errors if + // the value is missing. template - struct value_callback : lexy::production_value_callback - { - using lexy::production_value_callback::production_value_callback; - }; - // For the production that contains parse_as, use lexy::construct. - template - struct value_callback : lexy::_construct + using value_callback + = std::conditional_t, + lexy::production_value_callback, + lexy::_detail::void_value_callback>; +}; + +struct _pas_final_parser +{ + template + LEXY_PARSER_FUNC static bool parse(Context&, Reader&, lexy::_detail::lazy_init& value, + Args&&... args) { - constexpr value_callback() = default; - constexpr value_callback(State*) {} - }; + value.emplace_result(lexy::construct, LEXY_FWD(args)...); + return true; + } }; -template +template constexpr auto _make_pas_handler(Handler& handler) { - return _pas_handler{handler}; + return _pas_handler{handler}; } // Prevent infinite nesting when parse_as itself is recursive. -template -constexpr auto _make_pas_handler(_pas_handler& handler) +template +constexpr auto _make_pas_handler(_pas_handler& handler) { - return _pas_handler{handler._handler}; + return handler; } template @@ -77,18 +84,20 @@ struct _pas : _copy_base template LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { - auto handler = _make_pas_handler( - context.control_block->parse_handler); + auto handler = _make_pas_handler(context.control_block->parse_handler); lexy::_detail::parse_context_control_block cb(LEXY_MOV(handler), context.control_block); using context_type = lexy::_pc; context_type sub_context(&cb); + sub_context.handler = LEXY_MOV(context).handler; - auto result - = rule_parser.template finish(sub_context, reader); + lexy::_detail::lazy_init value; + auto result + = rule_parser.template finish<_pas_final_parser>(sub_context, reader, value); context.control_block->copy_vars_from(&cb); + context.handler = LEXY_MOV(sub_context).handler; if (!result) return false; @@ -96,11 +105,9 @@ struct _pas : _copy_base // NOLINTNEXTLINE: clang-tidy wrongly thinks the branch is repeated. return NextParser::parse(context, reader, LEXY_FWD(args)...); else if constexpr (Front) - return NextParser::parse(context, reader, *LEXY_MOV(sub_context.value), - LEXY_FWD(args)...); + return NextParser::parse(context, reader, *LEXY_MOV(value), LEXY_FWD(args)...); else - return NextParser::parse(context, reader, LEXY_FWD(args)..., - *LEXY_MOV(sub_context.value)); + return NextParser::parse(context, reader, LEXY_FWD(args)..., *LEXY_MOV(value)); } }; @@ -110,18 +117,20 @@ struct _pas : _copy_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { - auto handler = _make_pas_handler( - context.control_block->parse_handler); + auto handler = _make_pas_handler(context.control_block->parse_handler); lexy::_detail::parse_context_control_block cb(LEXY_MOV(handler), context.control_block); using context_type = lexy::_pc; context_type sub_context(&cb); + sub_context.handler = LEXY_MOV(context).handler; - auto result - = lexy::parser_for::parse(sub_context, reader); + lexy::_detail::lazy_init value; + auto result + = lexy::parser_for::parse(sub_context, reader, value); context.control_block->copy_vars_from(&cb); + context.handler = LEXY_MOV(sub_context).handler; if (!result) return false; @@ -129,11 +138,9 @@ struct _pas : _copy_base // NOLINTNEXTLINE: clang-tidy wrongly thinks the branch is repeated. return NextParser::parse(context, reader, LEXY_FWD(args)...); else if constexpr (Front) - return NextParser::parse(context, reader, *LEXY_MOV(sub_context.value), - LEXY_FWD(args)...); + return NextParser::parse(context, reader, *LEXY_MOV(value), LEXY_FWD(args)...); else - return NextParser::parse(context, reader, LEXY_FWD(args)..., - *LEXY_MOV(sub_context.value)); + return NextParser::parse(context, reader, LEXY_FWD(args)..., *LEXY_MOV(value)); } }; }; diff --git a/3rdparty/lexy/include/lexy/dsl/parse_tree_node.hpp b/3rdparty/lexy/include/lexy/dsl/parse_tree_node.hpp new file mode 100644 index 000000000..c8aff2505 --- /dev/null +++ b/3rdparty/lexy/include/lexy/dsl/parse_tree_node.hpp @@ -0,0 +1,251 @@ +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors +// SPDX-License-Identifier: BSL-1.0 + +#ifndef LEXY_DSL_PARSE_TREE_NODE_HPP_INCLUDED +#define LEXY_DSL_PARSE_TREE_NODE_HPP_INCLUDED + +#include +#include + +#if !LEXY_EXPERIMENTAL +# error "lexy::dsl::tnode/pnode are experimental" +#endif + +//=== impl ===// +namespace lexyd +{ +template +struct _n; + +template +struct _nr : branch_base +{ + template + struct _cont + { + template + LEXY_PARSER_FUNC static bool parse(Context& context, ChildReader& child_reader, + bool& rule_succeded, Reader& reader, Args&&... args) + { + rule_succeded = true; + + if (child_reader.peek() != ChildReader::encoding::eof()) + { + auto begin = child_reader.position(); + auto end = reader.position(); + context.on(_ev::token{}, lexy::error_token_kind, begin, end); + + auto err = lexy::error(begin, end); + context.on(_ev::error{}, err); + } + + return lexy::whitespace_parser::parse(context, reader, + LEXY_FWD(args)...); + } + }; + + template + LEXY_PARSER_FUNC static bool _parse_rule(Context& context, Reader& reader, + typename Reader::marker end, Args&&... args) + { + auto child_reader = Derived::node_child_reader(reader); + reader.reset(end); + + using rule_parser + = lexy::whitespace_parser>>; + if (auto rule_succeded = false; + rule_parser::parse(context, child_reader, rule_succeded, reader, LEXY_FWD(args)...)) + { + return true; + } + else + { + if (!rule_succeded) + // Report an error token for the child span that wasn't able to be parsed. + context.on(_ev::token{}, lexy::error_token_kind, child_reader.position(), + end.position()); + return false; + } + } + + template + struct bp + { + typename Reader::marker end; + + constexpr bool try_parse(const void*, const Reader& reader) + { + lexy::token_parser_for<_n, Reader> parser(reader); + auto result = parser.try_parse(reader); + end = parser.end; + return result; + } + + template + constexpr void cancel(Context&) + {} + + template + LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) + { + return _parse_rule(context, reader, end, LEXY_FWD(args)...); + } + }; + + template + struct p + { + template + LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) + { + lexy::token_parser_for<_n, Reader> parser(reader); + if (!parser.try_parse(reader)) + { + LEXY_ASSERT(parser.end.position() == reader.position(), "impl should be LL(1)"); + parser.report_error(context, reader); + return false; + } + + return _parse_rule(context, reader, parser.end, LEXY_FWD(args)...); + } + }; +}; + +template +struct _n : token_base +{ + template + struct tp + { + typename Reader::marker end; + + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} + + constexpr auto try_parse(Reader reader) + { + if constexpr (lexy::is_node_encoding) + { + if (!Reader::encoding::match(reader.peek(), Derived::node_kind())) + return false; + + reader.bump(); + end = reader.current(); + return true; + } + else + { + // This happens when it is used as whitespace, which is inherited while parsing the + // token lexeme, we don't match anything in that case. + return std::false_type{}; + } + } + + template + constexpr void report_error(Context& context, Reader reader) + { + constexpr auto name = Derived::node_kind_name(); + + auto err = lexy::error(reader.position(), name); + context.on(_ev::error{}, err); + } + }; + + template + constexpr auto operator()(Rule) const + { + return _nr{}; + } +}; +} // namespace lexyd + +//=== dsl::tnode ===// +namespace lexy +{ +struct expected_token_end +{ + static LEXY_CONSTEVAL auto name() + { + return "expected token end"; + } +}; +} // namespace lexy + +namespace lexyd +{ +template +struct _tn : _n<_tn> +{ + static LEXY_CONSTEVAL auto node_kind() + { + return Kind; + } + + static LEXY_CONSTEVAL auto node_kind_name() + { + using lexy::token_kind_name; + return token_kind_name(Kind); + } + + using node_end_error = lexy::expected_token_end; + + template + static constexpr auto node_child_reader(Reader& reader) + { + return reader.lexeme_reader(); + } +}; + +template +constexpr auto tnode = _tn{}; +} // namespace lexyd + +namespace lexy +{ +template +constexpr auto token_kind_of> = Kind; +} // namespace lexy + +//=== dsl::pnode ===// +namespace lexy +{ +struct expected_production_end +{ + static LEXY_CONSTEVAL auto name() + { + return "expected production end"; + } +}; +} // namespace lexy + +namespace lexyd +{ +template +struct _pn : _n<_pn> +{ + static_assert(lexy::is_production); + + static LEXY_CONSTEVAL auto node_kind() + { + return Production{}; + } + + static LEXY_CONSTEVAL auto node_kind_name() + { + return lexy::production_name(); + } + + using node_end_error = lexy::expected_production_end; + + template + static constexpr auto node_child_reader(Reader& reader) + { + return reader.child_reader(); + } +}; + +template +constexpr auto pnode = _pn{}; +} // namespace lexyd + +#endif // LEXY_DSL_PARSE_TREE_NODE_HPP_INCLUDED + diff --git a/3rdparty/lexy/include/lexy/dsl/peek.hpp b/3rdparty/lexy/include/lexy/dsl/peek.hpp index 933521f8a..57b3576b8 100644 --- a/3rdparty/lexy/include/lexy/dsl/peek.hpp +++ b/3rdparty/lexy/include/lexy/dsl/peek.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_PEEK_HPP_INCLUDED @@ -37,7 +37,7 @@ struct _peek : branch_base struct bp { typename Reader::iterator begin; - typename Reader::iterator end; + typename Reader::marker end; constexpr bool try_parse(const void*, Reader reader) { @@ -54,13 +54,13 @@ struct _peek : branch_base template constexpr void cancel(Context& context) { - context.on(_ev::backtracked{}, begin, end); + context.on(_ev::backtracked{}, begin, end.position()); } template LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { - context.on(_ev::backtracked{}, begin, end); + context.on(_ev::backtracked{}, begin, end.position()); return NextParser::parse(context, reader, LEXY_FWD(args)...); } }; @@ -76,13 +76,13 @@ struct _peek : branch_base { // Report that we've failed. using tag = lexy::_detail::type_or; - auto err = lexy::error(impl.begin, impl.end); + auto err = lexy::error(impl.begin, impl.end.position()); context.on(_ev::error{}, err); // But recover immediately, as we wouldn't have consumed anything either way. } - context.on(_ev::backtracked{}, impl.begin, impl.end); + context.on(_ev::backtracked{}, impl.begin, impl.end.position()); return NextParser::parse(context, reader, LEXY_FWD(args)...); } }; @@ -98,7 +98,7 @@ struct _peekn : branch_base struct bp { typename Reader::iterator begin; - typename Reader::iterator end; + typename Reader::marker end; constexpr bool try_parse(const void*, Reader reader) { @@ -115,13 +115,13 @@ struct _peekn : branch_base template constexpr void cancel(Context& context) { - context.on(_ev::backtracked{}, begin, end); + context.on(_ev::backtracked{}, begin, end.position()); } template LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { - context.on(_ev::backtracked{}, begin, end); + context.on(_ev::backtracked{}, begin, end.position()); return NextParser::parse(context, reader, LEXY_FWD(args)...); } }; @@ -137,20 +137,20 @@ struct _peekn : branch_base { // Report that we've failed. using tag = lexy::_detail::type_or; - auto err = lexy::error(impl.begin, impl.end); + auto err = lexy::error(impl.begin, impl.end.position()); context.on(_ev::error{}, err); // And recover by consuming the input. context.on(_ev::recovery_start{}, impl.begin); - context.on(_ev::token{}, lexy::error_token_kind, impl.begin, impl.end); - context.on(_ev::recovery_finish{}, impl.end); + context.on(_ev::token{}, lexy::error_token_kind, impl.begin, impl.end.position()); + context.on(_ev::recovery_finish{}, impl.end.position()); - reader.set_position(impl.end); + reader.reset(impl.end); return NextParser::parse(context, reader, LEXY_FWD(args)...); } else { - context.on(_ev::backtracked{}, impl.begin, impl.end); + context.on(_ev::backtracked{}, impl.begin, impl.end.position()); return NextParser::parse(context, reader, LEXY_FWD(args)...); } } diff --git a/3rdparty/lexy/include/lexy/dsl/position.hpp b/3rdparty/lexy/include/lexy/dsl/position.hpp index b1ab70232..088187bf9 100644 --- a/3rdparty/lexy/include/lexy/dsl/position.hpp +++ b/3rdparty/lexy/include/lexy/dsl/position.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_POSITION_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/production.hpp b/3rdparty/lexy/include/lexy/dsl/production.hpp index 225b55bd2..ba74de2a7 100644 --- a/3rdparty/lexy/include/lexy/dsl/production.hpp +++ b/3rdparty/lexy/include/lexy/dsl/production.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_PRODUCTION_HPP_INCLUDED @@ -179,7 +179,7 @@ struct _recb : branch_base template struct bp { - static_assert(lexy::is_branch_rule>); + LEXY_REQUIRE_BRANCH_RULE(lexy::production_rule, "recurse_branch"); using impl = lexy::branch_parser_for<_prd, Reader>; impl _impl; diff --git a/3rdparty/lexy/include/lexy/dsl/punctuator.hpp b/3rdparty/lexy/include/lexy/dsl/punctuator.hpp index 9e1937a7c..e53f7b0f2 100644 --- a/3rdparty/lexy/include/lexy/dsl/punctuator.hpp +++ b/3rdparty/lexy/include/lexy/dsl/punctuator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_PUNCTUATOR_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/recover.hpp b/3rdparty/lexy/include/lexy/dsl/recover.hpp index 0a31ae659..208d8c409 100644 --- a/3rdparty/lexy/include/lexy/dsl/recover.hpp +++ b/3rdparty/lexy/include/lexy/dsl/recover.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_RECOVER_HPP_INCLUDED @@ -38,17 +38,24 @@ struct _recovery_wrapper : _recovery_base LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { context.on(_ev::recovery_start{}, reader.position()); - auto recovery_finished = false; - auto result - = lexy::parser_for::parse(context, reader, recovery_finished, - LEXY_FWD(args)...); + + // As part of the recovery, we parse the rule and whitespace. + using parser = lexy::parser_for>; + auto result = parser::parse(context, reader, recovery_finished, LEXY_FWD(args)...); + if (!recovery_finished) context.on(_ev::recovery_cancel{}, reader.position()); return result; } }; }; + +struct _noop_recovery : rule_base +{ + template + using p = NextParser; +}; } // namespace lexyd namespace lexyd @@ -72,20 +79,20 @@ struct _find : _recovery_base context.on(_ev::recovery_start{}, begin); while (true) { - auto end = reader.position(); // *before* we've consumed Token/Limit + auto end = reader.current(); // *before* we've consumed Token/Limit auto result = matcher::try_match(reader); if (result == 0) { - context.on(_ev::token{}, lexy::error_token_kind, begin, end); - context.on(_ev::recovery_finish{}, end); - reader.set_position(end); // reset to before the token + context.on(_ev::token{}, lexy::error_token_kind, begin, end.position()); + context.on(_ev::recovery_finish{}, end.position()); + reader.reset(end); // reset to before the token return NextParser::parse(context, reader, LEXY_FWD(args)...); } else if (result == 1 || reader.peek() == Reader::encoding::eof()) { - context.on(_ev::token{}, lexy::error_token_kind, begin, end); - context.on(_ev::recovery_cancel{}, end); - reader.set_position(end); // reset to before the limit + context.on(_ev::token{}, lexy::error_token_kind, begin, end.position()); + context.on(_ev::recovery_cancel{}, end.position()); + reader.reset(end); // reset to before the limit return false; } else @@ -200,7 +207,7 @@ template constexpr auto recover(Branches...) { static_assert(sizeof...(Branches) > 0); - static_assert((lexy::is_branch_rule && ...)); + LEXY_REQUIRE_BRANCH_RULE(Branches..., "recover"); return _reco{}; } } // namespace lexyd @@ -231,13 +238,23 @@ struct _tryt : rule_base LEXY_PARSER_FUNC static bool recover(Context& context, Reader& reader, Args&&... args) { if constexpr (std::is_void_v) - return NextParser::parse(context, reader, LEXY_FWD(args)...); + { + using recovery_rule = _recovery_wrapper<_noop_recovery>; + return lexy::parser_for::parse(context, reader, + LEXY_FWD(args)...); + } else if constexpr (std::is_base_of_v<_recovery_base, Recover>) - return lexy::parser_for::parse(context, reader, - LEXY_FWD(args)...); + { + using recovery_rule = Recover; + return lexy::parser_for::parse(context, reader, + LEXY_FWD(args)...); + } else - return lexy::parser_for<_recovery_wrapper, - NextParser>::parse(context, reader, LEXY_FWD(args)...); + { + using recovery_rule = _recovery_wrapper; + return lexy::parser_for::parse(context, reader, + LEXY_FWD(args)...); + } } }; diff --git a/3rdparty/lexy/include/lexy/dsl/repeat.hpp b/3rdparty/lexy/include/lexy/dsl/repeat.hpp index 7321d54ad..bb41404b6 100644 --- a/3rdparty/lexy/include/lexy/dsl/repeat.hpp +++ b/3rdparty/lexy/include/lexy/dsl/repeat.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_REPEAT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/return.hpp b/3rdparty/lexy/include/lexy/dsl/return.hpp index e3f7269ba..46477f6f0 100644 --- a/3rdparty/lexy/include/lexy/dsl/return.hpp +++ b/3rdparty/lexy/include/lexy/dsl/return.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_RETURN_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/scan.hpp b/3rdparty/lexy/include/lexy/dsl/scan.hpp index 313dd2d57..d630fd61c 100644 --- a/3rdparty/lexy/include/lexy/dsl/scan.hpp +++ b/3rdparty/lexy/include/lexy/dsl/scan.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_SCAN_HPP_INCLUDED @@ -18,7 +18,9 @@ struct _prd; template struct _peek; template -struct _capt; +struct _cap; +template +struct _capr; template struct _int_dsl; @@ -184,6 +186,10 @@ class scanner { return _reader.position(); } + constexpr auto current() const noexcept -> typename Reader::marker + { + return _reader.current(); + } constexpr auto remaining_input() const noexcept { @@ -228,7 +234,7 @@ class scanner template >> constexpr bool branch(scan_result& result, Rule) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Rule, "branch"); if (_state == _state_failed) return false; @@ -323,6 +329,13 @@ class scanner context.on(parse_events::error{}, lexy::error(LEXY_FWD(args)...)); } + template + constexpr void error(const char* msg, Args&&... args) + { + auto& context = static_cast(*this).context(); + context.on(parse_events::error{}, lexy::error(LEXY_FWD(args)..., msg)); + } + template constexpr void fatal_error(Tag tag, Args&&... args) { @@ -330,6 +343,13 @@ class scanner _state = _state_failed; } + template + constexpr void fatal_error(const char* msg, Args&&... args) + { + error(msg, LEXY_FWD(args)...); + _state = _state_failed; + } + //=== convenience ===// template >> constexpr auto parse(Rule rule) @@ -361,25 +381,18 @@ class scanner return result; } - template - constexpr auto capture(Rule rule) -> scan_result> + template + constexpr auto capture(Token) { - static_assert(lexy::is_rule); - - auto begin = _reader.position(); - parse(rule); - auto end = _reader.position(); - - if (*this) - return lexeme(begin, end); - else - return scan_failed; + scan_result> result; + parse(result, lexyd::_cap{}); + return result; } - template - constexpr auto capture_token(Token) + template + constexpr auto capture(lexyd::_prd) { scan_result> result; - parse(result, lexyd::_capt{}); + parse(result, lexyd::_capr>{}); return result; } @@ -446,8 +459,9 @@ class rule_scanner : public _detail::scanner, Read namespace lexyd { -template -using _detect_scan_state = decltype(Context::production::scan(LEXY_DECLVAL(Scanner&), *StatePtr())); +template +using _detect_scan_state = decltype(Context::production::scan(LEXY_DECLVAL(Scanner&), *StatePtr(), + LEXY_DECLVAL(Args)...)); struct _scan : rule_base { @@ -458,16 +472,16 @@ struct _scan : rule_base LEXY_PARSER_FUNC static bool _parse(Scanner& scanner, Context& context, Reader& reader, Args&&... args) { - lexy::scan_result result = [&] { + typename Context::production::scan_result result = [&] { if constexpr (lexy::_detail::is_detected< _detect_scan_state, Context, decltype(scanner), - decltype(context.control_block->parse_state)>) + decltype(context.control_block->parse_state), Args&&...>) return Context::production::scan(scanner, *context.control_block->parse_state, LEXY_FWD(args)...); else return Context::production::scan(scanner, LEXY_FWD(args)...); }(); - reader.set_position(scanner.position()); + reader.reset(scanner.current()); if (!result) return false; diff --git a/3rdparty/lexy/include/lexy/dsl/separator.hpp b/3rdparty/lexy/include/lexy/dsl/separator.hpp index 175f7bf92..f50744d66 100644 --- a/3rdparty/lexy/include/lexy/dsl/separator.hpp +++ b/3rdparty/lexy/include/lexy/dsl/separator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_SEPARATOR_HPP_INCLUDED @@ -90,7 +90,7 @@ struct _sep : _sep_base template constexpr auto sep(Branch) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Branch, "sep"); return _sep{}; } @@ -110,7 +110,7 @@ struct _tsep : _sep_base template constexpr auto trailing_sep(Branch) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Branch, "trailing_sep"); return _tsep{}; } diff --git a/3rdparty/lexy/include/lexy/dsl/sequence.hpp b/3rdparty/lexy/include/lexy/dsl/sequence.hpp index 02a098fa3..6715e7ae3 100644 --- a/3rdparty/lexy/include/lexy/dsl/sequence.hpp +++ b/3rdparty/lexy/include/lexy/dsl/sequence.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_SEQUENCE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/sign.hpp b/3rdparty/lexy/include/lexy/dsl/sign.hpp index c0178b275..5cf38de0d 100644 --- a/3rdparty/lexy/include/lexy/dsl/sign.hpp +++ b/3rdparty/lexy/include/lexy/dsl/sign.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_SIGN_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/subgrammar.hpp b/3rdparty/lexy/include/lexy/dsl/subgrammar.hpp index 9f4bbc97f..6a291dfc4 100644 --- a/3rdparty/lexy/include/lexy/dsl/subgrammar.hpp +++ b/3rdparty/lexy/include/lexy/dsl/subgrammar.hpp @@ -20,6 +20,9 @@ using _subgrammar_for = _subgrammar \ + constexpr auto production_has_value_callback = true; \ + \ template \ struct _subgrammar \ { \ @@ -104,4 +107,3 @@ constexpr auto subgrammar = _subg{}; } // namespace lexyd #endif // LEXY_DSL_SUBGRAMMAR_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/dsl/symbol.hpp b/3rdparty/lexy/include/lexy/dsl/symbol.hpp index f8a58a9b1..f94511068 100644 --- a/3rdparty/lexy/include/lexy/dsl/symbol.hpp +++ b/3rdparty/lexy/include/lexy/dsl/symbol.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_SYMBOL_HPP_INCLUDED @@ -268,7 +268,8 @@ struct _sym : branch_base template struct bp { - typename Reader::iterator end; + static_assert(lexy::is_char_encoding); + typename Reader::marker end; typename LEXY_DECAY_DECLTYPE(Table)::key_index symbol; constexpr auto value() const @@ -286,7 +287,7 @@ struct _sym : branch_base end = parser.end; // Check whether this is a symbol. - auto content = lexy::partial_input(reader, end); + auto content = lexy::partial_input(reader, end.position()); symbol = Table.parse(content); // Only succeed if it is a symbol. @@ -301,8 +302,8 @@ struct _sym : branch_base LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { // We need to consume and report the token. - context.on(_ev::token{}, Token{}, reader.position(), end); - reader.set_position(end); + context.on(_ev::token{}, Token{}, reader.position(), end.position()); + reader.reset(end); // And continue parsing with the symbol value after whitespace skipping. using continuation = lexy::whitespace_parser; @@ -340,6 +341,7 @@ struct _sym : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_char_encoding); // Capture the token and continue with special continuation. return lexy::parser_for<_cap, _cont>::parse(context, reader, LEXY_FWD(args)...); @@ -360,8 +362,9 @@ struct _sym, Tag> : branch_base template struct bp { + static_assert(lexy::is_char_encoding); typename LEXY_DECAY_DECLTYPE(Table)::key_index symbol; - typename Reader::iterator end; + typename Reader::marker end; constexpr auto value() const { @@ -374,7 +377,7 @@ struct _sym, Tag> : branch_base symbol = Table.try_parse(reader); if (!symbol) return false; - end = reader.position(); + end = reader.current(); // We had a symbol, but it must not be the prefix of a valid identifier. return !lexy::try_match_token(T{}, reader); @@ -388,8 +391,8 @@ struct _sym, Tag> : branch_base LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { // We need to consume and report the identifier pattern. - context.on(_ev::token{}, _idp{}, reader.position(), end); - reader.set_position(end); + context.on(_ev::token{}, _idp{}, reader.position(), end.position()); + reader.reset(end); // And continue parsing with the symbol value after whitespace skipping. using continuation = lexy::whitespace_parser; @@ -403,6 +406,7 @@ struct _sym, Tag> : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_char_encoding); auto begin = reader.position(); // Try to parse a symbol that is not the prefix of an identifier. @@ -427,9 +431,9 @@ struct _sym, Tag> : branch_base else { // We need to consume and report the identifier pattern. - auto end = symbol_reader.position(); - context.on(_ev::token{}, _idp{}, begin, end); - reader.set_position(end); + auto end = symbol_reader.current(); + context.on(_ev::token{}, _idp{}, begin, end.position()); + reader.reset(end); // And continue parsing with the symbol value after whitespace skipping. using continuation = lexy::whitespace_parser; @@ -449,8 +453,9 @@ struct _sym : branch_base template struct bp { + static_assert(lexy::is_char_encoding); typename LEXY_DECAY_DECLTYPE(Table)::key_index symbol; - typename Reader::iterator end; + typename Reader::marker end; constexpr auto value() const { @@ -461,7 +466,7 @@ struct _sym : branch_base { // Try to parse a symbol. symbol = Table.try_parse(reader); - end = reader.position(); + end = reader.current(); // Only succeed if it is a symbol. return static_cast(symbol); @@ -475,8 +480,9 @@ struct _sym : branch_base LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { // We need to consume and report the token. - context.on(_ev::token{}, lexy::identifier_token_kind, reader.position(), end); - reader.set_position(end); + context.on(_ev::token{}, lexy::identifier_token_kind, reader.position(), + end.position()); + reader.reset(end); // And continue parsing with the symbol value after whitespace skipping. using continuation = lexy::whitespace_parser; @@ -490,6 +496,7 @@ struct _sym : branch_base template LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args) { + static_assert(lexy::is_char_encoding); bp impl{}; if (impl.try_parse(context.control_block, reader)) return impl.template finish(context, reader, LEXY_FWD(args)...); diff --git a/3rdparty/lexy/include/lexy/dsl/terminator.hpp b/3rdparty/lexy/include/lexy/dsl/terminator.hpp index 9535d01d9..56a4e53df 100644 --- a/3rdparty/lexy/include/lexy/dsl/terminator.hpp +++ b/3rdparty/lexy/include/lexy/dsl/terminator.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_TERMINATOR_HPP_INCLUDED @@ -105,7 +105,7 @@ struct _term template constexpr auto terminator(Branch) { - static_assert(lexy::is_branch_rule); + LEXY_REQUIRE_BRANCH_RULE(Branch, "terminator"); return _term{}; } } // namespace lexyd diff --git a/3rdparty/lexy/include/lexy/dsl/times.hpp b/3rdparty/lexy/include/lexy/dsl/times.hpp index 9aa1e9c2c..7ebf327cd 100644 --- a/3rdparty/lexy/include/lexy/dsl/times.hpp +++ b/3rdparty/lexy/include/lexy/dsl/times.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_TIMES_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/token.hpp b/3rdparty/lexy/include/lexy/dsl/token.hpp index 809fb8684..95c812c1c 100644 --- a/3rdparty/lexy/include/lexy/dsl/token.hpp +++ b/3rdparty/lexy/include/lexy/dsl/token.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_TOKEN_HPP_INCLUDED @@ -46,7 +46,7 @@ struct token_base : _token_inherit template struct bp { - typename Reader::iterator end; + typename Reader::marker end; constexpr auto try_parse(const void*, const Reader& reader) { @@ -63,8 +63,8 @@ struct token_base : _token_inherit template LEXY_PARSER_FUNC bool finish(Context& context, Reader& reader, Args&&... args) { - context.on(_ev::token{}, Derived{}, reader.position(), end); - reader.set_position(end); + context.on(_ev::token{}, Derived{}, reader.position(), end.position()); + reader.reset(end); return lexy::whitespace_parser::parse(context, reader, LEXY_FWD(args)...); } @@ -85,16 +85,17 @@ struct token_base : _token_inherit { if (!parser.try_parse(reader)) { - context.on(_ev::token{}, lexy::error_token_kind, reader.position(), parser.end); + context.on(_ev::token{}, lexy::error_token_kind, reader.position(), + parser.end.position()); parser.report_error(context, reader); - reader.set_position(parser.end); + reader.reset(parser.end); return false; } } - context.on(_ev::token{}, typename Derived::token_type{}, begin, parser.end); - reader.set_position(parser.end); + context.on(_ev::token{}, typename Derived::token_type{}, begin, parser.end.position()); + reader.reset(parser.end); return true; } @@ -153,7 +154,7 @@ struct _toke : token_base<_toke, Token> constexpr void report_error(Context& context, const Reader& reader) { // Report a different error. - auto err = lexy::error(reader.position(), this->end); + auto err = lexy::error(reader.position(), this->end.position()); context.on(_ev::error{}, err); } }; @@ -184,9 +185,9 @@ struct _token : token_base<_token> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { @@ -196,14 +197,14 @@ struct _token : token_base<_token> lexy::match_action::template result_type>(lexy::_mh(), lexy::no_parse_state, reader); - end = reader.position(); + end = reader.current(); return success; } template constexpr void report_error(Context& context, const Reader& reader) { - auto err = lexy::error(reader.position(), end); + auto err = lexy::error(reader.position(), end.position()); context.on(_ev::error{}, err); } }; diff --git a/3rdparty/lexy/include/lexy/dsl/unicode.hpp b/3rdparty/lexy/include/lexy/dsl/unicode.hpp index 1737b06fd..e895ae3c8 100644 --- a/3rdparty/lexy/include/lexy/dsl/unicode.hpp +++ b/3rdparty/lexy/include/lexy/dsl/unicode.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_UNICODE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/dsl/until.hpp b/3rdparty/lexy/include/lexy/dsl/until.hpp index 6dc0b6346..626d0b4fd 100644 --- a/3rdparty/lexy/include/lexy/dsl/until.hpp +++ b/3rdparty/lexy/include/lexy/dsl/until.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_UNTIL_HPP_INCLUDED @@ -39,9 +39,9 @@ struct _until_eof : token_base<_until_eof, unconditional_branch_base> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr std::true_type try_parse(Reader reader) { @@ -64,7 +64,7 @@ struct _until_eof : token_base<_until_eof, unconditional_branch_base> reader.bump(); } - end = reader.position(); + end = reader.current(); return {}; } }; @@ -76,9 +76,9 @@ struct _until : token_base<_until> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr bool try_parse(Reader reader) { @@ -90,7 +90,7 @@ struct _until : token_base<_until> if (lexy::try_match_token(Condition{}, reader)) { // It did match, we're done at that end. - end = reader.position(); + end = reader.current(); return true; } @@ -100,7 +100,7 @@ struct _until : token_base<_until> if (reader.peek() == Reader::encoding::eof()) { // It did, so we did not succeed. - end = reader.position(); + end = reader.current(); return false; } @@ -117,7 +117,7 @@ struct _until : token_base<_until> // We need to trigger the error `Condition` would. // As such, we try parsing it, which will report an error. - reader.set_position(end); + reader.reset(end); LEXY_ASSERT(reader.peek() == Reader::encoding::eof(), "forgot to set end in try_parse()"); diff --git a/3rdparty/lexy/include/lexy/dsl/whitespace.hpp b/3rdparty/lexy/include/lexy/dsl/whitespace.hpp index 5ffb87dbb..f80b30dcf 100644 --- a/3rdparty/lexy/include/lexy/dsl/whitespace.hpp +++ b/3rdparty/lexy/include/lexy/dsl/whitespace.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_DSL_WHITESPACE_HPP_INCLUDED @@ -137,7 +137,8 @@ constexpr auto skip_whitespace(ws_handler&& handler, Reader& reader) { // Without SWAR, we just repeatedly skip the whitespace rule. while (lexy::try_match_token(WhitespaceRule{}, reader)) - {} + { + } } handler.real_on(lexy::parse_events::token{}, lexy::whitespace_token_kind, begin, diff --git a/3rdparty/lexy/include/lexy/encoding.hpp b/3rdparty/lexy/include/lexy/encoding.hpp index 6c154d069..4529e67a1 100644 --- a/3rdparty/lexy/include/lexy/encoding.hpp +++ b/3rdparty/lexy/include/lexy/encoding.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ENCODING_HPP_INCLUDED @@ -253,13 +253,35 @@ struct _deduce_encoding }; } // namespace lexy +//=== encoding traits ===// +namespace lexy +{ +template +constexpr auto is_unicode_encoding + = std::is_same_v || std::is_same_v + || std::is_same_v || std::is_same_v + || std::is_same_v; + +template +constexpr auto is_text_encoding + = is_unicode_encoding || std::is_same_v; + +template +constexpr auto is_byte_encoding = std::is_same_v; + +template +constexpr auto is_char_encoding = is_text_encoding || is_byte_encoding; + +template +constexpr auto is_node_encoding = false; +} // namespace lexy + //=== impls ===// namespace lexy::_detail { template -constexpr bool is_compatible_char_type - = std::is_same_v || Encoding::template is_secondary_char_type(); +constexpr bool is_compatible_char_type = std::is_same_v + || Encoding::template is_secondary_char_type(); template using require_secondary_char_type diff --git a/3rdparty/lexy/include/lexy/error.hpp b/3rdparty/lexy/include/lexy/error.hpp index 0a7645c68..77a40937d 100644 --- a/3rdparty/lexy/include/lexy/error.hpp +++ b/3rdparty/lexy/include/lexy/error.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_ERROR_HPP_INCLUDED @@ -26,6 +26,13 @@ class error : _pos(begin), _end(end), _msg(msg) {} + template >> + constexpr operator error() const noexcept + { + return error(_pos, _end, _msg); + } + constexpr auto position() const noexcept { return _pos; @@ -68,6 +75,13 @@ class error : public error typename Reader::iterator end) noexcept : error(begin, end, _detail::type_name()) {} + + template >> + constexpr operator error() const noexcept + { + return error(this->begin(), this->end()); + } }; /// Expected the literal character sequence. @@ -83,6 +97,13 @@ class error : _pos(pos), _str(str), _idx(index), _length(length) {} + template >> + constexpr operator error() const noexcept + { + return error(_pos, _str, _idx, _length); + } + constexpr auto position() const noexcept { return _pos; @@ -127,6 +148,13 @@ class error : _begin(begin), _end(end), _str(str), _length(length) {} + template >> + constexpr operator error() const noexcept + { + return error(_begin, _end, _str, _length); + } + constexpr auto position() const noexcept { return _begin; @@ -169,6 +197,13 @@ class error : _pos(pos), _name(name) {} + template >> + constexpr operator error() const noexcept + { + return error(_pos, _name); + } + constexpr auto position() const noexcept { return _pos; diff --git a/3rdparty/lexy/include/lexy/grammar.hpp b/3rdparty/lexy/include/lexy/grammar.hpp index 4c03b0aa9..b1986594e 100644 --- a/3rdparty/lexy/include/lexy/grammar.hpp +++ b/3rdparty/lexy/include/lexy/grammar.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_GRAMMAR_HPP_INCLUDED @@ -65,8 +65,17 @@ constexpr auto is_separator = std::is_base_of_v; template constexpr auto is_operation = std::is_base_of_v; + +template +constexpr bool _require_branch_rule = (is_branch_rule && ...); } // namespace lexy +#define LEXY_REQUIRE_BRANCH_RULE(Rule, Name) \ + static_assert(lexy::_require_branch_rule, Name \ + " requires a branch condition." \ + " You may need to use `>>` to specify the condition that is used for dispatch." \ + " See https://lexy.foonathan.net/learn/branching/ for more information.") + //=== predefined_token_kind ===// namespace lexy { @@ -88,7 +97,12 @@ enum predefined_token_kind : std::uint_least16_t _smallest_predefined_token_kind = digits_token_kind, }; -constexpr const char* _kind_name(predefined_token_kind kind) noexcept +template +constexpr const char* token_kind_name(const T&) noexcept +{ + return "token"; +} +constexpr const char* token_kind_name(predefined_token_kind kind) noexcept { switch (kind) { @@ -244,6 +258,9 @@ using _detect_value_of = // qualify value_of() (it causes a hard error instead of going to ::value). typename decltype(LEXY_DECLVAL(ParseState&).value_of(Production{}))::return_type; +template +using _detect_value = decltype(Production::value); + template struct _sfinae_sink { @@ -270,6 +287,11 @@ struct _sfinae_sink } }; +template +constexpr bool production_has_value_callback + = lexy::_detail::is_detected<_detect_value_of, ParseState, Production> + || lexy::_detail::is_detected<_detect_value, Production>; + template class production_value_callback { @@ -323,12 +345,14 @@ class production_value_callback template constexpr return_type operator()(Args&&... args) const { - if constexpr (lexy::is_callback_for<_type, Args&&...>) + if constexpr (lexy::is_callback_with_state_for<_type, ParseState, Args&&...> + && !std::is_void_v) { - if constexpr (!std::is_void_v && lexy::is_callback_state<_type, ParseState>) - return _get_value(_state)[*_state](LEXY_FWD(args)...); - else - return _get_value(_state)(LEXY_FWD(args)...); + return _get_value(_state)[*_state](LEXY_FWD(args)...); + } + else if constexpr (lexy::is_callback_for<_type, Args&&...>) + { + return _get_value(_state)(LEXY_FWD(args)...); } else if constexpr ((lexy::is_sink<_type> // || lexy::is_sink<_type, std::add_lvalue_reference_t>) // @@ -355,4 +379,3 @@ class production_value_callback } // namespace lexy #endif // LEXY_GRAMMAR_HPP_INCLUDED - diff --git a/3rdparty/lexy/include/lexy/input/argv_input.hpp b/3rdparty/lexy/include/lexy/input/argv_input.hpp index f60ee4e8f..f4b4f1d70 100644 --- a/3rdparty/lexy/include/lexy/input/argv_input.hpp +++ b/3rdparty/lexy/include/lexy/input/argv_input.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_ARGV_INPUT_HPP_INCLUDED @@ -121,9 +121,9 @@ class argv_input public: using encoding = Encoding; using char_type = typename encoding::char_type; - static_assert( - std::is_same_v || Encoding::template is_secondary_char_type(), - "invalid encoding for argv"); + static_assert(std::is_same_v + || Encoding::template is_secondary_char_type(), + "invalid encoding for argv"); //=== constructors ===// constexpr argv_input() = default; @@ -147,7 +147,7 @@ class argv_input argv_iterator _begin, _end; }; -argv_input(int argc, char* argv[])->argv_input<>; +argv_input(int argc, char* argv[]) -> argv_input<>; } // namespace lexy namespace lexy @@ -169,9 +169,9 @@ struct _argvsep : token_base<_argvsep> template struct tp { - typename Reader::iterator end; + typename Reader::marker end; - constexpr explicit tp(const Reader& reader) : end(reader.position()) {} + constexpr explicit tp(const Reader& reader) : end(reader.current()) {} constexpr auto try_parse([[maybe_unused]] Reader reader) { @@ -182,7 +182,7 @@ struct _argvsep : token_base<_argvsep> return false; reader.bump(); - end = reader.position(); + end = reader.current(); return true; } else diff --git a/3rdparty/lexy/include/lexy/input/base.hpp b/3rdparty/lexy/include/lexy/input/base.hpp index ebd35f319..2bc260e2f 100644 --- a/3rdparty/lexy/include/lexy/input/base.hpp +++ b/3rdparty/lexy/include/lexy/input/base.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_BASE_HPP_INCLUDED @@ -18,6 +18,16 @@ class _rr using encoding = Encoding; using iterator = Iterator; + struct marker + { + iterator _it; + + constexpr iterator position() const noexcept + { + return _it; + } + }; + constexpr explicit _rr(Iterator begin, Sentinel end) noexcept : _cur(begin), _end(end) { LEXY_PRECONDITION(lexy::_detail::precedes(begin, end)); @@ -42,10 +52,14 @@ class _rr return _cur; } - constexpr void set_position(iterator new_pos) noexcept + constexpr marker current() const noexcept + { + return {_cur}; + } + constexpr void reset(marker m) noexcept { - LEXY_PRECONDITION(lexy::_detail::precedes(new_pos, _end)); - _cur = new_pos; + LEXY_PRECONDITION(lexy::_detail::precedes(m._it, _end)); + _cur = m._it; } private: diff --git a/3rdparty/lexy/include/lexy/input/buffer.hpp b/3rdparty/lexy/include/lexy/input/buffer.hpp index b6bfe758b..450ecf254 100644 --- a/3rdparty/lexy/include/lexy/input/buffer.hpp +++ b/3rdparty/lexy/include/lexy/input/buffer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_BUFFER_HPP_INCLUDED @@ -21,6 +21,16 @@ class _br : public _detail::swar_reader_base<_br> using encoding = Encoding; using iterator = const typename Encoding::char_type*; + struct marker + { + iterator _it; + + constexpr iterator position() const noexcept + { + return _it; + } + }; + explicit _br(iterator begin) noexcept : _cur(begin) {} auto peek() const noexcept @@ -39,9 +49,13 @@ class _br : public _detail::swar_reader_base<_br> return _cur; } - void set_position(iterator new_pos) noexcept + marker current() const noexcept + { + return {_cur}; + } + void reset(marker m) noexcept { - _cur = new_pos; + _cur = m._it; } private: @@ -80,13 +94,14 @@ namespace lexy template class buffer { + static_assert(lexy::is_char_encoding); static constexpr auto _has_sentinel = std::is_same_v; public: using encoding = Encoding; using char_type = typename encoding::char_type; - static_assert(std::is_trivial_v); + static_assert(std::is_trivially_copyable_v); //=== constructors ===// /// Allows the creation of an uninitialized buffer that is then filled by the user. @@ -119,6 +134,17 @@ class buffer buffer _buffer; }; + static buffer adopt(const char_type* data, std::size_t size, + MemoryResource* resource = _detail::get_memory_resource()) + { + buffer result(resource); + // We can cast away the const-ness, since we require that `data` came from a buffer + // origionally, where it wasn't const. + result._data = const_cast(data); + result._size = size; + return result; + } + constexpr buffer() noexcept : buffer(_detail::get_memory_resource()) {} constexpr explicit buffer(MemoryResource* resource) noexcept @@ -227,6 +253,14 @@ class buffer return _size; } + const char_type* release() && noexcept + { + auto result = _data; + _data = nullptr; + _size = 0; + return result; + } + //=== input ===// auto reader() const& noexcept { diff --git a/3rdparty/lexy/include/lexy/input/file.hpp b/3rdparty/lexy/include/lexy/input/file.hpp index 9c47d2d6c..8c4a2d57d 100644 --- a/3rdparty/lexy/include/lexy/input/file.hpp +++ b/3rdparty/lexy/include/lexy/input/file.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_FILE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/input/parse_tree_input.hpp b/3rdparty/lexy/include/lexy/input/parse_tree_input.hpp new file mode 100644 index 000000000..fdc7572f9 --- /dev/null +++ b/3rdparty/lexy/include/lexy/input/parse_tree_input.hpp @@ -0,0 +1,184 @@ +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors +// SPDX-License-Identifier: BSL-1.0 + +#ifndef LEXY_INPUT_PARSE_TREE_INPUT_HPP_INCLUDED +#define LEXY_INPUT_PARSE_TREE_INPUT_HPP_INCLUDED + +#include +#include +#include +#include + +#if !LEXY_EXPERIMENTAL +# error "lexy::parse_tree_input is experimental" +#endif + +namespace lexy +{ +template +struct parse_tree_input_traits; + +struct _parse_tree_eof // not real EOF, just no more siblings +{ + template + friend constexpr bool operator==(const Node& node, _parse_tree_eof) noexcept + { + return parse_tree_input_traits::is_null(node); + } + template + friend constexpr bool operator==(_parse_tree_eof, const Node& node) noexcept + { + return parse_tree_input_traits::is_null(node); + } + + template + friend constexpr bool operator!=(const Node& node, _parse_tree_eof) noexcept + { + return !parse_tree_input_traits::is_null(node); + } + template + friend constexpr bool operator!=(_parse_tree_eof, const Node& node) noexcept + { + return !parse_tree_input_traits::is_null(node); + } +}; + +template +class parse_tree_encoding +{ + using _traits = parse_tree_input_traits; + +public: + using char_encoding = typename _traits::char_encoding; + using char_type = typename char_encoding::char_type; + using value_type = Node; + + static LEXY_CONSTEVAL auto eof() + { + return _parse_tree_eof{}; + } + + template + static bool match(const Node& node, const NodeKind& node_kind) + { + return _traits::has_kind(node, node_kind); + } +}; +template +constexpr auto is_node_encoding> = true; + +template +class _ptr // parse tree reader +{ + using _traits = parse_tree_input_traits; + +public: + using encoding = parse_tree_encoding; + using iterator = typename _traits::iterator; + + struct marker + { + Node _parent = _traits::null(); + Node _cur = _traits::null(); + + constexpr iterator position() const noexcept + { + return _cur == _parse_tree_eof{} ? _traits::position_end(_parent) + : _traits::position_begin(_cur); + } + }; + + constexpr explicit _ptr(const Node& root) noexcept + : _parent(root), _cur(_traits::first_child(root)) + {} + + constexpr _ptr child_reader() const& noexcept + { + return _ptr(_cur); + } + constexpr auto lexeme_reader() const& noexcept + { + auto lexeme = _traits::lexeme(_cur); + return _range_reader(lexeme.begin(), lexeme.end()); + } + + constexpr const Node& peek() const noexcept + { + return _cur; + } + + constexpr void bump() noexcept + { + LEXY_PRECONDITION(_cur != _parse_tree_eof{}); + _cur = _traits::sibling(_cur); + } + + constexpr marker current() const noexcept + { + return {_parent, _cur}; + } + constexpr void reset(marker m) noexcept + { + _cur = m._cur; + } + + constexpr iterator position() const noexcept + { + return current().position(); + } + +private: + Node _parent; + Node _cur; +}; + +template +class parse_tree_input +{ +public: + using encoding = parse_tree_encoding; + using value_type = Node; + + //=== constructors ===// + constexpr parse_tree_input() noexcept : _root(nullptr) {} + + constexpr explicit parse_tree_input(Node root) noexcept : _root(LEXY_MOV(root)) {} + + template >> + constexpr explicit parse_tree_input(const ParseTree& tree) noexcept : _root(tree.root()) + {} + + //=== access ===// + constexpr const Node& root() const noexcept + { + return _root; + } + + //=== reader ===// + constexpr auto reader() const& noexcept + { + return _ptr(_root); + } + +private: + Node _root; +}; + +template +parse_tree_input(const ParseTree&) + -> parse_tree_input; + +//=== convenience typedefs ===// +template +using parse_tree_lexeme = lexeme_for>; + +template +using parse_tree_error = error_for, Tag>; + +template +using parse_tree_error_context = error_context>; +} // namespace lexy + +#endif // LEXY_INPUT_PARSE_TREE_INPUT_HPP_INCLUDED + diff --git a/3rdparty/lexy/include/lexy/input/range_input.hpp b/3rdparty/lexy/include/lexy/input/range_input.hpp index 3ad00f189..c32c0d3a7 100644 --- a/3rdparty/lexy/include/lexy/input/range_input.hpp +++ b/3rdparty/lexy/include/lexy/input/range_input.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_RANGE_INPUT_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/input/string_input.hpp b/3rdparty/lexy/include/lexy/input/string_input.hpp index 72568a715..a59a387da 100644 --- a/3rdparty/lexy/include/lexy/input/string_input.hpp +++ b/3rdparty/lexy/include/lexy/input/string_input.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_STRING_INPUT_HPP_INCLUDED @@ -17,6 +17,8 @@ using _string_view_char_type = LEXY_DECAY_DECLTYPE(*LEXY_DECLVAL(View).data()); template class string_input { + static_assert(lexy::is_char_encoding); + public: using encoding = Encoding; using char_type = typename encoding::char_type; diff --git a/3rdparty/lexy/include/lexy/input_location.hpp b/3rdparty/lexy/include/lexy/input_location.hpp index e6c14cf2d..983d2aa02 100644 --- a/3rdparty/lexy/include/lexy/input_location.hpp +++ b/3rdparty/lexy/include/lexy/input_location.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_INPUT_LOCATION_HPP_INCLUDED @@ -16,18 +16,18 @@ namespace lexy template struct input_location_anchor { - using iterator = typename lexy::input_reader::iterator; + using marker = typename lexy::input_reader::marker; constexpr explicit input_location_anchor(const Input& input) - : _line_begin(input.reader().position()), _line_nr(1) + : _line_begin(input.reader().current()), _line_nr(1) {} // implementation detail - constexpr explicit input_location_anchor(iterator line_begin, unsigned line_nr) + constexpr explicit input_location_anchor(marker line_begin, unsigned line_nr) : _line_begin(line_begin), _line_nr(line_nr) {} - iterator _line_begin; + marker _line_begin; unsigned _line_nr; }; } // namespace lexy @@ -42,12 +42,14 @@ class code_unit_location_counting template constexpr bool try_match_newline(Reader& reader) { + static_assert(lexy::is_char_encoding); return lexy::try_match_token(lexy::dsl::newline, reader); } template constexpr void match_column(Reader& reader) { + static_assert(lexy::is_char_encoding); reader.bump(); } }; @@ -59,12 +61,14 @@ class code_point_location_counting template constexpr bool try_match_newline(Reader& reader) { + static_assert(lexy::is_char_encoding); return lexy::try_match_token(lexy::dsl::newline, reader); } template constexpr void match_column(Reader& reader) { + static_assert(lexy::is_char_encoding); if (!lexy::try_match_token(lexy::dsl::code_point, reader)) reader.bump(); } @@ -78,6 +82,7 @@ class byte_location_counting template constexpr bool try_match_newline(Reader& reader) { + static_assert(lexy::is_byte_encoding); LEXY_PRECONDITION(_cur_index <= LineWidth - 1); if (_cur_index == LineWidth - 1) { @@ -98,7 +103,7 @@ class byte_location_counting template constexpr void match_column(Reader& reader) { - static_assert(std::is_same_v); + static_assert(lexy::is_byte_encoding); reader.bump(); ++_cur_index; @@ -109,9 +114,20 @@ class byte_location_counting }; template -using _default_location_counting = std::conditional_t< - std::is_same_v::encoding, lexy::byte_encoding>, - byte_location_counting<>, code_unit_location_counting>; +auto _compute_default_location_counting() +{ + using encoding = typename lexy::input_reader::encoding; + if constexpr (lexy::is_byte_encoding) + return byte_location_counting{}; + else if constexpr (lexy::is_char_encoding) + return code_unit_location_counting{}; + else + static_assert(_detail::error, + "input encoding does not have a default location counting policy"); +} + +template +using _default_location_counting = decltype(_compute_default_location_counting()); } // namespace lexy //=== input_location ===// @@ -122,10 +138,12 @@ template > class input_location { using iterator = typename lexy::input_reader::iterator; + using marker = typename lexy::input_reader::marker; public: constexpr explicit input_location(const Input& input) - : _line_begin(input.reader().position()), _column_begin(_line_begin), _line_nr(1), _column_nr(1) + : _line_begin(input.reader().current()), _column_begin(_line_begin.position()), _line_nr(1), + _column_nr(1) {} /// The closest previous anchor. @@ -162,7 +180,7 @@ class input_location { if (lhs._line_nr != rhs._line_nr) return lhs._line_nr < rhs._line_nr; - return lhs._column_nr < rhs._colum_nr; + return lhs._column_nr < rhs._column_nr; } friend constexpr bool operator<=(const input_location& lhs, const input_location& rhs) { @@ -178,12 +196,13 @@ class input_location } private: - constexpr input_location(iterator line_begin, unsigned line_nr, iterator column_begin, + constexpr input_location(marker line_begin, unsigned line_nr, iterator column_begin, unsigned column_nr) : _line_begin(line_begin), _column_begin(column_begin), _line_nr(line_nr), _column_nr(column_nr) {} - iterator _line_begin, _column_begin; + marker _line_begin; + iterator _column_begin; unsigned _line_nr, _column_nr; template @@ -201,7 +220,7 @@ constexpr auto get_input_location(const Input& i -> input_location { auto reader = input.reader(); - reader.set_position(anchor._line_begin); + reader.reset(anchor._line_begin); auto line_begin = anchor._line_begin; auto line_nr = anchor._line_nr; @@ -227,8 +246,10 @@ constexpr auto get_input_location(const Input& i else if (counting.try_match_newline(reader)) { // [column_begin, newline_end) covers the newline. - auto newline_end = reader.position(); - if (lexy::_detail::min_range_end(column_begin, newline_end, position) != newline_end) + auto newline_end = reader.current(); + if (lexy::_detail::min_range_end(column_begin.position(), newline_end.position(), + position) + != newline_end.position()) break; // Advance to the next line. @@ -242,8 +263,10 @@ constexpr auto get_input_location(const Input& i counting.match_column(reader); // [column_begin, column_end) covers the column. - auto column_end = reader.position(); - if (lexy::_detail::min_range_end(column_begin, column_end, position) != column_end) + auto column_end = reader.current(); + if (lexy::_detail::min_range_end(column_begin.position(), column_end.position(), + position) + != column_end.position()) break; // Advance to the next column. @@ -252,7 +275,7 @@ constexpr auto get_input_location(const Input& i } } - return {line_begin, line_nr, column_begin, column_nr}; + return {line_begin, line_nr, column_begin.position(), column_nr}; } template @@ -281,11 +304,11 @@ constexpr auto get_input_location(const Input& i namespace lexy::_detail { template -constexpr auto get_input_line(const Input& input, - typename lexy::input_reader::iterator line_begin) +constexpr auto get_input_line(const Input& input, + typename lexy::input_reader::marker line_begin) { auto reader = input.reader(); - reader.set_position(line_begin); + reader.reset(line_begin); auto line_end = reader.position(); for (Counting counting; @@ -301,7 +324,7 @@ constexpr auto get_input_line(const Input& input lexy::lexeme_for line; lexy::lexeme_for newline; }; - return result_t{{line_begin, line_end}, {line_end, newline_end}}; + return result_t{{line_begin.position(), line_end}, {line_end, newline_end}}; } // Advances the iterator to the beginning of the next code point. diff --git a/3rdparty/lexy/include/lexy/lexeme.hpp b/3rdparty/lexy/include/lexy/lexeme.hpp index 09d274a27..69d609854 100644 --- a/3rdparty/lexy/include/lexy/lexeme.hpp +++ b/3rdparty/lexy/include/lexy/lexeme.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_LEXEME_HPP_INCLUDED @@ -17,8 +17,8 @@ class lexeme { public: using encoding = typename Reader::encoding; - using char_type = typename encoding::char_type; using iterator = typename Reader::iterator; + using char_type = LEXY_DECAY_DECLTYPE(*LEXY_DECLVAL(iterator&)); constexpr lexeme() noexcept : _begin(), _end() {} constexpr lexeme(iterator begin, iterator end) noexcept : _begin(begin), _end(end) {} @@ -30,6 +30,13 @@ class lexeme : _begin(begin), _end(reader.position()) {} + template >> + constexpr operator lexeme() const noexcept + { + return lexeme(this->begin(), this->end()); + } + constexpr bool empty() const noexcept { return _begin == _end; diff --git a/3rdparty/lexy/include/lexy/parse_tree.hpp b/3rdparty/lexy/include/lexy/parse_tree.hpp index 403c6b4d0..b82efb1bd 100644 --- a/3rdparty/lexy/include/lexy/parse_tree.hpp +++ b/3rdparty/lexy/include/lexy/parse_tree.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_PARSE_TREE_HPP_INCLUDED @@ -11,6 +11,12 @@ #include #include +namespace lexy +{ +template +struct parse_tree_input_traits; +} + //=== internal: pt_node ===// namespace lexy::_detail { @@ -125,7 +131,8 @@ struct pt_node_token : pt_node { if constexpr (_optimize_end) { - static_assert(sizeof(pt_node_token) == 3 * sizeof(void*)); + static_assert(!std::is_pointer_v + || sizeof(pt_node_token) == 3 * sizeof(void*)); auto size = std::size_t(end - begin); LEXY_PRECONDITION(size <= UINT_LEAST32_MAX); @@ -133,7 +140,8 @@ struct pt_node_token : pt_node } else { - static_assert(sizeof(pt_node_token) <= 4 * sizeof(void*)); + static_assert(!std::is_pointer_v + || sizeof(pt_node_token) <= 4 * sizeof(void*)); end_impl = end; } @@ -327,9 +335,16 @@ class pt_buffer //=== parse_tree ===// namespace lexy { +template +class _pt_node_kind; +template +class _pt_node; + template class parse_tree { + static_assert(lexy::is_char_encoding); + public: //=== construction ===// class builder; @@ -363,8 +378,8 @@ class parse_tree } //=== node access ===// - class node; - class node_kind; + using node_kind = _pt_node_kind; + using node = _pt_node; node root() const noexcept { @@ -390,7 +405,11 @@ class parse_tree //=== remaining input ===// lexy::lexeme remaining_input() const noexcept { - return _remaining_input; + if (empty()) + return {}; + + auto token = _root->next_node()->as_token(); + return {token->begin, token->end()}; } private: @@ -398,7 +417,6 @@ class parse_tree _detail::pt_node_production* _root; std::size_t _size; std::size_t _depth; - lexy::lexeme _remaining_input; }; template @@ -542,12 +560,29 @@ class parse_tree::builder } explicit builder(production_info production) : builder(parse_tree(), production) {} - parse_tree&& finish(lexy::lexeme remaining_input = {}) && + [[deprecated("Pass the remaining input, or `input.end()` if there is none.")]] parse_tree&& + finish() && + { + return LEXY_MOV(*this).finish(lexy::lexeme()); + } + parse_tree&& finish(typename Reader::iterator end) && + { + return LEXY_MOV(*this).finish({end, end}); + } + parse_tree&& finish(lexy::lexeme remaining_input) && { LEXY_PRECONDITION(_cur.prod == _result._root); + _cur.insert_children_into(_cur.prod); _cur.update_size_depth(_result._size, _result._depth); - _result._remaining_input = remaining_input; + + _result._buffer.reserve(sizeof(_detail::pt_node_token)); + auto node = _result._buffer + .template allocate<_detail::pt_node_token>(lexy::eof_token_kind, + remaining_input.begin(), + remaining_input.end()); + _result._root->set_sibling(node); + return LEXY_MOV(_result); } @@ -712,13 +747,19 @@ class parse_tree::builder } } + //=== accessors ===// + std::size_t current_child_count() const noexcept + { + return _cur.child_count; + } + private: parse_tree _result; marker _cur; }; -template -class parse_tree::node_kind +template +class _pt_node_kind { public: bool is_token() const noexcept @@ -732,8 +773,10 @@ class parse_tree::node_kind bool is_root() const noexcept { - // Root node has no next node. - return _ptr->next_node() == nullptr; + // Root node has a next node (the remaining input node) which has no next node. + // We assume that _ptr is never the remaining input node, so we know that we have a next + // node. + return _ptr->next_node()->next_node() == nullptr; } bool is_token_production() const noexcept { @@ -753,65 +796,65 @@ class parse_tree::node_kind } } - friend bool operator==(node_kind lhs, node_kind rhs) + friend bool operator==(_pt_node_kind lhs, _pt_node_kind rhs) { if (lhs.is_token() && rhs.is_token()) return lhs._ptr->as_token()->kind == rhs._ptr->as_token()->kind; else return lhs._ptr->as_production()->id == rhs._ptr->as_production()->id; } - friend bool operator!=(node_kind lhs, node_kind rhs) + friend bool operator!=(_pt_node_kind lhs, _pt_node_kind rhs) { return !(lhs == rhs); } - friend bool operator==(node_kind nk, token_kind tk) + friend bool operator==(_pt_node_kind nk, token_kind tk) { if (auto token = nk._ptr->as_token()) return token_kind::from_raw(token->kind) == tk; else return false; } - friend bool operator==(token_kind tk, node_kind nk) + friend bool operator==(token_kind tk, _pt_node_kind nk) { return nk == tk; } - friend bool operator!=(node_kind nk, token_kind tk) + friend bool operator!=(_pt_node_kind nk, token_kind tk) { return !(nk == tk); } - friend bool operator!=(token_kind tk, node_kind nk) + friend bool operator!=(token_kind tk, _pt_node_kind nk) { return !(nk == tk); } - friend bool operator==(node_kind nk, production_info info) + friend bool operator==(_pt_node_kind nk, production_info info) { return nk.is_production() && nk._ptr->as_production()->id == info.id; } - friend bool operator==(production_info info, node_kind nk) + friend bool operator==(production_info info, _pt_node_kind nk) { return nk == info; } - friend bool operator!=(node_kind nk, production_info info) + friend bool operator!=(_pt_node_kind nk, production_info info) { return !(nk == info); } - friend bool operator!=(production_info info, node_kind nk) + friend bool operator!=(production_info info, _pt_node_kind nk) { return !(nk == info); } private: - explicit node_kind(_detail::pt_node* ptr) : _ptr(ptr) {} + explicit _pt_node_kind(_detail::pt_node* ptr) : _ptr(ptr) {} _detail::pt_node* _ptr; - friend parse_tree::node; + friend _pt_node; }; -template -class parse_tree::node +template +class _pt_node { public: void* address() const noexcept @@ -821,7 +864,7 @@ class parse_tree::node auto kind() const noexcept { - return node_kind(_ptr); + return _pt_node_kind(_ptr); } auto parent() const noexcept @@ -834,20 +877,20 @@ class parse_tree::node auto cur = _ptr; while (cur->next_role() == _detail::pt_node::role_sibling) cur = cur->next_node(); - return node(cur->next_node()); + return _pt_node(cur->next_node()); } class children_range { public: - class iterator : public _detail::forward_iterator_base + class iterator : public _detail::forward_iterator_base { public: iterator() noexcept : _cur(nullptr) {} - node deref() const noexcept + auto deref() const noexcept { - return node(_cur); + return _pt_node(_cur); } void increment() noexcept @@ -903,7 +946,7 @@ class parse_tree::node _detail::pt_node* _node; - friend node; + friend _pt_node; }; auto children() const noexcept @@ -914,14 +957,14 @@ class parse_tree::node class sibling_range { public: - class iterator : public _detail::forward_iterator_base + class iterator : public _detail::forward_iterator_base { public: iterator() noexcept : _cur() {} - node deref() const noexcept + auto deref() const noexcept { - return node(_cur); + return _pt_node(_cur); } void increment() noexcept @@ -969,7 +1012,7 @@ class parse_tree::node _detail::pt_node* _node; - friend node; + friend _pt_node; }; auto siblings() const noexcept @@ -983,6 +1026,19 @@ class parse_tree::node return _ptr->next_role() == _detail::pt_node::role_parent; } + auto position() const noexcept -> typename Reader::iterator + { + // Find the first descendant that is a token. + auto cur = _ptr; + while (cur->type() == _detail::pt_node::type_production) + { + cur = cur->as_production()->first_child(); + LEXY_PRECONDITION(cur); + } + + return cur->as_token()->begin; + } + auto lexeme() const noexcept { if (auto token = _ptr->as_token()) @@ -991,6 +1047,28 @@ class parse_tree::node return lexy::lexeme(); } + auto covering_lexeme() const noexcept + { + if (auto token = _ptr->as_token()) + return lexy::lexeme(token->begin, token->end()); + + auto begin = position(); + + auto sibling = _ptr; + while (true) + { + auto next_role = sibling->next_role(); + sibling = sibling->next_node(); + // If we went to parent, we need to continue finding siblings. + if (next_role == _detail::pt_node::role_sibling) + break; + } + auto end = _pt_node(sibling).position(); + + LEXY_PRECONDITION(begin == end || end != typename Reader::iterator()); + return lexy::lexeme(begin, end); + } + auto token() const noexcept { LEXY_PRECONDITION(kind().is_token()); @@ -1000,21 +1078,22 @@ class parse_tree::node return lexy::token(kind, token->begin, token->end()); } - friend bool operator==(node lhs, node rhs) noexcept + friend bool operator==(_pt_node lhs, _pt_node rhs) noexcept { return lhs._ptr == rhs._ptr; } - friend bool operator!=(node lhs, node rhs) noexcept + friend bool operator!=(_pt_node lhs, _pt_node rhs) noexcept { return lhs._ptr != rhs._ptr; } private: - explicit node(_detail::pt_node* ptr) noexcept : _ptr(ptr) {} + explicit _pt_node(_detail::pt_node* ptr) noexcept : _ptr(ptr) {} _detail::pt_node* _ptr; - friend parse_tree; + friend parse_tree; + friend parse_tree_input_traits<_pt_node>; }; enum class traverse_event @@ -1143,5 +1222,70 @@ class parse_tree::traverse_range }; } // namespace lexy +#if LEXY_EXPERIMENTAL +namespace lexy +{ +template +struct parse_tree_input_traits<_pt_node> +{ + using _node = _pt_node; + + using char_encoding = typename Reader::encoding; + + static bool is_null(_node cur) noexcept + { + return cur._ptr == nullptr; + } + + static _node null() noexcept + { + return _node(nullptr); + } + + static _node first_child(_node cur) noexcept + { + LEXY_PRECONDITION(!is_null(cur)); + if (auto prod = cur._ptr->as_production()) + return _node(prod->first_child()); + else + return _node(nullptr); + } + + static _node sibling(_node cur) noexcept + { + LEXY_PRECONDITION(!is_null(cur)); + return cur._ptr->next_role() == _detail::pt_node::role_sibling + ? _node(cur._ptr->next_node()) + : _node(nullptr); + } + + template + static bool has_kind(_node cur, const Kind& kind) noexcept + { + return !is_null(cur) && cur.kind() == kind; + } + + using iterator = typename Reader::iterator; + + static iterator position_begin(_node cur) noexcept + { + LEXY_PRECONDITION(!is_null(cur)); + return cur.position(); + } + static iterator position_end(_node cur) noexcept + { + LEXY_PRECONDITION(!is_null(cur)); + return cur.covering_lexeme().end(); + } + + static auto lexeme(_node cur) noexcept + { + LEXY_PRECONDITION(!is_null(cur)); + return cur.lexeme(); + } +}; +} // namespace lexy +#endif + #endif // LEXY_PARSE_TREE_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy/token.hpp b/3rdparty/lexy/include/lexy/token.hpp index 3ea1532b8..a7b1442e5 100644 --- a/3rdparty/lexy/include/lexy/token.hpp +++ b/3rdparty/lexy/include/lexy/token.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_TOKEN_HPP_INCLUDED @@ -88,9 +88,6 @@ inline constexpr auto token_kind_map_for = token_kind_map; namespace lexy { -template -using _detect_token_kind_name = decltype(token_kind_name(TokenKind{})); - template constexpr auto _has_special_token_kind = [] { using kind = LEXY_DECAY_DECLTYPE(lexy::token_kind_of); @@ -174,12 +171,13 @@ class token_kind constexpr const char* name() const noexcept { if (is_predefined()) - return _kind_name(static_cast(_value)); - else if constexpr (lexy::_detail::is_detected<_detect_token_kind_name, TokenKind>) - return token_kind_name(get()); // ADL + return token_kind_name(static_cast(_value)); else - // We only have a generic name. - return "token"; + return token_kind_name(get()); // ADL + } + friend constexpr const char* token_kind_name(token_kind kind) noexcept + { + return kind.name(); } constexpr _underlying_type get() const noexcept diff --git a/3rdparty/lexy/include/lexy/visualize.hpp b/3rdparty/lexy/include/lexy/visualize.hpp index 8b0b6f467..42b3fb0be 100644 --- a/3rdparty/lexy/include/lexy/visualize.hpp +++ b/3rdparty/lexy/include/lexy/visualize.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_VISUALIZE_HPP_INCLUDED @@ -363,32 +363,7 @@ OutputIt visualize_to(OutputIt out, lexy::lexeme lexeme, }; using encoding = typename Reader::encoding; - if constexpr (std::is_same_v // - || std::is_same_v) - { - auto count = 0u; - for (char c : lexeme) - { - // If the character is in fact ASCII, visualize the code point. - // Otherwise, visualize as byte. - if (lexy::_detail::is_ascii(c)) - out = visualize_to(out, lexy::code_point(static_cast(c)), opts); - else - out = write_escaped_byte(out, static_cast(c)); - - ++count; - if (count == opts.max_lexeme_width) - { - out = _detail::write_ellipsis(out, opts); - break; - } - } - return out; - } - else if constexpr (std::is_same_v // - || std::is_same_v // - || std::is_same_v // - || std::is_same_v) + if constexpr (lexy::is_unicode_encoding) { // Parse the individual code points, and write them out. lexy::range_input input(lexeme.begin(), lexeme.end()); @@ -406,7 +381,7 @@ OutputIt visualize_to(OutputIt out, lexy::lexeme lexeme, else if (result.error == lexy::_detail::cp_error::success) { // Consume and visualize. - reader.set_position(result.end); + reader.reset(result.end); out = visualize_to(out, lexy::code_point(result.cp), opts); } else @@ -461,7 +436,28 @@ OutputIt visualize_to(OutputIt out, lexy::lexeme lexeme, } return out; } - else if constexpr (std::is_same_v) + else if constexpr (lexy::is_text_encoding) + { + auto count = 0u; + for (char c : lexeme) + { + // If the character is in fact ASCII, visualize the code point. + // Otherwise, visualize as byte. + if (lexy::_detail::is_ascii(c)) + out = visualize_to(out, lexy::code_point(static_cast(c)), opts); + else + out = write_escaped_byte(out, static_cast(c)); + + ++count; + if (count == opts.max_lexeme_width) + { + out = _detail::write_ellipsis(out, opts); + break; + } + } + return out; + } + else if constexpr (lexy::is_byte_encoding) { auto count = 0u; for (auto iter = lexeme.begin(); iter != lexeme.end(); ++iter) @@ -480,6 +476,13 @@ OutputIt visualize_to(OutputIt out, lexy::lexeme lexeme, } return out; } + else if constexpr (lexy::is_node_encoding) + { + // Visualize as an iterator range of characters. + lexy::range_input + input(lexeme.begin(), lexeme.end()); + return visualize_to(out, lexy::lexeme_for(input.begin(), input.end())); + } else { static_assert(lexy::_detail::error, "unknown encoding"); @@ -622,6 +625,41 @@ struct cfile_output_iterator } }; +struct stderr_output_iterator +{ + auto operator*() const noexcept + { + return *this; + } + auto operator++(int) const noexcept + { + return *this; + } + + stderr_output_iterator& operator=(char c) + { + std::fputc(c, stderr); + return *this; + } +}; +struct stdout_output_iterator +{ + auto operator*() const noexcept + { + return *this; + } + auto operator++(int) const noexcept + { + return *this; + } + + stdout_output_iterator& operator=(char c) + { + std::fputc(c, stdout); + return *this; + } +}; + /// Writes the visualization to the FILE. template void visualize(std::FILE* file, const T& obj, visualization_options opts = {}) diff --git a/3rdparty/lexy/include/lexy_ext/compiler_explorer.hpp b/3rdparty/lexy/include/lexy_ext/compiler_explorer.hpp index 588a456ea..220adf4ab 100644 --- a/3rdparty/lexy/include/lexy_ext/compiler_explorer.hpp +++ b/3rdparty/lexy/include/lexy_ext/compiler_explorer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_EXT_COMPILER_EXPLORER_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy_ext/parse_tree_algorithm.hpp b/3rdparty/lexy/include/lexy_ext/parse_tree_algorithm.hpp index 9009ee08e..f8242fab6 100644 --- a/3rdparty/lexy/include/lexy_ext/parse_tree_algorithm.hpp +++ b/3rdparty/lexy/include/lexy_ext/parse_tree_algorithm.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_EXT_PARSE_TREE_ALGORITHM_HPP_INCLUDED @@ -216,7 +216,7 @@ class _filtered_node_range template _filtered_node_range(Predicate&& pred, Iterator begin, Sentinel end) noexcept - ->_filtered_node_range, Iterator, Sentinel>; + -> _filtered_node_range, Iterator, Sentinel>; /// Returns the children that of node that match the predicate. /// diff --git a/3rdparty/lexy/include/lexy_ext/parse_tree_doctest.hpp b/3rdparty/lexy/include/lexy_ext/parse_tree_doctest.hpp index 51c1d1f29..18b12dead 100644 --- a/3rdparty/lexy/include/lexy_ext/parse_tree_doctest.hpp +++ b/3rdparty/lexy/include/lexy_ext/parse_tree_doctest.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_EXT_PARSE_TREE_DOCTEST_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy_ext/report_error.hpp b/3rdparty/lexy/include/lexy_ext/report_error.hpp index fc04e10cf..0ee6c32a2 100644 --- a/3rdparty/lexy/include/lexy_ext/report_error.hpp +++ b/3rdparty/lexy/include/lexy_ext/report_error.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_EXT_REPORT_ERROR_HPP_INCLUDED @@ -317,7 +317,7 @@ OutputIt write_error(OutputIt out, const lexy::error_context& context, namespace lexy_ext { -template +template struct _report_error { OutputIterator _iter; @@ -337,18 +337,14 @@ struct _report_error void operator()(const lexy::error_context& context, const lexy::error& error) { - if constexpr (std::is_same_v) - _detail::write_error(lexy::cfile_output_iterator{stderr}, context, error, _opts, - _path); - else - _iter = _detail::write_error(_iter, context, error, _opts, _path); + _iter = _detail::write_error(_iter, context, error, _opts, _path); ++_count; } std::size_t finish() && { if (_count != 0) - std::fputs("\n", stderr); + *_iter++ = '\n'; return _count; } }; @@ -378,7 +374,7 @@ struct _report_error }; /// An error callback that uses diagnostic_writer to print to stderr (by default). -constexpr auto report_error = _report_error<>{}; +constexpr auto report_error = _report_error{}; } // namespace lexy_ext #endif // LEXY_EXT_REPORT_ERROR_HPP_INCLUDED diff --git a/3rdparty/lexy/include/lexy_ext/shell.hpp b/3rdparty/lexy/include/lexy_ext/shell.hpp index 6fe81ee01..66865bbda 100644 --- a/3rdparty/lexy/include/lexy_ext/shell.hpp +++ b/3rdparty/lexy/include/lexy_ext/shell.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 #ifndef LEXY_EXT_SHELL_HPP_INCLUDED @@ -168,6 +168,16 @@ class shell using encoding = typename Prompt::encoding; using iterator = typename lexy::_detail::buffer_builder::stable_iterator; + struct marker + { + iterator _it; + + constexpr iterator position() const noexcept + { + return _it; + } + }; + auto reader() const& { return *this; @@ -191,9 +201,13 @@ class shell return iterator(_shell->_buffer, _idx); } - void set_position(iterator new_pos) noexcept + marker current() const noexcept + { + return {position()}; + } + void reset(marker m) noexcept { - _idx = new_pos.index(); + _idx = m._it.index(); } private: diff --git a/3rdparty/lexy/src/CMakeLists.txt b/3rdparty/lexy/src/CMakeLists.txt index 6f07f43db..709cc831f 100644 --- a/3rdparty/lexy/src/CMakeLists.txt +++ b/3rdparty/lexy/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +# Copyright (C) 2020-2024 Jonathan Müller and lexy contributors # SPDX-License-Identifier: BSL-1.0 get_filename_component(include_dir ${CMAKE_CURRENT_SOURCE_DIR}/../include/lexy ABSOLUTE) @@ -80,6 +80,7 @@ set(header_files ${include_dir}/dsl/option.hpp ${include_dir}/dsl/operator.hpp ${include_dir}/dsl/parse_as.hpp + ${include_dir}/dsl/parse_tree_node.hpp ${include_dir}/dsl/peek.hpp ${include_dir}/dsl/position.hpp ${include_dir}/dsl/production.hpp @@ -105,6 +106,7 @@ set(header_files ${include_dir}/input/buffer.hpp ${include_dir}/input/file.hpp ${include_dir}/input/lexeme_input.hpp + ${include_dir}/input/parse_tree_input.hpp ${include_dir}/input/range_input.hpp ${include_dir}/input/string_input.hpp @@ -191,7 +193,7 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") # GCC's arry bounds, maybe uninitialized, and restrict warning seems to have false positives. target_compile_options(lexy_dev INTERFACE -Wno-array-bounds -Wno-maybe-uninitialized -Wno-restrict) elseif(MSVC) - target_compile_options(lexy_dev INTERFACE /WX /W3 /D _CRT_SECURE_NO_WARNINGS /wd5105) + target_compile_options(lexy_dev INTERFACE /WX /W3 /D _CRT_SECURE_NO_WARNINGS /wd5105 /utf-8) endif() # Link to have FILE I/O. @@ -214,3 +216,9 @@ target_sources(lexy_ext INTERFACE ${ext_headers_files}) add_library(lexy INTERFACE) add_alias(lexy lexy) target_link_libraries(lexy INTERFACE foonathan::lexy::core foonathan::lexy::file foonathan::lexy::unicode foonathan::lexy::ext) + +# Link to enable experimental features. +add_library(lexy_experimental INTERFACE) +add_alias(lexy::experimental lexy_experimental) +target_compile_definitions(lexy_experimental INTERFACE LEXY_EXPERIMENTAL=1) + diff --git a/3rdparty/lexy/src/input/file.cpp b/3rdparty/lexy/src/input/file.cpp index 655473ebc..028fb6de3 100644 --- a/3rdparty/lexy/src/input/file.cpp +++ b/3rdparty/lexy/src/input/file.cpp @@ -1,6 +1,7 @@ -// Copyright (C) 2020-2023 Jonathan Müller and lexy contributors +// Copyright (C) 2020-2024 Jonathan Müller and lexy contributors // SPDX-License-Identifier: BSL-1.0 +#include #include #include @@ -56,8 +57,8 @@ lexy::file_error get_file_error() noexcept } } -constexpr std::size_t small_file_size = 4 * 1024; -constexpr std::size_t medium_file_size = 32 * 1024; +constexpr std::size_t small_file_size = std::size_t(4) * 1024; +constexpr std::size_t medium_file_size = std::size_t(32) * 1024; } // namespace lexy::file_error lexy::_detail::read_file(const char* path, file_callback cb, void* user_data)