From 4bf6c79f88a388bcc0cf2a31a9d166efaa4022d5 Mon Sep 17 00:00:00 2001 From: Andersama Date: Mon, 4 Jan 2021 18:35:24 -0800 Subject: [PATCH] implement reset groups --- include/ctre/actions/capture.inc.hpp | 134 +++++++++++++++++++++++++++ include/ctre/atoms.hpp | 4 + include/ctre/evaluation.hpp | 10 ++ include/ctre/find_captures.hpp | 7 ++ include/ctre/first.hpp | 11 +++ include/ctre/pcre.hpp | 3 + include/ctre/pcre_actions.hpp | 2 + tests/generating.cpp | 3 + 8 files changed, 174 insertions(+) diff --git a/include/ctre/actions/capture.inc.hpp b/include/ctre/actions/capture.inc.hpp index ebf5437a..b63fd759 100644 --- a/include/ctre/actions/capture.inc.hpp +++ b/include/ctre/actions/capture.inc.hpp @@ -36,5 +36,139 @@ template , Content...>(), ctll::list()), pcre_parameters()}; } +template +static constexpr auto replace_captures_with_id(T, string) { // fallback case, no transform + return T{}; +} + +template +static constexpr auto replace_captures_with_id(capture, string) { + return capture(Content{}, string{}))...>{}; +} +// named reseted captures must have same Str... for all instances inside the call (otherwise how would we know how to access which by name?) +template +static constexpr auto replace_captures_with_id(capture_with_name, Content...>, string) { + static_assert((id{} == id{}) && "named captures must be the same"); + return capture_with_name, decltype(replace_captures_with_id(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(sequence, string) { + return sequence(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(reset_group, string) { + return reset_group(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(reset_group_with_name, Content...>, string) { + return reset_group_with_name, decltype(replace_captures_with_id(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(atomic_group, string) { + return atomic_group(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(lookahead_positive, string) { + return lookahead_positive(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(lookahead_negative, string) { + return lookahead_negative(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(possessive_repeat, string) { + return possessive_repeat(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(repeat, string) { + return repeat(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(lazy_repeat, string) { + return lazy_repeat(Content{}, string{}))...>{}; +} + +template +static constexpr auto replace_captures_with_id(select, string) { + return select(Opts{}, string{}))...>{}; +} + +// get name (might be a utility already written) +template +static constexpr string get_capture_name(captured_content>) noexcept { + return string{}; +} + +template +static constexpr string<> get_capture_name(captured_content) noexcept { + return string<>{}; +} + +template +static constexpr id make_id_from_string(string) noexcept { + return id{}; +} + +// find the first named capture +template +static constexpr auto get_capture_with_name(ctll::list) noexcept { + if constexpr (sizeof...(Tail)) + return get_capture_with_name(ctll::list{}); + else + return ctll::list<>{}; +} + +template +static constexpr auto get_capture_with_name(ctll::list, Tail...>) noexcept { + return ctll::list>{}; +} + +// reset group start +template static constexpr auto apply(pcre::start_reset_group, ctll::term, pcre_context, pcre_parameters>) { + return pcre_context{ ctll::push_front(reset_start(), ctll::list()), pcre_parameters() }; + //ctll::list(), Ts...>(), }; +} + +// reset group end +template static constexpr auto apply(pcre::make_reset_group, ctll::term, pcre_context, Ts...>, pcre_parameters>) { + using first_capture = decltype(ctll::front(find_captures(A{}))); + if constexpr (::std::is_same_v) { + //no captures to reset... easy case + return pcre_context{ ctll::list, Ts...>(), pcre_parameters() }; + } else { + using first_named_capture = decltype(ctll::front(get_capture_with_name(find_captures(A{})))); + if constexpr (::std::is_same_v) { + return pcre_context{ ctll::list(A{}, string<>{}))>, Ts...>(), pcre_parameters() }; + } else { + return pcre_context{ ctll::list(A{}, get_capture_name(first_named_capture{})))>, Ts...>(), pcre_parameters() }; + } + } +} +// reset group end (sequence) +template static constexpr auto apply(pcre::make_reset_group, ctll::term, pcre_context, reset_start, Ts...>, pcre_parameters>) { + using first_capture = decltype(ctll::front(find_captures(sequence{}))); + if constexpr (::std::is_same_v) { + //no captures to reset... easy case + return pcre_context{ ctll::list, Ts...>(), pcre_parameters() }; + } else { + using first_named_capture = decltype(ctll::front(get_capture_with_name(find_captures(sequence{})))); + if constexpr (::std::is_same_v) { + return pcre_context{ ctll::list(Content{}, string<>{}))...>, Ts...>(), pcre_parameters() }; + } else { + return pcre_context{ ctll::list(Content{}, get_capture_name(first_named_capture{})))...>, Ts...>(), pcre_parameters() }; + } + } +} + + #endif diff --git a/include/ctre/atoms.hpp b/include/ctre/atoms.hpp index 94a105bf..5527cac1 100644 --- a/include/ctre/atoms.hpp +++ b/include/ctre/atoms.hpp @@ -42,9 +42,13 @@ template struct capture { }; template struct capture_with_name { }; +template struct reset_group { }; +template struct reset_group_with_name { }; + template struct back_reference { }; template struct back_reference_with_name { }; +template struct reset_start { }; template struct look_start { }; template struct lookahead_positive { }; diff --git a/include/ctre/evaluation.hpp b/include/ctre/evaluation.hpp index 6701c6fa..1dfc7313 100644 --- a/include/ctre/evaluation.hpp +++ b/include/ctre/evaluation.hpp @@ -159,6 +159,16 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c } } +template +constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags & f, R captures, ctll::list, Tail...>) noexcept { + return evaluate(begin, current, end, f, captures, ctll::list, Tail...>{}); +} + +template +constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags& f, R captures, ctll::list, Tail...>) noexcept { + return evaluate(begin, current, end, f, captures, ctll::list, Tail...>{}); +} + // matching empty in patterns template constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags & f, R captures, ctll::list) noexcept { diff --git a/include/ctre/find_captures.hpp b/include/ctre/find_captures.hpp index e6c49e26..381cd676 100644 --- a/include/ctre/find_captures.hpp +++ b/include/ctre/find_captures.hpp @@ -120,6 +120,13 @@ template (), ctll::list>()); } +template constexpr auto find_captures(ctll::list, Tail...>, ctll::list) noexcept { + return find_captures(ctll::list(), ctll::list>()); +} + +template constexpr auto find_captures(ctll::list, Tail...>, ctll::list) noexcept { + return find_captures(ctll::list(), ctll::list>()); +} } diff --git a/include/ctre/first.hpp b/include/ctre/first.hpp index 65ef7ac0..6ed878cd 100644 --- a/include/ctre/first.hpp +++ b/include/ctre/first.hpp @@ -178,6 +178,17 @@ constexpr auto first(ctll::list l, ctll::list{}); } +// reset groups +template +constexpr auto first(ctll::list l, ctll::list, Tail...>) noexcept { + return first(l, ctll::list{}); +} + +template +constexpr auto first(ctll::list l, ctll::list, Tail...>) noexcept { + return first(l, ctll::list{}); +} + // backreference template constexpr auto first(ctll::list, ctll::list, Tail...>) noexcept { diff --git a/include/ctre/pcre.hpp b/include/ctre/pcre.hpp index 02f85d58..8ad22321 100644 --- a/include/ctre/pcre.hpp +++ b/include/ctre/pcre.hpp @@ -93,6 +93,7 @@ struct pcre { struct make_property: ctll::action {}; struct make_property_negative: ctll::action {}; struct make_range: ctll::action {}; + struct make_reset_group: ctll::action {}; struct make_relative_back_reference: ctll::action {}; struct make_sequence: ctll::action {}; struct negate_class_named: ctll::action {}; @@ -132,6 +133,7 @@ struct pcre { struct start_atomic: ctll::action {}; struct start_lookahead_negative: ctll::action {}; struct start_lookahead_positive: ctll::action {}; + struct start_reset_group: ctll::action {}; // (q)LL1 function: using _others = ctll::neg_set<'!','$','\x28','\x29','*','+',',','-','.',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_','a','b','c','d','e','f','g','h','0','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D','1','2','3','4','5','6','7','8','9'>; @@ -272,6 +274,7 @@ struct pcre { static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push>; static constexpr auto rule(d, ctll::term<'!'>) -> ctll::push>; static constexpr auto rule(d, ctll::term<'='>) -> ctll::push>; + static constexpr auto rule(d, ctll::term<'|'>) -> ctll::push>; static constexpr auto rule(e, ctll::term<'d'>) -> ctll::push; static constexpr auto rule(e, ctll::term<'h'>) -> ctll::push; diff --git a/include/ctre/pcre_actions.hpp b/include/ctre/pcre_actions.hpp index c9536b2b..3da3b9ea 100644 --- a/include/ctre/pcre_actions.hpp +++ b/include/ctre/pcre_actions.hpp @@ -5,6 +5,8 @@ #include "atoms.hpp" #include "atoms_unicode.hpp" #include "id.hpp" +#include "first.hpp" +#include "return_type.hpp" #include #include diff --git a/tests/generating.cpp b/tests/generating.cpp index ee6cf80c..e520a6c1 100644 --- a/tests/generating.cpp +++ b/tests/generating.cpp @@ -208,6 +208,9 @@ static_assert(same_f(CTRE_GEN("(((a)(b)))"),ctre::capture<1, ctre::capture<2,ctr static_assert(same_f(CTRE_GEN("((?:a)(b))"), ctre::capture<1,ctre::character<'a'>,ctre::capture<2,ctre::character<'b'>>>())); +// reset groups +static_assert(same_f(CTRE_GEN("(?|(?a)|(b))"), ctre::reset_group_with_name<1,ctre::id<'n','a','m','e'>,ctre::select, ctre::character<'a'>>,ctre::capture<1, ctre::character<'b'>>>>())); +static_assert(same_f(CTRE_GEN("(?|(b)|(a))"), ctre::reset_group<1,ctre::select>, ctre::capture<1, ctre::character<'a'>>>>())); // backreference static_assert(same_f(CTRE_GEN("(a)\\g{1}"), ctre::sequence>, ctre::back_reference<1>>()));