diff --git a/source/regex.c b/source/regex.c index 1c1f7ea..449e1df 100644 --- a/source/regex.c +++ b/source/regex.c @@ -48,6 +48,15 @@ typedef struct { int to; } offshoot_t; +typedef struct { + bool * do_catch; + bool * is_negative; + int * state; + int * width; + char * whitelist; + regex_t * regex; +} compiler_state; + // ---------------------------------- @@ -317,19 +326,24 @@ static bool catch_(const regex_t * const regex, #define HALT_AND_CATCH_FIRE -1 -#define HOOK_ALL(from, str, to) do { \ - int hook_to = (is_negative) ? -1 : state + to; \ - for (char * s = str; *s != '\0'; s++) { \ - vector_push(®ex->delta_table, \ - &(delta_t){state + from, *s, hook_to, width} \ - ); \ - } \ - if (do_catch || is_negative) { \ - vector_push(®ex->catch_table, \ - &(offshoot_t){state + from, hook_to} \ - ); \ - } \ -} while (0) +void HOOK_ALL( int from, + const char * const str, + int to, + compiler_state * cs) { + + int hook_to = (*cs->is_negative) ? HALT_AND_CATCH_FIRE : *cs->state + to; + + for (const char * s = str; *s != '\0'; s++) { + vector_push(&cs->regex->delta_table, + &(delta_t){*cs->state + from, *s, hook_to, *cs->width} + ); + } + if (cs->do_catch || cs->is_negative) { + vector_push(&cs->regex->catch_table, + &(offshoot_t){*cs->state + from, hook_to} + ); + } +} #define EAT(n) do { \ s += n; \ @@ -343,10 +357,20 @@ regex_t * regex_compile(const char * const pattern) { int state = 0; - char whitelist[64]; bool do_catch; bool is_negative; int width; + char whitelist[64]; + + compiler_state cs = { + .do_catch = &do_catch, + .is_negative = &is_negative, + .state = &state, + .width = &width, + .whitelist = whitelist, + .regex = regex, + }; + for (const char * s = pattern; *s != '\00';) { // Get token assert(!is_quantifier(*pattern) && "Pattern starts with quantifier."); @@ -385,21 +409,21 @@ regex_t * regex_compile(const char * const pattern) { switch (*s) { case '=': case '?': { - HOOK_ALL(0, whitelist, +1); + HOOK_ALL(0, whitelist, +1, &cs); EAT(1); } break; case '*': { - HOOK_ALL(0, whitelist, 0); + HOOK_ALL(0, whitelist, 0, &cs); EAT(1); } break; case '+': { - HOOK_ALL(0, whitelist, +1); + HOOK_ALL(0, whitelist, +1, &cs); state += 1; - HOOK_ALL(0, whitelist, 0); + HOOK_ALL(0, whitelist, 0, &cs); EAT(1); } break; default: { // Literal - HOOK_ALL(0, whitelist, +1); + HOOK_ALL(0, whitelist, +1, &cs); state += 1; } break; }