aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap/parser.c
blob: 7a5b5164c7db7f18fc82c119b951ce30defd7dbe (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
Token *
consume_token(Tokens *tokens) {
    if (tokens->n == 0) {
        return NULL;
    }
    Token *ret = tokens->start;
    tokens->start = &tokens->start[1];
    tokens->n--;
    return ret;
}

Object *
parse(Tokens *tokens) {
    while (tokens->n > 0) {
        Token *token = consume_token(tokens);
        if (token == NULL) {
            return NULL;
        }

        switch (token->type) {
            case TOKEN_FIXNUM: {
                ssize_t num = 0;
                int sign = 1;
                for (size_t i = 0; i < token->value.n; i++) {
                    char c = token->value.start[i];
                    if (c == '-') {
                        sign = -1;
                        continue;
                    }
                    num = num * 10 + (c - '0');
                }
                return make_fixnum(num * sign);
            } break;
            case TOKEN_BOOL: {
                if (sv_equal(token->value, TRUE_TOKEN)) {
                    return obj_true;
                }
                if (sv_equal(token->value, FALSE_TOKEN)) {
                    return obj_false;
                }
            } break;
            case TOKEN_RPAREN: {
                return NULL;
            } break;
            case TOKEN_LPAREN: {
                if (tokens->n > 0 && tokens->start[0].type == TOKEN_RPAREN) {
                    return obj_nil;
                }

                Object *next_obj = parse(tokens);
                if (next_obj == NULL) {
                    return NULL;
                }
                Object *root = make_pair(next_obj, obj_nil);
                Object *list = root;
                while (tokens->n > 0 && (next_obj = parse(tokens)) != NULL) {
                    list->cdr = make_pair(next_obj, obj_nil);
                    list = list->cdr;
                }
                return root;
            } break;
            case TOKEN_STRING: {
                Object *obj = make_empty_string();
                append_string(obj, token->value);
                return obj;
            } break;
            case TOKEN_SYMBOL: {
                return make_symbol(token->value.start, token->value.n);
            } break;
            default: {
                fprintf(stderr, "error: unknown token\n");
            } break;
        }
    }

    return NULL;
}