Skip to content

Commit

Permalink
implement reset groups
Browse files Browse the repository at this point in the history
  • Loading branch information
Andersama committed Jan 5, 2021
1 parent 0e646f3 commit 4bf6c79
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 0 deletions.
134 changes: 134 additions & 0 deletions include/ctre/actions/capture.inc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,139 @@ template <auto... Str, auto V, typename... Content, size_t Id, typename... Ts, s
return pcre_context{ctll::push_front(capture_with_name<Id, id<Str...>, Content...>(), ctll::list<Ts...>()), pcre_parameters<Counter>()};
}

template<size_t To, auto... Str, typename T>
static constexpr auto replace_captures_with_id(T, string<Str...>) { // fallback case, no transform
return T{};
}

template<size_t To, auto... Str, size_t From, typename... Content>
static constexpr auto replace_captures_with_id(capture<From, Content...>, string<Str...>) {
return capture<To, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}
// 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<size_t To, auto... Str, size_t From, auto... Str2, typename... Content>
static constexpr auto replace_captures_with_id(capture_with_name<From, id<Str2...>, Content...>, string<Str...>) {
static_assert((id<Str...>{} == id<Str2...>{}) && "named captures must be the same");
return capture_with_name<From, id<Str...>, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, typename... Content>
static constexpr auto replace_captures_with_id(sequence<Content...>, string<Str...>) {
return sequence<decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, size_t Id, typename... Content>
static constexpr auto replace_captures_with_id(reset_group<Id, Content...>, string<Str...>) {
return reset_group<To, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, size_t Id, auto... Str2, typename... Content>
static constexpr auto replace_captures_with_id(reset_group_with_name<Id, id<Str2...>, Content...>, string<Str...>) {
return reset_group_with_name<To, id<Str...>, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, typename... Content>
static constexpr auto replace_captures_with_id(atomic_group<Content...>, string<Str...>) {
return atomic_group<decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, typename... Content>
static constexpr auto replace_captures_with_id(lookahead_positive<Content...>, string<Str...>) {
return lookahead_positive<decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, typename... Content>
static constexpr auto replace_captures_with_id(lookahead_negative<Content...>, string<Str...>) {
return lookahead_negative<decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, size_t A, size_t B, typename... Content>
static constexpr auto replace_captures_with_id(possessive_repeat<A, B, Content...>, string<Str...>) {
return possessive_repeat<A, B, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, size_t A, size_t B, typename... Content>
static constexpr auto replace_captures_with_id(repeat<A, B, Content...>, string<Str...>) {
return repeat<A, B, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, size_t A, size_t B, typename... Content>
static constexpr auto replace_captures_with_id(lazy_repeat<A, B, Content...>, string<Str...>) {
return lazy_repeat<A, B, decltype(replace_captures_with_id<To>(Content{}, string<Str...>{}))...>{};
}

template<size_t To, auto... Str, typename... Opts>
static constexpr auto replace_captures_with_id(select<Opts...>, string<Str...>) {
return select<decltype(replace_captures_with_id<To>(Opts{}, string<Str...>{}))...>{};
}

// get name (might be a utility already written)
template<size_t Idx, auto... Str>
static constexpr string<Str...> get_capture_name(captured_content<Idx, id<Str...>>) noexcept {
return string<Str...>{};
}

template<size_t Idx>
static constexpr string<> get_capture_name(captured_content<Idx>) noexcept {
return string<>{};
}

template<auto... Str>
static constexpr id<Str...> make_id_from_string(string<Str...>) noexcept {
return id<Str...>{};
}

// find the first named capture
template<typename H, typename... Tail>
static constexpr auto get_capture_with_name(ctll::list<H, Tail...>) noexcept {
if constexpr (sizeof...(Tail))
return get_capture_with_name(ctll::list<Tail...>{});
else
return ctll::list<>{};
}

template<size_t Idx, typename Name, typename... Tail>
static constexpr auto get_capture_with_name(ctll::list<captured_content<Idx, Name>, Tail...>) noexcept {
return ctll::list<captured_content<Idx, Name>>{};
}

// reset group start
template <auto V, typename... Ts, size_t Counter> static constexpr auto apply(pcre::start_reset_group, ctll::term<V>, pcre_context<ctll::list<Ts...>, pcre_parameters<Counter>>) {
return pcre_context{ ctll::push_front(reset_start<Counter+1>(), ctll::list<Ts...>()), pcre_parameters<Counter>() };
//ctll::list<reset_start<Counter+1>(), Ts...>(), };
}

// reset group end
template <auto V, typename A, typename... Ts, size_t Id, size_t Counter> static constexpr auto apply(pcre::make_reset_group, ctll::term<V>, pcre_context<ctll::list<A, reset_start<Id>, Ts...>, pcre_parameters<Counter>>) {
using first_capture = decltype(ctll::front(find_captures(A{})));
if constexpr (::std::is_same_v<first_capture, ctll::_nothing>) {
//no captures to reset... easy case
return pcre_context{ ctll::list<sequence<A>, Ts...>(), pcre_parameters<Counter>() };
} else {
using first_named_capture = decltype(ctll::front(get_capture_with_name(find_captures(A{}))));
if constexpr (::std::is_same_v<first_named_capture, ctll::_nothing>) {
return pcre_context{ ctll::list<reset_group<Id, decltype(replace_captures_with_id<Id>(A{}, string<>{}))>, Ts...>(), pcre_parameters<Counter>() };
} else {
return pcre_context{ ctll::list<reset_group_with_name<Id, decltype(make_id_from_string(get_capture_name(first_named_capture{}))), decltype(replace_captures_with_id<Id>(A{}, get_capture_name(first_named_capture{})))>, Ts...>(), pcre_parameters<Counter>() };
}
}
}
// reset group end (sequence)
template <auto V, typename... Content, typename... Ts, size_t Id, size_t Counter> static constexpr auto apply(pcre::make_reset_group, ctll::term<V>, pcre_context<ctll::list<ctre::sequence<Content...>, reset_start<Id>, Ts...>, pcre_parameters<Counter>>) {
using first_capture = decltype(ctll::front(find_captures(sequence<Content...>{})));
if constexpr (::std::is_same_v<first_capture, ctll::_nothing>) {
//no captures to reset... easy case
return pcre_context{ ctll::list<sequence<Content...>, Ts...>(), pcre_parameters<Counter>() };
} else {
using first_named_capture = decltype(ctll::front(get_capture_with_name(find_captures(sequence<Content...>{}))));
if constexpr (::std::is_same_v<first_named_capture, ctll::_nothing>) {
return pcre_context{ ctll::list<reset_group<Id, decltype(replace_captures_with_id<Id>(Content{}, string<>{}))...>, Ts...>(), pcre_parameters<Counter>() };
} else {
return pcre_context{ ctll::list<reset_group<Id, decltype(make_id_from_string(get_capture_name(first_named_capture{}))), decltype(replace_captures_with_id<Id>(Content{}, get_capture_name(first_named_capture{})))...>, Ts...>(), pcre_parameters<Counter>() };
}
}
}



#endif
4 changes: 4 additions & 0 deletions include/ctre/atoms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ template <size_t Index, typename... Content> struct capture { };

template <size_t Index, typename Name, typename... Content> struct capture_with_name { };

template <size_t Index, typename... Content> struct reset_group { };
template <size_t Index, typename Name, typename... Content> struct reset_group_with_name { };

template <size_t Index> struct back_reference { };
template <typename Name> struct back_reference_with_name { };

template <size_t Idx> struct reset_start { };
template <typename Type> struct look_start { };

template <typename... Content> struct lookahead_positive { };
Expand Down
10 changes: 10 additions & 0 deletions include/ctre/evaluation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
}
}

template <typename R, typename Iterator, typename EndIterator, size_t Id, typename... Content, typename... Tail>
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags & f, R captures, ctll::list<reset_group<Id, Content...>, Tail...>) noexcept {
return evaluate(begin, current, end, f, captures, ctll::list<sequence<Content...>, Tail...>{});
}

template <typename R, typename Iterator, typename EndIterator, size_t Id, typename Name, typename... Content, typename... Tail>
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags& f, R captures, ctll::list<reset_group_with_name<Id, Name, Content...>, Tail...>) noexcept {
return evaluate(begin, current, end, f, captures, ctll::list<sequence<Content...>, Tail...>{});
}

// matching empty in patterns
template <typename R, typename Iterator, typename EndIterator, typename... Tail>
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags & f, R captures, ctll::list<empty, Tail...>) noexcept {
Expand Down
7 changes: 7 additions & 0 deletions include/ctre/find_captures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ template <size_t Id, typename Name, typename... Content, typename... Tail, typen
return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id, Name>>());
}

template <size_t Id, typename... Content, typename... Tail, typename... Output> constexpr auto find_captures(ctll::list<reset_group<Id, Content...>, Tail...>, ctll::list<Output...>) noexcept {
return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id>>());
}

template <size_t Id, typename Name, typename... Content, typename... Tail, typename... Output> constexpr auto find_captures(ctll::list<reset_group_with_name<Id, Name, Content...>, Tail...>, ctll::list<Output...>) noexcept {
return find_captures(ctll::list<Content..., Tail...>(), ctll::list<Output..., captured_content<Id, Name>>());
}


}
Expand Down
11 changes: 11 additions & 0 deletions include/ctre/first.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,17 @@ constexpr auto first(ctll::list<Content...> l, ctll::list<capture_with_name<Id,
return first(l, ctll::list<Seq..., Tail...>{});
}

// reset groups
template <typename... Content, size_t Id, typename... Seq, typename... Tail>
constexpr auto first(ctll::list<Content...> l, ctll::list<reset_group<Id, Seq...>, Tail...>) noexcept {
return first(l, ctll::list<Seq..., Tail...>{});
}

template <typename... Content, size_t Id, typename Name, typename... Seq, typename... Tail>
constexpr auto first(ctll::list<Content...> l, ctll::list<reset_group_with_name<Id, Name, Seq...>, Tail...>) noexcept {
return first(l, ctll::list<Seq..., Tail...>{});
}

// backreference
template <typename... Content, size_t Id, typename... Tail>
constexpr auto first(ctll::list<Content...>, ctll::list<back_reference<Id>, Tail...>) noexcept {
Expand Down
3 changes: 3 additions & 0 deletions include/ctre/pcre.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
Expand Down Expand Up @@ -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'>;
Expand Down Expand Up @@ -272,6 +274,7 @@ struct pcre {
static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push<reset_capture, ctll::anything, start_atomic, content_in_capture, make_atomic, ctll::term<'\x29'>>;
static constexpr auto rule(d, ctll::term<'!'>) -> ctll::push<reset_capture, ctll::anything, start_lookahead_negative, content_in_capture, look_finish, ctll::term<'\x29'>>;
static constexpr auto rule(d, ctll::term<'='>) -> ctll::push<reset_capture, ctll::anything, start_lookahead_positive, content_in_capture, look_finish, ctll::term<'\x29'>>;
static constexpr auto rule(d, ctll::term<'|'>) -> ctll::push<reset_capture, ctll::anything, start_reset_group, content_in_capture, make_reset_group, ctll::term<'\x29'>>;

static constexpr auto rule(e, ctll::term<'d'>) -> ctll::push<ctll::anything, class_digit>;
static constexpr auto rule(e, ctll::term<'h'>) -> ctll::push<ctll::anything, class_horizontal_space>;
Expand Down
2 changes: 2 additions & 0 deletions include/ctre/pcre_actions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "atoms.hpp"
#include "atoms_unicode.hpp"
#include "id.hpp"
#include "first.hpp"
#include "return_type.hpp"
#include <cstdint>
#include <limits>

Expand Down
3 changes: 3 additions & 0 deletions tests/generating.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("(?|(?<name>a)|(b))"), ctre::reset_group_with_name<1,ctre::id<'n','a','m','e'>,ctre::select<ctre::capture_with_name<1,ctre::id<'n','a','m','e'>, 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<'b'>>, ctre::capture<1, ctre::character<'a'>>>>()));

// backreference
static_assert(same_f(CTRE_GEN("(a)\\g{1}"), ctre::sequence<ctre::capture<1,ctre::character<'a'>>, ctre::back_reference<1>>()));
Expand Down

0 comments on commit 4bf6c79

Please sign in to comment.