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

#include "regex.h"

/*
 To implement:
 - ^
 - $
 - [...]
 - [^...]
 - *
 */

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;
    }
    else if (regex[0] == '\0') {
        return NULL;
    }
    else if (regex[1] == '*') {
        if (regex[0] == line[0] && line[0] != '\0') {
            range_t *end = _regexp_match(whole_regex, regex + 2, line + 1, caret, dollar, index + 1, start, len + 1);
            if (end) {
                return end;
            }
            range_t *include = _regexp_match(whole_regex, regex, line + 1, caret, dollar, index + 1, start, len + 1);
            if (include) {
                return include;
            }
        } 
        if (!caret && line[0] != '\0') {
            range_t *restart = _regexp_match(whole_regex, whole_regex, line + 1, caret, dollar, index + 1, index + 1, 0);
            if (restart) {
                return restart;
            }
        }
        range_t *skip = _regexp_match(whole_regex, regex + 2, line, caret, dollar, index, start, len);
        if (skip) {
            return skip;
        }
        return NULL;
    }
    else if (regex[0] == line[0]) {
        return _regexp_match(whole_regex, regex + 1, line + 1, caret, dollar, index + 1, start, len + 1);
    }
    else if (!caret && line[0] != '\0') {
        return _regexp_match(whole_regex, whole_regex, line + 1, caret, dollar, index + 1, index + 1, 0);
    }
    else {
        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] != '*');
    return _regexp_match(regex, regex, line, caret, dollar, 0, 0, 0);
}