diff --git a/README.md b/README.md index d0bbdf31..e609ef97 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ctre::match<"REGEX">(subject); // C++20 * Matching * Searching (`search` or `starts_with`) -* Capturing content (named captures are supported too) +* Capturing content (named captures are supported too, but only with syntax `(?...)`) * Back-Reference (\g{N} syntax, and \1...\9 syntax too) * Multiline support (with `multi_`) functions * Unicode properties and UTF-8 support diff --git a/include/ctre/pcre.gram b/include/ctre/pcre.gram index 74f60707..705c126e 100644 --- a/include/ctre/pcre.gram +++ b/include/ctre/pcre.gram @@ -34,8 +34,9 @@ alphanum_characters={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 set_control_chars={:,],-} capture_control_chars={<} -S-> | epsilon,[push_empty] | pipe,[push_empty],,[make_alternate] +S-> | epsilon,[push_empty] | pipe,[push_empty],,[make_alternate] +opt_content->epsilon,[push_empty]| content->, content_in_capture->, | epsilon,[push_empty] content_in_capture->pipe,[push_empty],,[make_alternate] diff --git a/include/ctre/pcre.hpp b/include/ctre/pcre.hpp index 840db7c0..87679b97 100644 --- a/include/ctre/pcre.hpp +++ b/include/ctre/pcre.hpp @@ -20,7 +20,6 @@ struct pcre { struct c {}; struct class_named_name {}; struct content2 {}; - struct content {}; struct content_in_capture {}; struct content_or_empty {}; struct d {}; @@ -40,6 +39,7 @@ struct pcre { struct number2 {}; struct number {}; struct o {}; + struct opt_content {}; struct p {}; struct property_name2 {}; struct property_name {}; @@ -149,7 +149,7 @@ struct pcre { static constexpr auto rule(s, ctll::set<'!',',','-','/','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'>) -> ctll::push; static constexpr auto rule(s, _others) -> ctll::push; static constexpr auto rule(s, ctll::term<'.'>) -> ctll::push; - static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; static constexpr auto rule(s, ctll::epsilon) -> ctll::push; static constexpr auto rule(s, ctll::set<'\x29','*','+','?','\x7B','\x7D'>) -> ctll::reject; @@ -251,16 +251,6 @@ struct pcre { static constexpr auto rule(content2, ctll::epsilon) -> ctll::epsilon; static constexpr auto rule(content2, ctll::term<'|'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'\\'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'['>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'\x28'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'^'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'$'>) -> ctll::push; - static constexpr auto rule(content, ctll::set<'!',',','-','/','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'>) -> ctll::push; - static constexpr auto rule(content, _others) -> ctll::push; - static constexpr auto rule(content, ctll::term<'.'>) -> ctll::push; - static constexpr auto rule(content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; - static constexpr auto rule(content_in_capture, ctll::term<'\\'>) -> ctll::push; static constexpr auto rule(content_in_capture, ctll::term<'['>) -> ctll::push; static constexpr auto rule(content_in_capture, ctll::term<'\x28'>) -> ctll::push; @@ -392,7 +382,7 @@ struct pcre { static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push; static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push; - static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; + static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push; static constexpr auto rule(number2, ctll::set<',','\x7D'>) -> ctll::epsilon; @@ -404,6 +394,17 @@ struct pcre { static constexpr auto rule(o, ctll::term<'!'>) -> ctll::push>; static constexpr auto rule(o, ctll::term<'='>) -> ctll::push>; + static constexpr auto rule(opt_content, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'$'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::set<'!',',','-','/','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'>) -> ctll::push; + static constexpr auto rule(opt_content, _others) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::epsilon) -> ctll::push; + static constexpr auto rule(opt_content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; + static constexpr auto rule(p, ctll::term<'p'>) -> ctll::push, ctll::term<'a'>, class_named_alpha>; static constexpr auto rule(p, ctll::term<'n'>) -> ctll::push, ctll::term<'m'>, class_named_alnum>; diff --git a/single-header/ctre-unicode.hpp b/single-header/ctre-unicode.hpp index 3a0e631c..3aa248ae 100644 --- a/single-header/ctre-unicode.hpp +++ b/single-header/ctre-unicode.hpp @@ -970,7 +970,6 @@ struct pcre { struct c {}; struct class_named_name {}; struct content2 {}; - struct content {}; struct content_in_capture {}; struct content_or_empty {}; struct d {}; @@ -990,6 +989,7 @@ struct pcre { struct number2 {}; struct number {}; struct o {}; + struct opt_content {}; struct p {}; struct property_name2 {}; struct property_name {}; @@ -1099,7 +1099,7 @@ struct pcre { static constexpr auto rule(s, ctll::set<'!',',','-','/','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'>) -> ctll::push; static constexpr auto rule(s, _others) -> ctll::push; static constexpr auto rule(s, ctll::term<'.'>) -> ctll::push; - static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; static constexpr auto rule(s, ctll::epsilon) -> ctll::push; static constexpr auto rule(s, ctll::set<'\x29','*','+','?','\x7B','\x7D'>) -> ctll::reject; @@ -1201,16 +1201,6 @@ struct pcre { static constexpr auto rule(content2, ctll::epsilon) -> ctll::epsilon; static constexpr auto rule(content2, ctll::term<'|'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'\\'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'['>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'\x28'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'^'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'$'>) -> ctll::push; - static constexpr auto rule(content, ctll::set<'!',',','-','/','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'>) -> ctll::push; - static constexpr auto rule(content, _others) -> ctll::push; - static constexpr auto rule(content, ctll::term<'.'>) -> ctll::push; - static constexpr auto rule(content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; - static constexpr auto rule(content_in_capture, ctll::term<'\\'>) -> ctll::push; static constexpr auto rule(content_in_capture, ctll::term<'['>) -> ctll::push; static constexpr auto rule(content_in_capture, ctll::term<'\x28'>) -> ctll::push; @@ -1342,7 +1332,7 @@ struct pcre { static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push; static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push; - static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; + static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push; static constexpr auto rule(number2, ctll::set<',','\x7D'>) -> ctll::epsilon; @@ -1354,6 +1344,17 @@ struct pcre { static constexpr auto rule(o, ctll::term<'!'>) -> ctll::push>; static constexpr auto rule(o, ctll::term<'='>) -> ctll::push>; + static constexpr auto rule(opt_content, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'$'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::set<'!',',','-','/','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'>) -> ctll::push; + static constexpr auto rule(opt_content, _others) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::epsilon) -> ctll::push; + static constexpr auto rule(opt_content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; + static constexpr auto rule(p, ctll::term<'p'>) -> ctll::push, ctll::term<'a'>, class_named_alpha>; static constexpr auto rule(p, ctll::term<'n'>) -> ctll::push, ctll::term<'m'>, class_named_alnum>; @@ -5463,7 +5464,7 @@ namespace std::ranges { namespace ctre { -template struct regular_expression; +CTRE_EXPORT template struct regular_expression; struct zero_terminated_string_end_iterator { // this is here only because I want to support std::make_reverse_iterator diff --git a/single-header/ctre.hpp b/single-header/ctre.hpp index afc753f3..096e4114 100644 --- a/single-header/ctre.hpp +++ b/single-header/ctre.hpp @@ -967,7 +967,6 @@ struct pcre { struct c {}; struct class_named_name {}; struct content2 {}; - struct content {}; struct content_in_capture {}; struct content_or_empty {}; struct d {}; @@ -987,6 +986,7 @@ struct pcre { struct number2 {}; struct number {}; struct o {}; + struct opt_content {}; struct p {}; struct property_name2 {}; struct property_name {}; @@ -1096,7 +1096,7 @@ struct pcre { static constexpr auto rule(s, ctll::set<'!',',','-','/','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'>) -> ctll::push; static constexpr auto rule(s, _others) -> ctll::push; static constexpr auto rule(s, ctll::term<'.'>) -> ctll::push; - static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; + static constexpr auto rule(s, ctll::term<'|'>) -> ctll::push; static constexpr auto rule(s, ctll::epsilon) -> ctll::push; static constexpr auto rule(s, ctll::set<'\x29','*','+','?','\x7B','\x7D'>) -> ctll::reject; @@ -1198,16 +1198,6 @@ struct pcre { static constexpr auto rule(content2, ctll::epsilon) -> ctll::epsilon; static constexpr auto rule(content2, ctll::term<'|'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'\\'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'['>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'\x28'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'^'>) -> ctll::push; - static constexpr auto rule(content, ctll::term<'$'>) -> ctll::push; - static constexpr auto rule(content, ctll::set<'!',',','-','/','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'>) -> ctll::push; - static constexpr auto rule(content, _others) -> ctll::push; - static constexpr auto rule(content, ctll::term<'.'>) -> ctll::push; - static constexpr auto rule(content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; - static constexpr auto rule(content_in_capture, ctll::term<'\\'>) -> ctll::push; static constexpr auto rule(content_in_capture, ctll::term<'['>) -> ctll::push; static constexpr auto rule(content_in_capture, ctll::term<'\x28'>) -> ctll::push; @@ -1339,7 +1329,7 @@ struct pcre { static constexpr auto rule(mode_switch2, ctll::term<'s'>) -> ctll::push; static constexpr auto rule(mode_switch2, ctll::term<'\x29'>) -> ctll::push; - static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; + static constexpr auto rule(n, ctll::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctll::push, mod>; static constexpr auto rule(n, ctll::term<'\x7D'>) -> ctll::push; static constexpr auto rule(number2, ctll::set<',','\x7D'>) -> ctll::epsilon; @@ -1351,6 +1341,17 @@ struct pcre { static constexpr auto rule(o, ctll::term<'!'>) -> ctll::push>; static constexpr auto rule(o, ctll::term<'='>) -> ctll::push>; + static constexpr auto rule(opt_content, ctll::term<'\\'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'['>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'\x28'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'^'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'$'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::set<'!',',','-','/','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'>) -> ctll::push; + static constexpr auto rule(opt_content, _others) -> ctll::push; + static constexpr auto rule(opt_content, ctll::term<'.'>) -> ctll::push; + static constexpr auto rule(opt_content, ctll::epsilon) -> ctll::push; + static constexpr auto rule(opt_content, ctll::set<'\x29','*','+','?','\x7B','|','\x7D'>) -> ctll::reject; + static constexpr auto rule(p, ctll::term<'p'>) -> ctll::push, ctll::term<'a'>, class_named_alpha>; static constexpr auto rule(p, ctll::term<'n'>) -> ctll::push, ctll::term<'m'>, class_named_alnum>; diff --git a/tests/parsing.cpp b/tests/parsing.cpp index 6e2b8e3b..96de275d 100644 --- a/tests/parsing.cpp +++ b/tests/parsing.cpp @@ -23,6 +23,9 @@ static_assert(CTRE_TEST(".")); static_assert(CTRE_TEST("a")); static_assert(CTRE_TEST("ab")); static_assert(CTRE_TEST("a|b")); +static_assert(CTRE_TEST("a|")); +static_assert(CTRE_TEST("|b")); +static_assert(CTRE_TEST("|")); static_assert(CTRE_TEST("n")); // repetation