diff --git a/include/iris/x4/core/action.hpp b/include/iris/x4/core/action.hpp index fba6c57ab..da408cb64 100644 --- a/include/iris/x4/core/action.hpp +++ b/include/iris/x4/core/action.hpp @@ -17,11 +17,12 @@ #include #include -#include +#include // subrange #include #include #include #include +#include namespace iris::x4 { @@ -109,6 +110,11 @@ struct action : proxy_parser> constexpr void operator[](auto const&) const = delete; // You can't add semantic action for semantic action + [[nodiscard]] constexpr std::string get_x4_info() const + { + return std::format("{}[f]", get_info{}(this->subject)); + } + private: // Semantic action with no parameter: `p[([] { /* ... */ })]` template diff --git a/include/iris/x4/core/skip_over.hpp b/include/iris/x4/core/skip_over.hpp index 51a9f6eeb..83910a2d0 100644 --- a/include/iris/x4/core/skip_over.hpp +++ b/include/iris/x4/core/skip_over.hpp @@ -42,6 +42,25 @@ enum struct builtin_skipper_kind : char space, }; +namespace detail { + +template +struct builtin_skipper_traits; + +template<> +struct builtin_skipper_traits +{ + static constexpr char const* name = "blank"; +}; + +template<> +struct builtin_skipper_traits +{ + static constexpr char const* name = "space"; +}; + +} // detail + template Se, class Context> requires X4Subject> constexpr void skip_over(It& first, Se const& last, Context const& ctx) diff --git a/include/iris/x4/debug/print_attribute.hpp b/include/iris/x4/debug/print_attribute.hpp index 650641993..97859dfd7 100644 --- a/include/iris/x4/debug/print_attribute.hpp +++ b/include/iris/x4/debug/print_attribute.hpp @@ -18,6 +18,7 @@ #include #include +#include #ifdef IRIS_X4_UNICODE # include @@ -133,18 +134,23 @@ struct print_attribute_debug requires (!std::is_same_v) static void call(std::ostream& out, T_ const& val) { - out << '['; - bool is_first = true; - auto last = traits::end(val); - for (auto it = traits::begin(val); it != last; ++it) { - if (is_first) { - is_first = false; - } else { - out << ", "; + if constexpr (iris::StringLike) { + out << std::basic_string_view{val}; + + } else { + out << '['; + bool is_first = true; + auto last = traits::end(val); + for (auto it = traits::begin(val); it != last; ++it) { + if (is_first) { + is_first = false; + } else { + out << ", "; + } + traits::print_attribute(out, *it); } - traits::print_attribute(out, *it); + out << ']'; } - out << ']'; } // for variant types diff --git a/include/iris/x4/directive/lexeme.hpp b/include/iris/x4/directive/lexeme.hpp index f14118091..d12dfc20f 100644 --- a/include/iris/x4/directive/lexeme.hpp +++ b/include/iris/x4/directive/lexeme.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,11 @@ struct lexeme_directive : proxy_parser> attr ); } + + [[nodiscard]] constexpr std::string get_x4_info() const + { + return std::format("lexeme[{}]", get_info{}(this->subject)); + } }; namespace detail { diff --git a/include/iris/x4/directive/skip.hpp b/include/iris/x4/directive/skip.hpp index 2b788f5c6..83e10bf90 100644 --- a/include/iris/x4/directive/skip.hpp +++ b/include/iris/x4/directive/skip.hpp @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -49,6 +50,15 @@ struct skip_directive : proxy_parser> return this->subject.parse(first, last, x4::replace_first_context(ctx, skipper_), attr); } + [[nodiscard]] constexpr std::string get_x4_info() const + { + return std::format( + "skip({})[{}]", + get_info{}(this->skipper_), + get_info{}(this->subject) + ); + } + private: template using context_t = std::remove_cvref_tsubject.parse(first, last, x4::replace_first_context(ctx, skipper_kind), attr); } + + [[nodiscard]] constexpr std::string get_x4_info() const + { + return std::format( + "skip({})[{}]", + detail::builtin_skipper_traits::name, + get_info{}(this->subject) + ); + } }; diff --git a/include/iris/x4/operator/alternative.hpp b/include/iris/x4/operator/alternative.hpp index 2746a15e5..ca187c5c7 100644 --- a/include/iris/x4/operator/alternative.hpp +++ b/include/iris/x4/operator/alternative.hpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -211,6 +212,15 @@ struct alternative : binary_parser> } return false; // `attr` is untouched } + + [[nodiscard]] constexpr std::string get_x4_info() const + { + return std::format( + "{} | {}", + get_info{}(this->left), + get_info{}(this->right) + ); + } }; template diff --git a/include/iris/x4/operator/list.hpp b/include/iris/x4/operator/list.hpp index c6d9039b9..87646a504 100644 --- a/include/iris/x4/operator/list.hpp +++ b/include/iris/x4/operator/list.hpp @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -63,6 +64,15 @@ struct list : binary_parser> return true; } } + + [[nodiscard]] constexpr std::string get_x4_info() const + { + return std::format( + "({} % {})", + get_info{}(this->left), + get_info{}(this->right) + ); + } }; template diff --git a/include/iris/x4/operator/sequence.hpp b/include/iris/x4/operator/sequence.hpp index 67109b1a9..9d31d2550 100644 --- a/include/iris/x4/operator/sequence.hpp +++ b/include/iris/x4/operator/sequence.hpp @@ -20,7 +20,9 @@ #include #include +#include +#include #include #include #include @@ -28,6 +30,9 @@ namespace iris::x4 { +template +struct expect_directive; + template struct sequence : binary_parser> { @@ -73,6 +78,23 @@ struct sequence : binary_parser> { return detail::parse_sequence(*this, first, last, ctx, attr); } + + [[nodiscard]] constexpr std::string get_x4_info() const + { + if constexpr (iris::is_ttp_specialization_of_v) { + return std::format( + "{} > {}", + get_info{}(this->left), + get_info{}(this->right.subject) + ); + } else { + return std::format( + "{} >> {}", + get_info{}(this->left), + get_info{}(this->right) + ); + } + } }; template diff --git a/include/iris/x4/string/literal_string.hpp b/include/iris/x4/string/literal_string.hpp index 848e5ed7a..54def7122 100644 --- a/include/iris/x4/string/literal_string.hpp +++ b/include/iris/x4/string/literal_string.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -75,7 +76,7 @@ struct get_info> using result_type = std::string; [[nodiscard]] constexpr std::string operator()(literal_string const& p) const { - return '"' + x4::to_utf8(p.str) + '"'; + return std::format("\"{}\"", p.str); } }; diff --git a/modules/iris b/modules/iris index cec583eed..fe9e3a14d 160000 --- a/modules/iris +++ b/modules/iris @@ -1 +1 @@ -Subproject commit cec583eed7ab2fb70e7ef6aa52ab840bc03e92ca +Subproject commit fe9e3a14dd412910b5a6dd6f14590bb6ced68ddc diff --git a/test/x4/expect.cpp b/test/x4/expect.cpp index 86fe5b483..7421940de 100644 --- a/test/x4/expect.cpp +++ b/test/x4/expect.cpp @@ -339,13 +339,11 @@ TEST_CASE("expect") #ifndef IRIS_X4_NO_RTTI X4_TEST_FAILURE("ay:a", char_ > char_('x') >> ':' > 'a', { - CHECK(x.which().find("sequence") != std::string::npos); CHECK(where == "y:a"sv); }); #else X4_TEST_FAILURE("ay:a", char_ > char_('x') >> ':' > 'a', { - CHECK(which == "undefined"sv); CHECK(where == "y:a"sv); }); #endif @@ -418,23 +416,6 @@ TEST_CASE("expect") }); } - // - // ********* Developers note ********** - // - // As of now (see `git blame`), get_info is still not - // specialized for many of the X4 parsers so that the - // value of `expectation_failure<...>::which()` will be - // implementation-defined demangled string. - // Therefore, it's essentially impossible to test them - // right now; further work must be done. - // - // Some specific situations are already been reported - // (e.g. https://github.com/boostorg/spirit/issues/777) - // but we really need to implement all specializations for - // X4's predefined parsers, not just the one reported above. - // - - // sanity check: test expectation_failure propagation // on custom skippers {