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
|
#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) {
char* buf_str = inner(&buf);
push_to_StrVec(result, buf_str);
}
}
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;
}
typedef struct {
TokenKind kind;
union {
char* word;
SpecialToken spec;
} as;
} ExpandedToken;
DECLARE_VEC(ExpandedToken, ExpandedTokenVec)
Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) {
ExpandedTokenVec exp_tokens = make_ExpandedTokenVec(256);
for (int m = 0; m < tokens.count; m++) {
Token tok = *get_from_TokenVec(&tokens, m);
StrVec strs;
switch (tok.kind) {
case TOK_SPEC:
push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_SPEC, .as.spec = tok.as.spec});
break;
case TOK_WORD:
strs = process_word(tok.as.word);
for (int n = 0; n < strs.count; n++) {
push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_WORD, .as.word = *get_from_StrVec(&strs, n)});
}
}
}
Pipeline pl = make_Pipeline(256);
size_t tok_pos = 0;
PlCommand curr_cmd = {.args = make_ArgVec(256), .redirects = make_RedirectVec(256), .conn = CONN_EOL};
PlCommand* root_pl;
for (int i = 0; i < exp_tokens.count; i++) {
ExpandedToken curr_tok = *get_from_ExpandedTokenVec(&exp_tokens, i);
switch (curr_tok.kind) {
case TOK_WORD:
push_to_ArgVec(&curr_cmd.args, (Arg){.kind = ARG_LIT, .as.lit_str = curr_tok.as.word});
break;
case TOK_SPEC:
switch (curr_tok.as.spec.kind) {
case SPEC_OP:
switch (curr_tok.as.spec.as.op) {
case OP_PIPE:
curr_cmd.conn = CONN_PIPE;
push_to_Pipeline(&pl, curr_cmd);
curr_cmd = (PlCommand){.args = make_ArgVec(256), .redirects = make_RedirectVec(256), .conn = CONN_EOL};
break;
case OP_EOL:
push_to_Pipeline(&pl, curr_cmd);
break;
default:
exit(63);
}
break;
default:
exit(62);
}
}
}
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};
}
|