aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
blob: 5e07f0e95ba17c57130006f24aa07ea48c9484b6 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "../include/parser.h"
#include <stdio.h>

typedef struct {
    TslTokenizer tokenizer;
} TslParser;

static void tsl_parser_init(TslParser *self, const char *code, size_t code_size) {
    tsl_tokenizer_init(&self->tokenizer, code, code_size);
}

static int tsl_parser_parse_map(TslParser *self) {
#define parse_map_element_separator                                     \
    if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_COLON))        \
        return -1;                                                      \
    token = tsl_tokenizer_next(&self->tokenizer);                       \
    if(token == TSL_TOKEN_COMMA) {                                      \
        continue;                                                       \
    } else if(token == TSL_TOKEN_RBRACE) {                              \
        return 0;                                                       \
    } else {                                                            \
        fprintf(stderr, "Error: Expected ',' or '}', got TODO\n");      \
        return -1;                                                      \
    }

    for(;;) {
        TslToken token = tsl_tokenizer_next(&self->tokenizer);
        if(token == TSL_TOKEN_NUM) {
            printf("rhs num: %ld\n", self->tokenizer.number_value);
            parse_map_element_separator
        } else if(token == TSL_TOKEN_BOOL) {
            printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
            parse_map_element_separator
        } else if(token == TSL_TOKEN_NULL) {
            printf("rhs null\n");
            parse_map_element_separator
        } else if(token == TSL_TOKEN_STRING) {
            printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data);
            parse_map_element_separator
        } else if(token == TSL_TOKEN_RBRACE) {
            /* '}' after trailing ',' or an empty map */
            return 0;
        } else {
            fprintf(stderr, "Error: Expected '}', got TODO\n");
            return -1;
        }

        token = tsl_tokenizer_next(&self->tokenizer);
    }
}

static int tsl_parser_parse_list(TslParser *self) {
#define parse_list_element_separator                                    \
    token = tsl_tokenizer_next(&self->tokenizer);                       \
    if(token == TSL_TOKEN_COMMA) {                                      \
        continue;                                                       \
    } else if(token == TSL_TOKEN_RBRACKET) {                            \
        return 0;                                                       \
    } else {                                                            \
        fprintf(stderr, "Error: Expected ',' or ']', got TODO\n");      \
        return -1;                                                      \
    }

    for(;;) {
        TslToken token = tsl_tokenizer_next(&self->tokenizer);
        if(token == TSL_TOKEN_NUM) {
            printf("rhs num: %ld\n", self->tokenizer.number_value);
            parse_list_element_separator
        } else if(token == TSL_TOKEN_BOOL) {
            printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
            parse_list_element_separator
        } else if(token == TSL_TOKEN_NULL) {
            printf("rhs null\n");
            parse_list_element_separator
        } else if(token == TSL_TOKEN_STRING) {
            printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data);
            parse_list_element_separator
        } else if(token == TSL_TOKEN_RBRACKET) {
            /* ']' after trailing ',' or an empty list */
            return 0;
        } else {
            fprintf(stderr, "Error: Expected '}', got TODO\n");
            return -1;
        }
    }
}

static int tsl_parser_parse_rhs(TslParser *self) {
    TslToken token = tsl_tokenizer_next(&self->tokenizer);
    if(token == TSL_TOKEN_NUM) {
        printf("rhs num: %ld\n", self->tokenizer.number_value);
    } else if(token == TSL_TOKEN_BOOL) {
        printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
    } else if(token == TSL_TOKEN_NULL) {
        printf("rhs null\n");
    } else if(token == TSL_TOKEN_STRING) {
        printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data);
    } else if(token == TSL_TOKEN_LBRACE) {
        tsl_parser_parse_map(self);
    } else if(token == TSL_TOKEN_LBRACKET) {
        tsl_parser_parse_list(self);
    } else {
        fprintf(stderr, "Error: Expected number, bool or null, got TODO\n");
        return -1;
    }
    return 0;
}

static int tsl_parser_parse(TslParser *self) {
    for(;;) {
        TslToken token = tsl_tokenizer_next(&self->tokenizer);
        if(token == TSL_TOKEN_IDENTIFIER) {
            TslStringView identifier = self->tokenizer.identifier;
            printf("identifier: %.*s\n", identifier.size, identifier.data);
            if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_EQUAL)) {
                return -1;
            }
            if(tsl_parser_parse_rhs(self) != 0) {
                return -1;
            }
        } else if(token == TSL_TOKEN_END_OF_FILE) {
            break;
        } else {
            fprintf(stderr, "Error: Expected identifier, got TODO\n");
            return -1;
        }
    }
    return 0;
}

int tsl_parse(const char *code, size_t code_size) {
    TslParser parser;
    tsl_parser_init(&parser, code, code_size);
    return tsl_parser_parse(&parser);
}