111 lines
3.1 KiB
C
111 lines
3.1 KiB
C
// 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 <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "parser_utils.h"
|
|
|
|
const char * parser_utils_strcmpi_event(const enum string_cmp_event_types type) {
|
|
const char *ret;
|
|
|
|
switch (type) {
|
|
case STRING_CMP_MAYEQ:
|
|
ret = "wait(c)";
|
|
break;
|
|
case STRING_CMP_EQ:
|
|
ret = "eq(c)";
|
|
break;
|
|
case STRING_CMP_NEQ:
|
|
ret = "neq(c)";
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void may_eq(struct parser_event *ret, const uint8_t c) {
|
|
ret->type = STRING_CMP_MAYEQ;
|
|
ret->n = 1;
|
|
ret->data[0] = c;
|
|
}
|
|
|
|
static void eq(struct parser_event *ret, const uint8_t c) {
|
|
ret->type = STRING_CMP_EQ;
|
|
ret->n = 1;
|
|
ret->data[0] = c;
|
|
}
|
|
|
|
static void neq(struct parser_event *ret, const uint8_t c) {
|
|
ret->type = STRING_CMP_NEQ;
|
|
ret->n = 1;
|
|
ret->data[0] = c;
|
|
}
|
|
|
|
struct parser_definition * parser_utils_strcmpi(const char *s) {
|
|
const size_t n = strlen(s);
|
|
|
|
struct parser_state_transition **states = calloc(n + 2, sizeof(*states));
|
|
size_t *nstates = calloc(n + 2, sizeof(*nstates));
|
|
struct parser_state_transition *transitions = calloc(3 * (n + 2), sizeof(*transitions));
|
|
|
|
if (states == NULL || nstates == NULL || transitions == NULL) {
|
|
free(states);
|
|
free(nstates);
|
|
free(transitions);
|
|
|
|
struct parser_definition * def = calloc(1, sizeof(struct parser_definition));
|
|
|
|
return def;
|
|
}
|
|
|
|
// Estados fijos
|
|
const size_t st_eq = n;
|
|
const size_t st_neq = n + 1;
|
|
|
|
for(size_t i = 0; i < n; i++) {
|
|
const size_t dest = (i + 1 == n) ? st_eq : i + 1;
|
|
|
|
transitions[i * 3 + 0].when = tolower(s[i]);
|
|
transitions[i * 3 + 0].dest = dest;
|
|
transitions[i * 3 + 0].act1 = i + 1 == n ? eq : may_eq;
|
|
transitions[i * 3 + 1].when = toupper(s[i]);
|
|
transitions[i * 3 + 1].dest = dest;
|
|
transitions[i * 3 + 1].act1 = i + 1 == n ? eq : may_eq;
|
|
transitions[i * 3 + 2].when = ANY;
|
|
transitions[i * 3 + 2].dest = st_neq;
|
|
transitions[i * 3 + 2].act1 = neq;
|
|
states[i] = transitions + (i * 3 + 0);
|
|
nstates[i] = 3;
|
|
}
|
|
|
|
// EQ
|
|
transitions[(n + 0) * 3].when = ANY;
|
|
transitions[(n + 0) * 3].dest = st_neq;
|
|
transitions[(n + 0) * 3].act1 = neq;
|
|
states[(n + 0)] = transitions + ((n + 0) * 3 + 0);
|
|
nstates[(n + 0)] = 1;
|
|
|
|
// NEQ
|
|
transitions[(n + 1) * 3].when = ANY;
|
|
transitions[(n + 1) * 3].dest = st_neq;
|
|
transitions[(n + 1) * 3].act1 = neq;
|
|
states[(n + 1)] = transitions + ((n + 1) * 3 + 0);
|
|
nstates[(n + 1)] = 1;
|
|
|
|
|
|
struct parser_definition * def = malloc(sizeof(*def));
|
|
def->start_state = 0;
|
|
def->states_count = n + 2;
|
|
def->states = (struct parser_state_transition **) states;
|
|
def->states_n = (size_t *) nstates;
|
|
|
|
return def;
|
|
}
|
|
|
|
void parser_utils_strcmpi_destroy(struct parser_definition *p) {
|
|
free((void *)p->states[0]);
|
|
free((void *)p->states);
|
|
free((void *)p->states_n);
|
|
free(p);
|
|
}
|