summaryrefslogtreecommitdiff
path: root/lexparse.c
blob: 19ce08bcab6c7a9a1a1566559f59845f7cfad1b1 (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
#include <ctype.h>
#include "syntax.h"
#include "utils.h"

typedef struct {
    Word word_germ;
    String lit_germ;
} LexingBuffer;

typedef struct {
    TokenVec* token_pool;
    TokenPtrVec* top_tokens;
} PseudoAst;

static void consolidate_buffer(LexingBuffer* buf, PseudoAst ps_ast) {
    if (buf->lit_germ.count > 0) {
        push_to_Word(&buf->word_germ, (Chunk){
            .qmode = UN_Q,
            .kind = CHUNK_LIT,
            .as.lit_str = inner(&buf->lit_germ)
        });
        buf->lit_germ = make_String(256);
    }
    if (buf->word_germ.count > 0) {
        Token* tok_ptr = push_to_TokenVec(ps_ast.token_pool, (Token){
            .kind = TOK_WORD,
            .as.word = buf->word_germ
        });
        push_to_TokenPtrVec(ps_ast.top_tokens, tok_ptr);
    }
}


static Chunk collect_single_q_section(char* line, size_t* pos) {
    (*pos)++;
    String buf = make_String(256);
    size_t i;
    for (i = *pos; line[*pos] != '\'' && line[*pos] != '\0'; i++) {
        push_to_String(&buf, line[*pos]);
    }
    if (line[i] == '\0') exit(44);

    *pos = i;
    return (Chunk){
        .qmode = SINGLE_Q,
        .kind = LITERAL,
        .as.literal_str = inner(&buf)
    };
}

DECLARE_MAYBE(SpecialToken, MaybeSpecialToken)


static MaybeSpecialToken recognize_spec_token(char* line, size_t* pos) {
    // TODO: add more error guards for peekaheads
    char next_ch;

    switch (line[*pos]) {
        case '|':
            (*pos)++;
            return (MaybeSpecialToken){.some = true, .value = SPEC_PIPE};
        case '>':
            next_ch = line[(*pos)+1];
            switch (next_ch) {
                case '(':
                    return (MaybeSpecialToken){.some = false};
                case '>':
                    *pos += 2;
                    return (MaybeSpecialToken){.some = true, .value = SPEC_REDIR_W_APPEND};
                default:
                    (*pos)++;
                    return (MaybeSpecialToken){.some = true, .value = SPEC_REDIR_W_TRUNC};
            }
        case '<':
            next_ch = line[(*pos)+1];
            if (line[(*pos)+1] == '(') {
                return (MaybeSpecialToken){.some = false};
            } else {
                (*pos)++;
                return (MaybeSpecialToken){.some = true, .value = SPEC_REDIR_R};
            }
        default:
            return (MaybeSpecialToken){.some = false};
    }
}

static void lex_level(char* line, size_t* pos, char until, PseudoAst ps_ast) {
    LexingBuffer buf = {.word_germ = make_Word(256), .lit_germ = make_String(256)};
    while (line[*pos] != until) {
        if (line[*pos] == ' ') {
            consolidate_buffer(&buf, ps_ast);
            while (line[*pos] == ' ') (*pos)++;
            continue;
        } 
        MaybeSpecialToken m_spec = recognize_spec_token(line, pos);
    }
}

Ast lex(char* input) {
    size_t line_pos = 0;
}