-
Notifications
You must be signed in to change notification settings - Fork 0
/
match.c
186 lines (132 loc) · 4.31 KB
/
match.c
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include <string.h>
#include <stdio.h>
#include "commands.h"
#include "match.h"
#include "history.h"
struct automaton_state match_end_of_input(struct automaton_state state) {
if(**(state.current) != '\0') {
state.acceptance_state = t_failed;
}
return state;
}
// Greedy
struct automaton_state match_optional(struct automaton_state state, AUTOMATON_MATCHER f) {
struct automaton_state out = f(state);
if(out.acceptance_state == t_accepting) {
return out;
} else {
return state;
}
}
// Greedy
struct automaton_state match_one_or_more(struct automaton_state state, AUTOMATON_MATCHER f) {
struct automaton_state a = state;
struct automaton_state b = f(a);
if(b.acceptance_state == t_failed) {
state.acceptance_state = t_failed;
return state;
}
while(b.acceptance_state == t_accepting) {
a = b;
b = f(a);
}
return a;
}
struct automaton_state match_const_token(struct automaton_state state, char *token) {
char *current_string = *(state.current);
if(strcmp(current_string, token) != 0) {
state.acceptance_state = t_failed;
}
automaton_advance(&state);
return state;
}
struct automaton_state match_ampersand(struct automaton_state state) {
struct automaton_state out = match_const_token(state, "&");
out.cmd.value.u_simple.bg = 1;
return out;
}
struct automaton_state match_end(struct automaton_state state) {
return match_end_of_input(match_optional(state, &match_ampersand));
}
struct automaton_state match_argument(struct automaton_state state) {
// Santitize arg to make sure it contains alpha-numeric characters, not longer than
// ARG_LENGTH, etc.
if(match_end_of_input(state).acceptance_state == t_accepting) {
state.acceptance_state = t_failed;
return state;
}
if(match_const_token(state, "&").acceptance_state == t_accepting
|| match_const_token(state, "|").acceptance_state == t_accepting
|| match_const_token(state, ">").acceptance_state == t_accepting) {
state.acceptance_state = t_failed;
return state;
}
cmd_append_arg(&state.cmd.value.u_simple, *(state.current));
automaton_advance(&state);
return state;
}
struct automaton_state match_command(struct automaton_state state) {
state.cmd.type = t_simple;
state.cmd.value.u_simple.len = 0;
state.cmd.value.u_simple.bg = 0;
return match_one_or_more(state, match_argument);
}
struct automaton_state match_history(struct automaton_state state) {
char *arg = *state.current;
int hist_number;
// I should have just used this the whole time.
if(sscanf(arg, "!%d", &hist_number) == 1) {
struct cmd_tagged_union *ptr = hist_fetch(hist_number);
if(ptr == 0) {
state.acceptance_state = t_failed;
} else {
state.cmd = *ptr;
}
} else {
state.acceptance_state = t_failed;
}
automaton_advance(&state);
return state;
}
struct automaton_state match_full_history(struct automaton_state state) {
return match_end_of_input(match_history(state));
}
struct automaton_state match_full_simple(struct automaton_state state) {
return match_end(match_command(state));
}
struct automaton_state match_full_compound(struct automaton_state state, char *delimeter, enum cmd_type out_type) {
state = match_command(state);
struct cmd_simple cmd1 = state.cmd.value.u_simple;
state = match_const_token(state, delimeter);
state = match_command(state);
struct cmd_simple cmd2 = state.cmd.value.u_simple;
state = match_end_of_input(state);
state.cmd.type = out_type;
state.cmd.value.u_compound.cmd1 = cmd1;
state.cmd.value.u_compound.cmd2 = cmd2;
return state;
}
struct automaton_state match_full_pipe(struct automaton_state state) {
return match_full_compound(state, "|", t_pipe);
}
struct automaton_state match_full_redirect(struct automaton_state state) {
return match_full_compound(state, ">", t_redirect);
}
struct automaton_state match_full_generic(struct automaton_state state) {
struct automaton_state after_matching;
// Empty?
if((after_matching = match_full_history(state)).acceptance_state == t_accepting) {
return after_matching;
}
if((after_matching = match_full_simple(state)).acceptance_state == t_accepting) {
return after_matching;
}
if((after_matching = match_full_pipe(state)).acceptance_state == t_accepting) {
return after_matching;
}
if((after_matching = match_full_redirect(state)).acceptance_state == t_accepting) {
return after_matching;
}
// Return failed state
return after_matching;
}