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
|
#include <assert.h>
#include <stdio.h>
#include "syntax.h"
void split_str_on_space(char* str, StrVec* result) {
String buf = make_String(256);
for (int pos = 0; str[pos] != '\0'; pos++) {
if (str[pos] == ' ') {
push_to_StrVec(result, inner(&buf));
buf = make_String(256);
} else {
push_to_String(&buf, str[pos]);
}
}
if (buf.count > 0) {
push_to_StrVec(result, inner(&buf));
}
}
StrVec process_word(Word word) {
StrVec result = make_StrVec(256);
for (int i = 0; i < word.count; i++) {
Chunk chunk = *get_from_Word(&word, i);
switch (chunk.qmode) {
case SINGLE_Q:
push_to_StrVec(&result, chunk.as.lit_str);
break;
case DOUBLE_Q:
// TODO
exit(67);
break;
case UN_Q:
// TODO: this only does literals, implement the rest
split_str_on_space(chunk.as.lit_str, &result);
break;
}
}
return result;
}
Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) {
Pipeline pl = make_Pipeline(256);
size_t tok_pos = 0;
while (tok_pos < tokens.count) {
PlCommand pl_cmd = {
.args = make_ArgVec(256),
.redirects = make_RedirectVec(256),
.conn = CONN_EOL,
};
Token curr_tok;
for (;
(
curr_tok = *get_from_TokenVec(&tokens, tok_pos),
!(curr_tok.kind == TOK_SPEC && (curr_tok.as.spec == SPEC_PIPE || curr_tok.as.spec == SPEC_EOL))
);
tok_pos++
) {
StrVec exp_word;
switch (curr_tok.kind) {
case TOK_WORD:
exp_word = process_word(curr_tok.as.word);
for (int j = 0; j < exp_word.count; j++) {
char* arg_str = *get_from_StrVec(&exp_word, j);
push_to_ArgVec(&pl_cmd.args, (Arg){.kind = ARG_LIT, .as.lit_str = arg_str});
}
break;
default:
exit(68); // TODO: the other kinds
}
}
Token delim_tok = *get_from_TokenVec(&tokens, tok_pos++);
assert(delim_tok.kind == TOK_SPEC);
switch (delim_tok.as.spec) {
case SPEC_PIPE:
pl_cmd.conn = CONN_PIPE;
break;
case SPEC_EOL:
pl_cmd.conn = CONN_EOL;
break;
default:
exit(69);
}
push_to_Pipeline(&pl, pl_cmd);
}
return push_to_PipelineVec(pl_pool, pl);
}
PipelineTree process_ast(Ast ast) {
PipelineVec pls = make_PipelineVec(256);
TokenVec root_toks = *ast.root;
Pipeline* root_pl = process_token_sequence(root_toks, &pls);
return (PipelineTree){.pl_pool = pls, root_pl};
}
|