Skip to content

Commit 32594a0

Browse files
authored
Merge pull request #261 from hanickadot/feature/switching-modes-in-regex
support for switching modes inside the pattern
2 parents 331aebc + 1800359 commit 32594a0

File tree

11 files changed

+292
-4
lines changed

11 files changed

+292
-4
lines changed

include/ctre/actions/mode.inc.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef CTRE__ACTIONS__MODE__HPP
2+
#define CTRE__ACTIONS__MODE__HPP
3+
4+
// we need to reset counter and wrap Mode into mode_switch
5+
template <typename Mode, typename... Ts, typename Parameters> static constexpr auto apply_mode(Mode, ctll::list<Ts...>, Parameters) {
6+
return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, Parameters>{};
7+
}
8+
9+
template <typename Mode, typename... Ts, size_t Id, size_t Counter> static constexpr auto apply_mode(Mode, ctll::list<capture_id<Id>, Ts...>, pcre_parameters<Counter>) {
10+
return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, pcre_parameters<Counter-1>>{};
11+
}
12+
13+
// catch a semantic action into mode
14+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_case_insensitive mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
15+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
16+
}
17+
18+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_case_sensitive mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
19+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
20+
}
21+
22+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_singleline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
23+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
24+
}
25+
26+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_multiline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
27+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
28+
}
29+
30+
// to properly reset capture
31+
32+
#endif

include/ctre/atoms.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ struct assert_subject_end_line{ };
7171
struct assert_line_begin { };
7272
struct assert_line_end { };
7373

74+
template <typename> struct mode_switch { };
75+
7476
}
7577

7678
#endif

include/ctre/evaluation.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,12 @@ constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator curre
550550
}
551551
}
552552

553+
// switching modes
554+
template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename Mode, typename... Tail>
555+
constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<mode_switch<Mode>, Tail...>) noexcept {
556+
return evaluate(begin, current, last, f + Mode{}, captures, ctll::list<Tail...>());
557+
}
558+
553559

554560
}
555561

include/ctre/flags_and_modes.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ struct flags {
3333
(this->set_flag(Args{}), ...);
3434
}
3535

36+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_insensitive) noexcept {
37+
f.case_insensitive = true;
38+
return f;
39+
}
40+
41+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_sensitive) noexcept {
42+
f.case_insensitive = false;
43+
return f;
44+
}
45+
46+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_singleline) noexcept {
47+
f.multiline = false;
48+
return f;
49+
}
50+
51+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_multiline) noexcept {
52+
f.multiline = true;
53+
return f;
54+
}
55+
3656
constexpr CTRE_FORCE_INLINE void set_flag(ctre::singleline) noexcept {
3757
multiline = false;
3858
}

include/ctre/pcre.gram

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ number2->epsilon | num,[push_number],<number2>
6767
preblock->open,[prepare_capture],<block>
6868

6969
block-><content_in_capture>,[make_capture],close
70+
block->questionmark,<mode_switch>
7071
block->questionmark,angle_close,[reset_capture],[start_atomic],<content_in_capture>,[make_atomic],close
7172
block->questionmark,equal_sign,[reset_capture],[start_lookahead_positive],<content_in_capture>,[look_finish],close
7273
block->questionmark,angle_open,equal_sign,[reset_capture],[start_lookbehind_positive],<content_in_capture>,[look_finish],close
@@ -78,6 +79,11 @@ block->questionmark,angle_open,<block_name>,angle_close,<content_in_capture>,[ma
7879
block_name->alpha_characters,[push_name],<block_name2>
7980
block_name2->alphanum_characters,[push_name],<block_name2>|epsilon
8081

82+
mode_switch->i,[mode_case_insensitive],<mode_switch2>
83+
mode_switch->c,[mode_case_sensitive],<mode_switch2>
84+
mode_switch->s,[mode_singleline],<mode_switch2>
85+
mode_switch->m,[mode_multiline],<mode_switch2>
86+
mode_switch2->close | <mode_switch>
8187

8288
character_class->sopen,<set>,[set_make],sclose|sopen,caret,<set2a>,[set_make_negative],sclose
8389
set-><setitem>,[set_start],<set2b>

include/ctre/pcre.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct pcre {
3333
struct l {};
3434
struct m {};
3535
struct mod {};
36+
struct mode_switch2 {};
3637
struct n {};
3738
struct number2 {};
3839
struct number {};
@@ -92,6 +93,10 @@ struct pcre {
9293
struct make_range: ctll::action {};
9394
struct make_relative_back_reference: ctll::action {};
9495
struct make_sequence: ctll::action {};
96+
struct mode_case_insensitive: ctll::action {};
97+
struct mode_case_sensitive: ctll::action {};
98+
struct mode_multiline: ctll::action {};
99+
struct mode_singleline: ctll::action {};
95100
struct negate_class_named: ctll::action {};
96101
struct prepare_capture: ctll::action {};
97102
struct push_assert_begin: ctll::action {};
@@ -264,6 +269,10 @@ struct pcre {
264269
static constexpr auto rule(content_in_capture, ctll::term<'\x29'>) -> ctll::push<push_empty>;
265270
static constexpr auto rule(content_in_capture, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject;
266271

272+
static constexpr auto rule(d, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
273+
static constexpr auto rule(d, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
274+
static constexpr auto rule(d, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
275+
static constexpr auto rule(d, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
267276
static constexpr auto rule(d, ctll::term<'<'>) -> ctll::push<ctll::anything, o>;
268277
static constexpr auto rule(d, ctll::term<':'>) -> ctll::push<ctll::anything, reset_capture, content_in_capture, ctll::term<'\x29'>>;
269278
static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push<ctll::anything, reset_capture, start_atomic, content_in_capture, make_atomic, ctll::term<'\x29'>>;
@@ -362,6 +371,12 @@ struct pcre {
362371
static constexpr auto rule(mod, ctll::term<'+'>) -> ctll::push<ctll::anything, make_possessive>;
363372
static constexpr auto rule(mod, ctll::set<'*','\x7B','\x7D'>) -> ctll::reject;
364373

374+
static constexpr auto rule(mode_switch2, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
375+
static constexpr auto rule(mode_switch2, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
376+
static constexpr auto rule(mode_switch2, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
377+
static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
378+
static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push<ctll::anything>;
379+
365380
static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, create_number, number2, repeat_ab, ctll::term<'\x7D'>, mod>;
366381
static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push<repeat_at_least, ctll::anything, mod>;
367382

include/ctre/pcre_actions.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ template <size_t Counter> struct pcre_parameters {
1313
static constexpr size_t current_counter = Counter;
1414
};
1515

16-
template <typename Stack = ctll::list<>, typename Parameters = pcre_parameters<0>> struct pcre_context {
16+
template <typename Stack = ctll::list<>, typename Parameters = pcre_parameters<0>, typename Mode = ctll::list<>> struct pcre_context {
1717
using stack_type = Stack;
1818
using parameters_type = Parameters;
19+
using mode_list = Mode;
1920
static constexpr inline auto stack = stack_type();
2021
static constexpr inline auto parameters = parameters_type();
22+
static constexpr inline auto mode = mode_list();
2123
constexpr pcre_context() noexcept { }
2224
constexpr pcre_context(Stack, Parameters) noexcept { }
25+
constexpr pcre_context(Stack, Parameters, Mode) noexcept { }
2326
};
2427

2528
template <typename... Content, typename Parameters> pcre_context(ctll::list<Content...>, Parameters) -> pcre_context<ctll::list<Content...>, Parameters>;
@@ -46,6 +49,7 @@ struct pcre_actions {
4649
#include "actions/repeat.inc.hpp"
4750
#include "actions/sequence.inc.hpp"
4851
#include "actions/set.inc.hpp"
52+
#include "actions/mode.inc.hpp"
4953

5054
};
5155

single-header/ctre-unicode.hpp

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ struct pcre {
959959
struct l {};
960960
struct m {};
961961
struct mod {};
962+
struct mode_switch2 {};
962963
struct n {};
963964
struct number2 {};
964965
struct number {};
@@ -1018,6 +1019,10 @@ struct pcre {
10181019
struct make_range: ctll::action {};
10191020
struct make_relative_back_reference: ctll::action {};
10201021
struct make_sequence: ctll::action {};
1022+
struct mode_case_insensitive: ctll::action {};
1023+
struct mode_case_sensitive: ctll::action {};
1024+
struct mode_multiline: ctll::action {};
1025+
struct mode_singleline: ctll::action {};
10211026
struct negate_class_named: ctll::action {};
10221027
struct prepare_capture: ctll::action {};
10231028
struct push_assert_begin: ctll::action {};
@@ -1190,6 +1195,10 @@ struct pcre {
11901195
static constexpr auto rule(content_in_capture, ctll::term<'\x29'>) -> ctll::push<push_empty>;
11911196
static constexpr auto rule(content_in_capture, ctll::set<'*','+','?','\x7B','\x7D'>) -> ctll::reject;
11921197

1198+
static constexpr auto rule(d, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
1199+
static constexpr auto rule(d, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
1200+
static constexpr auto rule(d, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
1201+
static constexpr auto rule(d, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
11931202
static constexpr auto rule(d, ctll::term<'<'>) -> ctll::push<ctll::anything, o>;
11941203
static constexpr auto rule(d, ctll::term<':'>) -> ctll::push<ctll::anything, reset_capture, content_in_capture, ctll::term<'\x29'>>;
11951204
static constexpr auto rule(d, ctll::term<'>'>) -> ctll::push<ctll::anything, reset_capture, start_atomic, content_in_capture, make_atomic, ctll::term<'\x29'>>;
@@ -1288,6 +1297,12 @@ struct pcre {
12881297
static constexpr auto rule(mod, ctll::term<'+'>) -> ctll::push<ctll::anything, make_possessive>;
12891298
static constexpr auto rule(mod, ctll::set<'*','\x7B','\x7D'>) -> ctll::reject;
12901299

1300+
static constexpr auto rule(mode_switch2, ctll::term<'i'>) -> ctll::push<ctll::anything, mode_case_insensitive, mode_switch2>;
1301+
static constexpr auto rule(mode_switch2, ctll::term<'c'>) -> ctll::push<ctll::anything, mode_case_sensitive, mode_switch2>;
1302+
static constexpr auto rule(mode_switch2, ctll::term<'m'>) -> ctll::push<ctll::anything, mode_multiline, mode_switch2>;
1303+
static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push<ctll::anything, mode_singleline, mode_switch2>;
1304+
static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push<ctll::anything>;
1305+
12911306
static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push<ctll::anything, create_number, number2, repeat_ab, ctll::term<'\x7D'>, mod>;
12921307
static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push<repeat_at_least, ctll::anything, mod>;
12931308

@@ -1436,6 +1451,26 @@ struct flags {
14361451
(this->set_flag(Args{}), ...);
14371452
}
14381453

1454+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_insensitive) noexcept {
1455+
f.case_insensitive = true;
1456+
return f;
1457+
}
1458+
1459+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_case_sensitive) noexcept {
1460+
f.case_insensitive = false;
1461+
return f;
1462+
}
1463+
1464+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_singleline) noexcept {
1465+
f.multiline = false;
1466+
return f;
1467+
}
1468+
1469+
constexpr friend CTRE_FORCE_INLINE auto operator+(flags f, pcre::mode_multiline) noexcept {
1470+
f.multiline = true;
1471+
return f;
1472+
}
1473+
14391474
constexpr CTRE_FORCE_INLINE void set_flag(ctre::singleline) noexcept {
14401475
multiline = false;
14411476
}
@@ -1678,6 +1713,8 @@ struct assert_subject_end_line{ };
16781713
struct assert_line_begin { };
16791714
struct assert_line_end { };
16801715

1716+
template <typename> struct mode_switch { };
1717+
16811718
}
16821719

16831720
#endif
@@ -2059,13 +2096,16 @@ template <size_t Counter> struct pcre_parameters {
20592096
static constexpr size_t current_counter = Counter;
20602097
};
20612098

2062-
template <typename Stack = ctll::list<>, typename Parameters = pcre_parameters<0>> struct pcre_context {
2099+
template <typename Stack = ctll::list<>, typename Parameters = pcre_parameters<0>, typename Mode = ctll::list<>> struct pcre_context {
20632100
using stack_type = Stack;
20642101
using parameters_type = Parameters;
2102+
using mode_list = Mode;
20652103
static constexpr inline auto stack = stack_type();
20662104
static constexpr inline auto parameters = parameters_type();
2105+
static constexpr inline auto mode = mode_list();
20672106
constexpr pcre_context() noexcept { }
20682107
constexpr pcre_context(Stack, Parameters) noexcept { }
2108+
constexpr pcre_context(Stack, Parameters, Mode) noexcept { }
20692109
};
20702110

20712111
template <typename... Content, typename Parameters> pcre_context(ctll::list<Content...>, Parameters) -> pcre_context<ctll::list<Content...>, Parameters>;
@@ -2852,6 +2892,39 @@ template <auto V, auto B, auto A, typename... Ts, typename Parameters> static co
28522892

28532893
#endif
28542894

2895+
#ifndef CTRE__ACTIONS__MODE__HPP
2896+
#define CTRE__ACTIONS__MODE__HPP
2897+
2898+
// we need to reset counter and wrap Mode into mode_switch
2899+
template <typename Mode, typename... Ts, typename Parameters> static constexpr auto apply_mode(Mode, ctll::list<Ts...>, Parameters) {
2900+
return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, Parameters>{};
2901+
}
2902+
2903+
template <typename Mode, typename... Ts, size_t Id, size_t Counter> static constexpr auto apply_mode(Mode, ctll::list<capture_id<Id>, Ts...>, pcre_parameters<Counter>) {
2904+
return pcre_context<ctll::list<mode_switch<Mode>, Ts...>, pcre_parameters<Counter-1>>{};
2905+
}
2906+
2907+
// catch a semantic action into mode
2908+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_case_insensitive mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2909+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2910+
}
2911+
2912+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_case_sensitive mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2913+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2914+
}
2915+
2916+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_singleline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2917+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2918+
}
2919+
2920+
template <auto V, typename... Ts, typename Parameters> static constexpr auto apply(pcre::mode_multiline mode, ctll::term<V>,pcre_context<ctll::list<Ts...>, Parameters>) {
2921+
return apply_mode(mode, ctll::list<Ts...>{}, Parameters{});
2922+
}
2923+
2924+
// to properly reset capture
2925+
2926+
#endif
2927+
28552928
};
28562929

28572930
}
@@ -4768,6 +4841,12 @@ constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator curre
47684841
}
47694842
}
47704843

4844+
// switching modes
4845+
template <typename R, typename BeginIterator, typename Iterator, typename EndIterator, typename Mode, typename... Tail>
4846+
constexpr CTRE_FORCE_INLINE R evaluate(const BeginIterator begin, Iterator current, const EndIterator last, const flags & f, R captures, ctll::list<mode_switch<Mode>, Tail...>) noexcept {
4847+
return evaluate(begin, current, last, f + Mode{}, captures, ctll::list<Tail...>());
4848+
}
4849+
47714850
}
47724851

47734852
#endif

0 commit comments

Comments
 (0)