regex.c 2.07 KB
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>

#include "regex.h"

range_t*_regexp_match(
    char *whole_regex, char *regex, char *line, 
    bool caret, bool dollar, 
    size_t index, size_t start, size_t len) {
    if ((regex[0] == '\0' && line[0] == '\0') || (regex[0] == '\0' && !dollar)) {
        range_t *result = malloc(sizeof(range_t));
        *result = (range_t){.start=start, .end=len + start};
        return result;
    }
    if (regex[0] == '\0' || line[0] == '\0') {
        return NULL;
    }
    if (regex[1] == '*') {
        if (regex[0] == line[0]) {
            range_t *end = _regexp_match(whole_regex, regex + 2, line + 1, dollar, index + 1, start, len + 1);
            if (end) {
                return end;
            }
            return _regexp_match(whole_regex, regex, line + 1, dollar, index + 1, start, len + 1);
        } 
        if (!caret) {
            range_t *restart = _regexp_match(whole_regex, whole_regex, line + 1, dollar, index + 1, index + 1, 0);
            if (restart) {
                return restart;
            }
        }
        return _regexp_match(whole_regex, regex + 2, line, dollar, index, start, len);
    }
    if (regex[0] == line[0]) {
        range_t *has_match = _regexp_match(whole_regex, regex + 1, line + 1, dollar, index + 1, start, len + 1);
        if (has_match) {
            return has_match;
        }
    }
     if (!caret) {
        return _regexp_match(whole_regex, whole_regex, line + 1, dollar, index + 1, index + 1, 0);
    }
    return NULL;
}

range_t *regexp_match(char *regex, char *line) {
    bool caret = false;
    if (regex[0] == '^') { 
        caret = true; 
        regex += 1; 
    }

    bool dollar = false;
    if (regex[strlen(regex) - 1] == '$') { 
        dollar = true; 
        regex[strlen(regex) - 1] = '\0';
    }

    assert(line[0] != '*');

    range_t *result;
    for (size_t i = 0; i < strlen(line); i++) {
        if ((result = _regexp_match(regex, regex, line + i, dollar, i, i, 0))) {
            return result;
        }
    }
    return NULL;
}