Compile-time regex matcher using constexpr
With my growing constexpr fascination, I thought of using it for something that would be really hard using template meta-programs. How about implementing a compile-time regular expression matcher? Fortunately, a simple regular expression matcher has already been written by Rob Pike. I just rewrote it using constexpr: single return statement in functions, no modifications to the parameters, abundant ternery operators, and recursion. Here we go...constexpr int match_c(const char *regexp, const char *text); constexpr int matchhere_c(const char *regexp, const char *text); constexpr int matchstar_c(int c, const char *regexp, const char *text); constexpr int matchend_c(const char * regexp, const char * text); constexpr int matchend_c(const char * regexp, const char * text) { return matchhere_c(regexp, text) ? 1 : (*text == '\0') ? 0 : matchend_c(regexp, text+1); } constexpr int match_c(const char *regexp, const char *text) { return (regexp[0] == '^') ? matchhere_c(regexp+1, text) : matchend_c(regexp, text); } /* matchhere: search for regexp at beginning of text */ constexpr int matchhere_c(const char *regexp, const char *text) { return (regexp[0] == '\0') ? 1 : (regexp[1] == '*') ? matchstar_c(regexp[0], regexp+2, text) : (regexp[0] == '$' && regexp[1] == '\0') ? (*text == '\0') : (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) ? matchhere_c(regexp+1, text+1) : 0; } /* matchstar: search for c*regexp at beginning of text */ constexpr int matchstar_c(int c, const char * regexp, const char *text) { return matchhere_c(regexp, text) ? 1 : (*text != '\0' && (*text == c || c == '.')) ? matchstar_c(c, regexp, text+1) : 0; } #define TO_STR_IMPL(R) #R #define TO_STR(R) TO_STR_IMPL(R) int main(void) { static_assert(match_c(TO_STR(REGEX), TO_STR(TEXT)), "..."); return 0; }
To compile it, as of today, you need g++ 4.6 or better. You've to pass REGEX and TEXT as #defines while compilation. For instance, -D REGEX=o$ -D TEXT=Foo It matches!
I used two macros TO_STR and To_STR_IMPL to convert the REGEX and TEXT into string literals. #R is basically using the preprocessor stringification technique. For some reason I need two separate TO_STR macros for TEXT substitution and stringification. Seems like the gcc preprocessor can't do those two things in a single macro.
Have fun!