-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser_utils.c
More file actions
145 lines (128 loc) · 4.45 KB
/
parser_utils.c
File metadata and controls
145 lines (128 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#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;
}
/*
* para comparar "foo" (length 3) necesitamos 3 + 2 estados.
* Los útimos dos, son el sumidero de comparación fallida, y
* el estado donde se llegó a la comparación completa.
*
* static const struct parser_state_transition ST_0 [] = {
* {.when = 'F', .dest = 1, .action1 = may_eq, },
* {.when = 'f', .dest = 1, .action1 = may_eq, },
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_1 [] = {
* {.when = 'O', .dest = 2, .action1 = may_eq, },
* {.when = 'o', .dest = 2, .action1 = may_eq, },
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_2 [] = {
* {.when = 'O', .dest = EQ, .action1 = eq, },
* {.when = 'o', .dest = EQ, .action1 = eq, },
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_EQ (3) [] = {
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_NEQ (4) [] = {
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
*
*/
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 = {
.start_state = 0,
.states_count = 0,
.states = NULL,
.states_n = NULL,
};
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 = {
.start_state = 0,
.states_count = n + 2,
.states = (struct parser_state_transition **) states,
.states_n = (size_t *) nstates,
};
return def;
}
void
parser_utils_strcmpi_destroy(const struct parser_definition *p) {
free((void *)p->states[0]);
free((void *)p->states);
free((void *)p->states_n);
}