Skip to content

Commit a843638

Browse files
committed
Allow [^] empty set to be equivalent of "any one character" (fixes #341)
1 parent 21d0cdf commit a843638

File tree

6 files changed

+32
-4
lines changed

6 files changed

+32
-4
lines changed

include/ctre/actions/set.inc.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ template <template <typename...> typename SetType, typename T, typename... As, b
2222
template <auto V, typename A,typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_start, ctll::term<V>, pcre_context<ctll::list<A,Ts...>, Parameters> subject) {
2323
return pcre_context{ctll::push_front(set<A>(), ctll::list<Ts...>()), subject.parameters};
2424
}
25+
26+
// set_empty
27+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
28+
return pcre_context{ctll::push_front(set<>(), ctll::list<Ts...>()), subject.parameters};
29+
}
30+
2531
// set_make
2632
template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_make, ctll::term<V>, pcre_context<ctll::list<set<Content...>, Ts...>, Parameters> subject) {
2733
return pcre_context{ctll::push_front(set<Content...>(), ctll::list<Ts...>()), subject.parameters};

include/ctre/pcre.gram

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ mode_switch2->close | <mode_switch>
8989

9090
character_class->sopen,<set>,[set_make],sclose|sopen,caret,<set2a>,[set_make_negative],sclose
9191
set-><setitem>,[set_start],<set2b>
92-
set2a-><setitem2>,[set_start],<set2b>|epsilon
92+
set2a-><setitem2>,[set_start],<set2b>|epsilon,[set_empty]
9393
set2b-><setitem2>,[set_combine],<set2b>|epsilon
9494

9595
class_named->sopen,colon,<class_named_name>,colon,sclose | sopen,colon,caret,<class_named_name>,[negate_class_named],colon,sclose

include/ctre/pcre.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct pcre {
130130
struct repeat_star: ctll::action {};
131131
struct reset_capture: ctll::action {};
132132
struct set_combine: ctll::action {};
133+
struct set_empty: ctll::action {};
133134
struct set_make: ctll::action {};
134135
struct set_make_negative: ctll::action {};
135136
struct set_start: ctll::action {};
@@ -433,11 +434,11 @@ struct pcre {
433434
static constexpr auto rule(repeat, ctll::term<'*'>) -> ctll::push<ctll::anything, repeat_star, mod>;
434435
static constexpr auto rule(repeat, ctll::term<'\x7D'>) -> ctll::reject;
435436

436-
static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::epsilon;
437437
static constexpr auto rule(set2a, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b>;
438438
static constexpr auto rule(set2a, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_start, set2b>;
439439
static constexpr auto rule(set2a, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','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','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
440440
static constexpr auto rule(set2a, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
441+
static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::push<set_empty>;
441442
static constexpr auto rule(set2a, ctll::term<'-'>) -> ctll::reject;
442443

443444
static constexpr auto rule(set2b, ctll::term<']'>) -> ctll::epsilon;

single-header/ctre-unicode.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,7 @@ struct pcre {
10751075
struct repeat_star: ctll::action {};
10761076
struct reset_capture: ctll::action {};
10771077
struct set_combine: ctll::action {};
1078+
struct set_empty: ctll::action {};
10781079
struct set_make: ctll::action {};
10791080
struct set_make_negative: ctll::action {};
10801081
struct set_start: ctll::action {};
@@ -1378,11 +1379,11 @@ struct pcre {
13781379
static constexpr auto rule(repeat, ctll::term<'*'>) -> ctll::push<ctll::anything, repeat_star, mod>;
13791380
static constexpr auto rule(repeat, ctll::term<'\x7D'>) -> ctll::reject;
13801381

1381-
static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::epsilon;
13821382
static constexpr auto rule(set2a, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b>;
13831383
static constexpr auto rule(set2a, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_start, set2b>;
13841384
static constexpr auto rule(set2a, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','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','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
13851385
static constexpr auto rule(set2a, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
1386+
static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::push<set_empty>;
13861387
static constexpr auto rule(set2a, ctll::term<'-'>) -> ctll::reject;
13871388

13881389
static constexpr auto rule(set2b, ctll::term<']'>) -> ctll::epsilon;
@@ -2911,6 +2912,12 @@ template <template <typename...> typename SetType, typename T, typename... As, b
29112912
template <auto V, typename A,typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_start, ctll::term<V>, pcre_context<ctll::list<A,Ts...>, Parameters> subject) {
29122913
return pcre_context{ctll::push_front(set<A>(), ctll::list<Ts...>()), subject.parameters};
29132914
}
2915+
2916+
// set_empty
2917+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2918+
return pcre_context{ctll::push_front(set<>(), ctll::list<Ts...>()), subject.parameters};
2919+
}
2920+
29142921
// set_make
29152922
template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_make, ctll::term<V>, pcre_context<ctll::list<set<Content...>, Ts...>, Parameters> subject) {
29162923
return pcre_context{ctll::push_front(set<Content...>(), ctll::list<Ts...>()), subject.parameters};

single-header/ctre.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,7 @@ struct pcre {
10721072
struct repeat_star: ctll::action {};
10731073
struct reset_capture: ctll::action {};
10741074
struct set_combine: ctll::action {};
1075+
struct set_empty: ctll::action {};
10751076
struct set_make: ctll::action {};
10761077
struct set_make_negative: ctll::action {};
10771078
struct set_start: ctll::action {};
@@ -1375,11 +1376,11 @@ struct pcre {
13751376
static constexpr auto rule(repeat, ctll::term<'*'>) -> ctll::push<ctll::anything, repeat_star, mod>;
13761377
static constexpr auto rule(repeat, ctll::term<'\x7D'>) -> ctll::reject;
13771378

1378-
static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::epsilon;
13791379
static constexpr auto rule(set2a, ctll::term<'['>) -> ctll::push<ctll::anything, ctll::term<':'>, i, range, set_start, set2b>;
13801380
static constexpr auto rule(set2a, ctll::term<'\\'>) -> ctll::push<ctll::anything, f, set_start, set2b>;
13811381
static constexpr auto rule(set2a, ctll::set<'!','$','\x28','\x29','*','+',',','.','/','0','1','2','3','4','5','6','7','8','9',':','<','=','>','?','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','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D'>) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
13821382
static constexpr auto rule(set2a, _others) -> ctll::push<ctll::anything, push_character, range, set_start, set2b>;
1383+
static constexpr auto rule(set2a, ctll::term<']'>) -> ctll::push<set_empty>;
13831384
static constexpr auto rule(set2a, ctll::term<'-'>) -> ctll::reject;
13841385

13851386
static constexpr auto rule(set2b, ctll::term<']'>) -> ctll::epsilon;
@@ -2908,6 +2909,12 @@ template <template <typename...> typename SetType, typename T, typename... As, b
29082909
template <auto V, typename A,typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_start, ctll::term<V>, pcre_context<ctll::list<A,Ts...>, Parameters> subject) {
29092910
return pcre_context{ctll::push_front(set<A>(), ctll::list<Ts...>()), subject.parameters};
29102911
}
2912+
2913+
// set_empty
2914+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_empty, ctll::term<V>, pcre_context<ctll::list<Ts...>, Parameters> subject) {
2915+
return pcre_context{ctll::push_front(set<>(), ctll::list<Ts...>()), subject.parameters};
2916+
}
2917+
29112918
// set_make
29122919
template <auto V, typename... Content, typename... Ts, typename Parameters> static constexpr auto apply(pcre::set_make, ctll::term<V>, pcre_context<ctll::list<set<Content...>, Ts...>, Parameters> subject) {
29132920
return pcre_context{ctll::push_front(set<Content...>(), ctll::list<Ts...>()), subject.parameters};

tests/matching3.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,10 @@ TEST_SEARCH(228, "(?<=ba|cd)s", "bas");
239239
TEST_NOT_SEARCH(229, "(?<!ba|cd)s", "bas"); // negative means both "ba|cd most not be there"
240240
TEST_SEARCH(230, "(?<=ba|cd)s", "cds");
241241
TEST_NOT_SEARCH(231, "(?<!ba|cd)s", "cds"); // negative means both "ba|cd most not be there"
242+
243+
// issue #341 (negative empty set is any character)
244+
TEST_MATCH(232, "[^]", "a");
245+
TEST_NOT_MATCH(233, "[^]", "");
246+
TEST_MATCH(234, "[^]+", "x");
247+
TEST_MATCH(235, "[^]?", "");
248+

0 commit comments

Comments
 (0)