From 90ac938666e9ea1d6bb742fe1d170c040e8859de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= Date: Mon, 20 Aug 2018 23:43:27 +0200 Subject: [PATCH] Support for regex grammar (need to be checked). --- Makefile | 15 ++- future.cpp | 9 ++ gram.txt | 44 +++++++ grammar.txt | 0 include/ctre/fixed_string.hpp | 8 +- include/ctre/literals.hpp | 15 ++- include/ctre/parser.hpp | 51 +++++--- include/ctre/pcre.gram | 68 +++++++++++ include/ctre/pcre.hpp | 213 ++++++++++++++++++++++++++++++++++ test.cpp | 41 ++++--- 10 files changed, 429 insertions(+), 35 deletions(-) create mode 100644 future.cpp create mode 100644 gram.txt delete mode 100644 grammar.txt create mode 100644 include/ctre/pcre.gram create mode 100644 include/ctre/pcre.hpp diff --git a/Makefile b/Makefile index 1bd4788e..82c74788 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,11 @@ -.PHONY: default all clean +.PHONY: default all clean grammar default: all TARGETS := test.cpp +DESATOMAT := /www/root/desatomat/console/desatomat.php + CXXFLAGS := -std=c++17 -Iinclude -O3 -Wno-gnu-string-literal-operator-template #-fconcepts @@ -22,4 +24,13 @@ $(OBJECTS): %.o: %.cpp -include $(DEPEDENCY_FILES) clean: - rm -f $(TRUE_TARGETS) $(OBJECTS) $(DEPEDENCY_FILES) \ No newline at end of file + rm -f $(TRUE_TARGETS) $(OBJECTS) $(DEPEDENCY_FILES) + +grammar: include/ctre/pcre.hpp + +regrammar: + rm -f include/ctre/pcre.hpp + $(MAKE) grammar + +include/ctre/pcre.hpp: include/ctre/pcre.gram + $(DESATOMAT) --ll --q --input=include/ctre/pcre.gram --output=include/ctre/ --generator=cpp_ctre_v2 --cfg:fname=pcre.hpp --cfg:namespace=ctre --cfg:guard=CTRE__PCRE__HPP --cfg:grammar_name=pcre \ No newline at end of file diff --git a/future.cpp b/future.cpp new file mode 100644 index 00000000..42766717 --- /dev/null +++ b/future.cpp @@ -0,0 +1,9 @@ +#include + +std::optional match(std::string_view sv) { + if (auto match = regex<"^(name:[a-z]+):">(sv); match) { + return {true, match.get<"name">().first()}; + } else { + return std::nullopt; + } +} \ No newline at end of file diff --git a/gram.txt b/gram.txt new file mode 100644 index 00000000..79799621 --- /dev/null +++ b/gram.txt @@ -0,0 +1,44 @@ +backslash = {\\} +dot = {.} +dolar = {$} +open = {(} +close = {)} +questionmark = {?} +colon = {:} +sopen = {[} +sclose = {]} +plus = {+} +star = {*} +copen = {{} +cclose = {}} +num = {0,1,2,3,4,5,6,7,8,9} +comma = {\,} +pipe = {|} +caret = {^} +minus = {-} +hexdec = {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,a,b,c,d,e,f} +octal = {0,1,2,3,4,5,6,7} +nonspecial = {\,,-,0,1,2,3,4,5,6,7,8,9,:,A,B,C,D,E,F,X,],a,b,c,d,e,f,x} +nonspecial2 = {0,1,2,3,4,5,6,7,8,9,:,A,B,C,D,E,F,X,a,b,c,d,e,f,x} + +S -> epsilon | [addchar],other,,, | [addchar],nonspecial,,, | \\,,,, | dot,[any],,, | caret,[insert_begin],,, | dolar,[insert_end],,, | (,,,, | [,,,, +A -> [repeat_exactly],cclose | \,, +alt2 -> pipe, | epsilon +alt -> [addchar],other,,, | [addchar],nonspecial,,, | \\,,,, | dot,[any],,, | caret,[insert_begin],,, | dolar,[insert_end],,, | (,,,, | [,,,, +altB -> epsilon | [addchar],other,,, | [addchar],nonspecial,,, | \\,,,, | dot,[any],,, | caret,[insert_begin],,, | dolar,[insert_end],,, | (,,,, | [,,,, +B -> a | 0,[odigit],octal,[odigit],octal,[odigit],octal | x, | dot | sopen | copen | cclose | open | close | backslash | star | plus | questionmark | pipe | caret | dolar | d +C -> questionmark,colon,,close | [addchar],other,,,,[make_catch],close | [addchar],nonspecial,,,,[make_catch],close | \\,,,,,[make_catch],close | dot,[any],,,,[make_catch],close | caret,[insert_begin],,,,[make_catch],close | dolar,[insert_end],,,,[make_catch],close | (,,,,,[make_catch],close | [,,,,,[make_catch],close | [empty],[make_catch],close +D -> caret,[set_neg_start],,sclose | [addchar],other,,,sclose | [addchar],nonspecial2,,,sclose | [addchar],dot,,,sclose | \\,,,sclose +E -> b | a | 0,[odigit],octal,[odigit],octal,[odigit],octal | x, | dot | sopen | copen | cclose | open | close | backslash | star | plus | questionmark | pipe | caret | dolar +F -> [insert_range],other | [insert_range],nonspecial2 +G -> [hdigit],hexdec,[hdigit],hexdec | copen,[hdigit],hexdec,[hdigit],hexdec,[hdigit],hexdec,[hdigit],hexdec,cclose +H -> [repeat_at_least],cclose, | [digit],num,,[insert_number],[repeat_ab],cclose, +mod -> epsilon | questionmark | plus +number2 -> epsilon | [digit],num, +number -> [digit],num, +range -> epsilon | -, +repeat -> epsilon | plus,[plus], | star,[star], | questionmark,[optional], | {,, +set2 -> epsilon | [addchar],other,,[set_combine], | [addchar],nonspecial2,,[set_combine], | [addchar],dot,,[set_combine], | \\,,[set_combine], +set -> [addchar],other,, | [addchar],nonspecial2,, | [addchar],dot,, | \\,, +string2 -> epsilon | [addchar],other,, | [addchar],nonspecial,, | \\,,, | dot,[any],, | caret,[insert_begin],, | dolar,[insert_end],, | (,,, | [,,, + diff --git a/grammar.txt b/grammar.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/include/ctre/fixed_string.hpp b/include/ctre/fixed_string.hpp index 9eca00e4..067474b6 100644 --- a/include/ctre/fixed_string.hpp +++ b/include/ctre/fixed_string.hpp @@ -17,8 +17,12 @@ template class basic_fixed_string { constexpr size_t size() const noexcept { // if it's zero terminated string (from string literal) then size N - 1 - if (content[N-1] == '\0') return N - 1; - else return N; + if constexpr (N > 0) { + if (content[N-1] == '\0') return N - 1; + else return N; + } else { + return 0; + } } constexpr CharT operator[](size_t i) const noexcept { return content[i]; diff --git a/include/ctre/literals.hpp b/include/ctre/literals.hpp index 0a1d3e80..93da4bdf 100644 --- a/include/ctre/literals.hpp +++ b/include/ctre/literals.hpp @@ -4,6 +4,7 @@ #include "fixed_string.hpp" #include "parser.hpp" #include "grammar.hpp" +#include "pcre.hpp" namespace ctre { @@ -19,11 +20,23 @@ namespace literals { template static inline constexpr auto string = basic_fixed_string({input...}, std::make_index_sequence()); -template constexpr auto operator""_ctre() noexcept { +template constexpr auto operator""_expr() noexcept { return ctre::parser>::decide(); //return ctre::parser>::decide(math_grammar_quick::subject_type()); } +template constexpr auto operator""_ctre() noexcept { + auto expression = ctre::parser>::decide(ctre::empty_subject()); + static_assert(expression, "Regular expression is not correct."); + return expression; + //return ctre::parser>::decide(math_grammar_quick::subject_type()); +} + +template constexpr auto operator""_pcre_test() noexcept { + return bool(ctre::parser>::decide(ctre::empty_subject())); + //return ctre::parser>::decide(math_grammar_quick::subject_type()); +} + } // literals } // ctre diff --git a/include/ctre/parser.hpp b/include/ctre/parser.hpp index 9f968d90..5fe895aa 100644 --- a/include/ctre/parser.hpp +++ b/include/ctre/parser.hpp @@ -5,8 +5,8 @@ #define RULE static constexpr auto rule #define NONTERM(name) struct name { } -#define START_NONTERM(name) struct name { }; using start = name -#define SUBJECT_TYPE(name) using subject_type = name +#define START_NONTERM(name) struct name { }; using _start = name +#define SUBJECT_TYPE(name) using _subject_type = name namespace ctre { @@ -36,13 +36,14 @@ template struct set { template > constexpr set(term) noexcept; }; + template struct neg_set { constexpr neg_set() noexcept { }; //template constexpr set(term) noexcept requires ((Def == V) || ... || false); template > constexpr neg_set(term) noexcept; }; -template struct anything { +struct anything { constexpr anything() noexcept { }; template constexpr anything(term) noexcept; }; @@ -80,7 +81,7 @@ template struct IsAction { // everything else can be used as a nonterminal template struct augment_grammar: public Grammar { - using typename Grammar::start; + using typename Grammar::_start; using Grammar::rule; // Grammar rules should have same priority // default behaviour is reject if there is unexpected state @@ -89,24 +90,37 @@ template struct augment_grammar: public Grammar { // if there are two same terms on top of the stack and current input, you should move forward template static constexpr auto rule(term, term) -> pop_input; - //template static constexpr auto rule(range, term) -> pop_input requires ((A <= V) && (V <= B)); template > static constexpr auto rule(range, term) -> pop_input; - - //template static constexpr auto rule(set, term) -> pop_input requires ((V == Def) || ... || false); template > static constexpr auto rule(set, term) -> pop_input; + template static constexpr auto rule(anything, term) -> pop_input; + + template > static constexpr auto rule(neg_set, term) -> pop_input; + + // empty stack and empty input means we are accepting static constexpr auto rule(epsilon, epsilon) -> accept; }; struct empty_subject { }; -template struct parse_result { - bool value; - size_t steps; - Subject subject; - constexpr parse_result(bool value, size_t steps, Subject subject) noexcept: value{value}, steps{steps}, subject{subject} { } +template struct parse_result { + static constexpr bool correct{Value}; + //static constexpr size_t steps{Steps}; + Subject subject{}; + constexpr parse_result(Subject subject) noexcept: subject{subject} { } + constexpr operator bool() const noexcept { + return correct; + } +}; + +template struct parse_result { + static constexpr bool correct{Value}; + constexpr parse_result(empty_subject) noexcept { }; + constexpr operator bool() const noexcept { + return correct; + } }; //template struct parser { // in c++20 @@ -129,11 +143,14 @@ template struct parser { return epsilon(); } } + template static constexpr auto rule(A a,B b) { + return decltype(grammar().rule(a,b))(); + } template static constexpr auto get_move(Head head) { - return decltype(grammar().rule(Head(), current()))(); + return rule(Head(), current()); } - template static constexpr auto decide(const Subject subject = Subject{}) { - return decide(list(), 1, subject); + template static constexpr auto decide(const Subject subject = Subject{}) { + return decide(list(), 1, subject); } template static constexpr auto decide(Stack stack, unsigned step, Subject subject) { auto head_of_stack = head(stack); @@ -152,7 +169,7 @@ template struct parser { return decide(pop(stack), step+1, subject); } else { // else reject input - return parse_result(false, step, subject); + return parse_result(subject); } } else { // "else" branch because return type deduction is not working with standalone "if constexpr" @@ -163,7 +180,7 @@ template struct parser { return decide(pop_and_push_quick(m, stack), step+1, subject); } else if constexpr (IsExplicitlyConvertibleToBool::value) { // accept or reject state - return parse_result(bool(m), step, subject); + return parse_result(subject); } else { // move forward with parsing // if decltype(m) is pop_char then move a char forward diff --git a/include/ctre/pcre.gram b/include/ctre/pcre.gram new file mode 100644 index 00000000..d4eb2b6d --- /dev/null +++ b/include/ctre/pcre.gram @@ -0,0 +1,68 @@ +backslash={\\} +dot={.} +dolar={$} +open={(} +close={)} +questionmark={?} +colon={:} +sopen={[} +sclose={]} +plus={+} +star={*} +copen={\{} +cclose={\}} +num={0,1,2,3,4,5,6,7,8,9} +comma={\,} +pipe={|} +caret={^} +minus={-} + +hexdec={0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,A,B,C,D,E,F} +octal={0,1,2,3,4,5,6,7} +nonspecial={a,b,c,d,e,f,A,B,C,D,E,F,x,X,:,],0,1,2,3,4,5,6,7,8,9,\,,-} +nonspecial2={a,b,c,d,e,f,A,B,C,D,E,F,x,X,:,0,1,2,3,4,5,6,7,8,9} + +S-> | epsilon + +alt->, +altB->, | epsilon,[empty] +alt2->pipe,,[alternate] | epsilon + +string->, +string2->,,[create_sequence] | epsilon + +atom_repeat->, + +atom->||| + +repeat->epsilon | plus,[plus],|star,[star],|questionmark,[optional], +repeat->copen,,[repeat_exactly],cclose +repeat->copen,,comma,[repeat_at_least],cclose, +repeat->copen,,comma,,[repeat_ab],cclose, +mod->epsilon | questionmark,[nongreedy] | plus,[possessive] + +number->[digit],num,,[insert_number] +number2->epsilon | [digit],num, + +block->open,,[make_catch],close | open,questionmark,colon,,close + +character_class->sopen,[set_start],,sclose,[set_finish]|sopen,caret,[set_neg_start],,sclose,[set_finish] +set->, +set2->,[set_combine],|epsilon + +setitem->[addchar],other, | [addchar],nonspecial2, | [addchar],dot, +range->epsilon|minus,[insert_range],other|minus,[insert_range],nonspecial2 + +setitem->backslash, | backslash,b,[backb] + +backslash->[addchar], +special->dot|sopen|copen|cclose|open|close|backslash|star|plus|questionmark|pipe|caret|dolar + +backslash->a,[backa] +backslash->x,[hdigit],hexdec,[hdigit],hexdec,[hexdec2] +backslash->x,copen,[hdigit],hexdec,[hdigit],hexdec,[hdigit],hexdec,[hdigit],hexdec,cclose,[hexdec4] +backslash->0,[odigit],octal,[odigit],octal,[odigit],octal,[octal3] +backslash_char->d,[class_digit] + +character->[addchar],other | [addchar],nonspecial | dot,[any] | backslash, | backslash, +nonchar->caret,[insert_begin] | dolar,[insert_end] diff --git a/include/ctre/pcre.hpp b/include/ctre/pcre.hpp new file mode 100644 index 00000000..f40aaff5 --- /dev/null +++ b/include/ctre/pcre.hpp @@ -0,0 +1,213 @@ +#ifndef CTRE__PCRE__HPP +#define CTRE__PCRE__HPP + +// THIS FILE WAS GENERATED BY DESATOMAT TOOL, DO NOT MODIFY THIS FILE + +namespace ctre { + +struct pcre { + +struct _subject_type {}; + + +// NONTERMINALS: + struct s {}; using _start = s; + struct a {}; + struct alt2 {}; + struct alt {}; + struct altb {}; + struct atom {}; + struct atom_repeat {}; + struct b {}; + struct backslash {}; + struct backslash_char {}; + struct block {}; + struct c {}; + struct character {}; + struct character_class {}; + struct d {}; + struct e {}; + struct f {}; + struct g {}; + struct h {}; + struct mod {}; + struct nonchar {}; + struct number2 {}; + struct number {}; + struct range {}; + struct repeat {}; + struct set2 {}; + struct set {}; + struct setitem {}; + struct special {}; + struct string2 {}; + struct string {}; + +// 'action' types: + struct addchar: ctre::action {}; + struct alternate: ctre::action {}; + struct any: ctre::action {}; + struct backa: ctre::action {}; + struct backb: ctre::action {}; + struct class_digit: ctre::action {}; + struct create_sequence: ctre::action {}; + struct digit: ctre::action {}; + struct empty: ctre::action {}; + struct hdigit: ctre::action {}; + struct hexdec2: ctre::action {}; + struct hexdec4: ctre::action {}; + struct insert_begin: ctre::action {}; + struct insert_end: ctre::action {}; + struct insert_number: ctre::action {}; + struct insert_range: ctre::action {}; + struct make_catch: ctre::action {}; + struct nongreedy: ctre::action {}; + struct octal3: ctre::action {}; + struct odigit: ctre::action {}; + struct optional: ctre::action {}; + struct plus: ctre::action {}; + struct possessive: ctre::action {}; + struct repeat_ab: ctre::action {}; + struct repeat_at_least: ctre::action {}; + struct repeat_exactly: ctre::action {}; + struct set_combine: ctre::action {}; + struct set_finish: ctre::action {}; + struct set_neg_start: ctre::action {}; + struct star: ctre::action {}; + +// (q)LL1 function: + using _others = ctre::neg_set<'$','(',')','*','+',',','-','.',':','?','A','B','C','D','E','F','X','[','\\',']','^','0','a','b','c','d','e','f','x','{','|','}','1','2','3','4','5','6','7','8','9'>; + static constexpr auto rule(s, ctre::epsilon) -> ctre::epsilon; //1 + static constexpr auto rule(s, ctre::set<',','-',':','A','B','C','D','E','F','X',']','a','b','c','d','e','f','x','0','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //28 + static constexpr auto rule(s, _others) -> ctre::push; //1 + static constexpr auto rule(s, ctre::term<'.'>) -> ctre::push; //1 + static constexpr auto rule(s, ctre::term<'\\'>) -> ctre::push; //1 + static constexpr auto rule(s, ctre::term<'('>) -> ctre::push; //1 + static constexpr auto rule(s, ctre::term<'['>) -> ctre::push; //1 + static constexpr auto rule(s, ctre::term<'^'>) -> ctre::push; //1 + static constexpr auto rule(s, ctre::term<'$'>) -> ctre::push; //1 + static constexpr auto rule(s, ctre::set<')','*','+','?','{','|','}'>) -> ctre::reject; //7 + + static constexpr auto rule(a, ctre::term<','>) -> ctre::push; //1 + static constexpr auto rule(a, ctre::term<'}'>) -> ctre::push; //1 + + static constexpr auto rule(alt2, ctre::term<')'>) -> ctre::epsilon; //1 + static constexpr auto rule(alt2, ctre::epsilon) -> ctre::epsilon; //1 + static constexpr auto rule(alt2, ctre::term<'|'>) -> ctre::push; //1 + + static constexpr auto rule(alt, ctre::set<',','-',':','A','B','C','D','E','F','X',']','a','b','c','d','e','f','x','0','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //28 + static constexpr auto rule(alt, _others) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::term<'.'>) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::term<'\\'>) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::term<'('>) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::term<'['>) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::term<'^'>) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::term<'$'>) -> ctre::push; //1 + static constexpr auto rule(alt, ctre::set<')','*','+','?','{','|','}'>) -> ctre::reject; //7 + + static constexpr auto rule(altb, ctre::set<',','-',':','A','B','C','D','E','F','X',']','a','b','c','d','e','f','x','0','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //28 + static constexpr auto rule(altb, _others) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<'.'>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<'\\'>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<'('>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<'['>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<'^'>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<'$'>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::term<')'>) -> ctre::push; //1 + static constexpr auto rule(altb, ctre::set<'*','+','?','{','|','}'>) -> ctre::reject; //6 + + static constexpr auto rule(b, ctre::term<'a'>) -> ctre::push; //1 + static constexpr auto rule(b, ctre::term<'d'>) -> ctre::push; //1 + static constexpr auto rule(b, ctre::term<'x'>) -> ctre::push; //1 + static constexpr auto rule(b, ctre::term<'0'>) -> ctre::push, odigit, ctre::set<'0','1','2','3','4','5','6','7'>, odigit, ctre::set<'0','1','2','3','4','5','6','7'>, octal3>; //1 + static constexpr auto rule(b, ctre::set<'$','(',')','*','+','.','?','[','\\','^','{','|','}'>) -> ctre::push; //13 + + static constexpr auto rule(c, ctre::set<',','-',':','A','B','C','D','E','F','X',']','a','b','c','d','e','f','x','0','1','2','3','4','5','6','7','8','9'>) -> ctre::push>; //28 + static constexpr auto rule(c, _others) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<'.'>) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<'\\'>) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<'('>) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<'?'>) -> ctre::push, altb, ctre::term<')'>>; //1 + static constexpr auto rule(c, ctre::term<'['>) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<'^'>) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<'$'>) -> ctre::push>; //1 + static constexpr auto rule(c, ctre::term<')'>) -> ctre::push; //1 + static constexpr auto rule(c, ctre::set<'*','+','{','|','}'>) -> ctre::reject; //5 + + static constexpr auto rule(d, ctre::set<'0','.',':','A','B','C','D','E','F','X','a','b','c','d','e','f','x','1','2','3','4','5','6','7','8','9'>) -> ctre::push, set_finish>; //26 + static constexpr auto rule(d, _others) -> ctre::push, set_finish>; //1 + static constexpr auto rule(d, ctre::term<'\\'>) -> ctre::push, set_finish>; //1 + static constexpr auto rule(d, ctre::term<'^'>) -> ctre::push, set_finish>; //1 + static constexpr auto rule(d, ctre::set<'$','(',')','*','+',',','-','?','[',']','{','|','}'>) -> ctre::reject; //13 + + static constexpr auto rule(e, ctre::term<'a'>) -> ctre::push; //1 + static constexpr auto rule(e, ctre::term<'b'>) -> ctre::push; //1 + static constexpr auto rule(e, ctre::term<'x'>) -> ctre::push; //1 + static constexpr auto rule(e, ctre::term<'0'>) -> ctre::push, odigit, ctre::set<'0','1','2','3','4','5','6','7'>, odigit, ctre::set<'0','1','2','3','4','5','6','7'>, octal3>; //1 + static constexpr auto rule(e, ctre::set<'$','(',')','*','+','.','?','[','\\','^','{','|','}'>) -> ctre::push; //13 + + static constexpr auto rule(f, ctre::set<'0',':','A','B','C','D','E','F','X','a','b','c','d','e','f','x','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //25 + static constexpr auto rule(f, _others) -> ctre::push; //1 + static constexpr auto rule(f, ctre::set<'$','(',')','*','+',',','-','.','?','[','\\',']','^','{','|','}'>) -> ctre::reject; //16 + + static constexpr auto rule(g, ctre::term<'{'>) -> ctre::push, hdigit, ctre::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, hdigit, ctre::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, hdigit, ctre::set<'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f'>, ctre::term<'}'>, hexdec4>; //1 + static constexpr auto rule(g, ctre::set<'0','A','B','C','D','E','F','a','b','c','d','e','f','1','2','3','4','5','6','7','8','9'>) -> ctre::push, hexdec2>; //22 + + static constexpr auto rule(h, ctre::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctre::push, mod>; //10 + static constexpr auto rule(h, ctre::term<'}'>) -> ctre::push; //1 + + static constexpr auto rule(mod, ctre::set<'$','(',')',',','-','.',':','A','B','C','D','E','F','X','[','\\',']','^','a','b','c','d','e','f','x','|','0','1','2','3','4','5','6','7','8','9'>) -> ctre::epsilon; //36 + static constexpr auto rule(mod, ctre::epsilon) -> ctre::epsilon; //1 + static constexpr auto rule(mod, _others) -> ctre::epsilon; //1 + static constexpr auto rule(mod, ctre::term<'?'>) -> ctre::push; //1 + static constexpr auto rule(mod, ctre::term<'+'>) -> ctre::push; //1 + static constexpr auto rule(mod, ctre::set<'*','{','}'>) -> ctre::reject; //3 + + static constexpr auto rule(number2, ctre::set<',','}'>) -> ctre::epsilon; //2 + static constexpr auto rule(number2, ctre::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //10 + + static constexpr auto rule(number, ctre::set<'0','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //10 + + static constexpr auto rule(range, ctre::set<'.',':','0','A','B','C','D','E','F','X','\\',']','a','b','c','d','e','f','x','1','2','3','4','5','6','7','8','9'>) -> ctre::epsilon; //28 + static constexpr auto rule(range, ctre::epsilon) -> ctre::epsilon; //1 + static constexpr auto rule(range, _others) -> ctre::epsilon; //1 + static constexpr auto rule(range, ctre::term<'-'>) -> ctre::push; //1 + static constexpr auto rule(range, ctre::set<'$','(',')','*','+',',','?','[','^','{','|','}'>) -> ctre::reject; //12 + + static constexpr auto rule(repeat, ctre::set<'$','(',')',',','-','.',':','A','B','C','D','E','F','X','[','\\',']','^','a','b','c','d','e','f','x','|','0','1','2','3','4','5','6','7','8','9'>) -> ctre::epsilon; //36 + static constexpr auto rule(repeat, ctre::epsilon) -> ctre::epsilon; //1 + static constexpr auto rule(repeat, _others) -> ctre::epsilon; //1 + static constexpr auto rule(repeat, ctre::term<'{'>) -> ctre::push; //1 + static constexpr auto rule(repeat, ctre::term<'?'>) -> ctre::push; //1 + static constexpr auto rule(repeat, ctre::term<'+'>) -> ctre::push; //1 + static constexpr auto rule(repeat, ctre::term<'*'>) -> ctre::push; //1 + static constexpr auto rule(repeat, ctre::term<'}'>) -> ctre::reject; //1 + + static constexpr auto rule(set2, ctre::term<']'>) -> ctre::epsilon; //1 + static constexpr auto rule(set2, ctre::set<'0','.',':','A','B','C','D','E','F','X','a','b','c','d','e','f','x','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //26 + static constexpr auto rule(set2, _others) -> ctre::push; //1 + static constexpr auto rule(set2, ctre::term<'\\'>) -> ctre::push; //1 + static constexpr auto rule(set2, ctre::set<'$','(',')','*','+',',','-','?','[','^','{','|','}'>) -> ctre::reject; //13 + + static constexpr auto rule(set, ctre::set<'0','.',':','A','B','C','D','E','F','X','a','b','c','d','e','f','x','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //26 + static constexpr auto rule(set, _others) -> ctre::push; //1 + static constexpr auto rule(set, ctre::term<'\\'>) -> ctre::push; //1 + static constexpr auto rule(set, ctre::set<'$','(',')','*','+',',','-','?','[',']','^','{','|','}'>) -> ctre::reject; //14 + + static constexpr auto rule(string2, ctre::set<')','|'>) -> ctre::epsilon; //2 + static constexpr auto rule(string2, ctre::epsilon) -> ctre::epsilon; //1 + static constexpr auto rule(string2, ctre::set<',','-',':','A','B','C','D','E','F','X',']','a','b','c','d','e','f','x','0','1','2','3','4','5','6','7','8','9'>) -> ctre::push; //28 + static constexpr auto rule(string2, _others) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::term<'.'>) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::term<'\\'>) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::term<'('>) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::term<'['>) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::term<'^'>) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::term<'$'>) -> ctre::push; //1 + static constexpr auto rule(string2, ctre::set<'*','+','?','{','}'>) -> ctre::reject; //5 + +}; + +} + +#endif //CTRE__PCRE__HPP diff --git a/test.cpp b/test.cpp index e5f020c2..a4c66a19 100644 --- a/test.cpp +++ b/test.cpp @@ -1,31 +1,46 @@ #include #include #include "ctre/type-stack.hpp" +#include "ctre/pcre.hpp" + +template void accept(Expr) { + static_assert(std::declval().value); +} + +template void reject(Expr) { + static_assert(!std::declval().value); +} template void foo(); template void info(Expr x) { printf("%s\n", x.value?"accept":"reject"); printf("steps = %zu\n", x.steps); - printf("variables = %zu\n", x.subject.variables); - printf("constants = %u\n", x.subject.constants); - x.subject.print([](auto t){ - printf("<%c> ",t.value); - }); + //printf("variables = %zu\n", x.subject.variables); + //printf("constants = %u\n", x.subject.constants); + //x.subject.print([](auto t){ + // printf("<%c> ",t.value); + //}); printf("\n\n"); } int main() { using namespace ctre::literals; - using out = decltype( - ctre::augment_grammar::rule(ctre::math_grammar::E(), ctre::term<'c'>()) - ); - - info("(x+y+z)*(x+y+a)"_ctre); - info("(x+y+z)*(x+y+a)+(x+y+z)*(x+y)"_ctre); - info("(x+y+z)*(x+y+a)+(x+y+z)*(x+y)+(x+y+z)*(x+y)"_ctre); - info("(x+y+z)*(x+y+a)+(x+y+z)*(x+y)+(x+y+z)*(x+y)+(x+y+z)*(x+y)"_ctre); + static_assert( ""_pcre_test); + static_assert( "^"_pcre_test); + static_assert( "$"_pcre_test); + static_assert( "^$"_pcre_test); + static_assert( "a{1}"_pcre_test); + static_assert( "a{1,}"_pcre_test); + static_assert( "a{1,2}"_pcre_test); + "a{,2}"_ctre; + static_assert( "a{10}"_pcre_test); + static_assert( "a{10,}"_pcre_test); + static_assert( "(a{10,20})+"_pcre_test); + static_assert( "[abcd]+"_pcre_test); + static_assert( "(X|[abc]*)+"_pcre_test); + static_assert( "a+"_pcre_test); } \ No newline at end of file