summaryrefslogtreecommitdiff
path: root/redes/preproc.c
blob: 944883104eb20ffdbf2ce4c9d80a0b680c01db4f (plain)
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};
}