/* * Copyright (c) Camden Dixie O'Brien * SPDX-License-Identifier: AGPL-3.0-only */ #include "fsa.h" #include #include #define FSA_START_CAPACITY 16 #define STATE_START_CAPACITY 16 void fsa_init(fsa_t *fsa) { fsa->count = 0; fsa->capacity = FSA_START_CAPACITY; fsa->states = malloc(fsa->capacity * sizeof(fsa_state_t)); assert(NULL != fsa->states); fsa->initial = fsa_add_state(fsa); fsa->states[fsa->initial].final = false; } void fsa_free(const fsa_t *fsa) { for (int i = 0; i < fsa->count; ++i) free(fsa->states[i].rules); free(fsa->states); } int fsa_add_state(fsa_t *fsa) { if (fsa->count >= fsa->capacity) { fsa->capacity *= 2; fsa->states = realloc(fsa->states, fsa->capacity); assert(NULL != fsa->states); } fsa_state_t *state = &fsa->states[fsa->count]; state->final = false; state->count = 0; state->capacity = STATE_START_CAPACITY; state->rules = malloc(state->capacity * sizeof(fsa_rule_t)); assert(state->rules); return fsa->count++; } void fsa_add_rule(fsa_t *fsa, int from, int to, int input) { assert(fsa->count > from); assert(fsa->count > to); assert(input < ALPHABET_SIZE); fsa_state_t *state = &fsa->states[from]; if (state->count >= state->capacity) { state->capacity *= 2; state->rules = realloc(state->rules, state->capacity); assert(NULL != state->rules); } fsa_rule_t *rule = &state->rules[state->count]; rule->input = input; rule->next = to; ++state->count; } bool fsa_accepts(const fsa_t *dfa, const char *input, int len) { const char *end = input + len; int current = dfa->initial; while (input < end) { bool found = false; const fsa_rule_t *rules = dfa->states[current].rules; for (int i = 0; i < dfa->states[current].count; ++i) { if (rules[i].input == *input) { current = rules[i].next; found = true; break; } } if (!found) return false; ++input; } return dfa->states[current].final; }