// This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include "parser.h"
#include "parser_utils.h"

void parser_destroy(struct parser *p) {
    if (p != NULL) {
        free(p);
    }
}

#include <stdio.h>

struct parser * parser_init(const unsigned *classes, struct parser_definition *def) {
    struct parser *ret = malloc(sizeof(*ret));
    if (ret != NULL) {
        memset(ret, 0, sizeof(*ret));
        ret->classes = classes;
        ret->def = def;
        ret->state = def->start_state;
    }
    return ret;
}

void parser_reset(struct parser *p) {
    p->state = p->def->start_state;
}

struct parser_event * parser_feed(struct parser *p, const uint8_t c) {
    const unsigned type = p->classes[c];

    p->e1.next = p->e2.next = 0;

    const struct parser_state_transition *state = p->def->states[p->state];
    const size_t n = p->def->states_n[p->state];
    bool matched;

    for (unsigned i = 0; i < n ; i++) {
        const int when = state[i].when;
        if (state[i].when <= 0xFF) {
            matched = (c == when);
        } else if (state[i].when == (int) ANY) {
            matched = true;
        } else {
            matched = (type & when);
        }

        if (matched) {
            state[i].act1(&p->e1, c);
            if (state[i].act2 != NULL) {
                p->e1.next = &p->e2;
                state[i].act2(&p->e2, c);
            }
            p->state = state[i].dest;
            break;
        }
    }
    return &p->e1;
}

static const unsigned classes[0xFF + 1] = {0x00};

const unsigned * parser_no_classes(void) {
    return classes;
}
