diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/parser.c | 94 | ||||
-rw-r--r-- | src/tokenizer.c | 6 |
3 files changed, 67 insertions, 35 deletions
@@ -7,7 +7,7 @@ int main() { "value2 = true\n" "value3 = null\n" "value4 = \"hello world\"\n" -"value5 = {\"hello\", \"world\", 5}\n" +"value5 = [\"hello\", \"world\", 5]\n" "value6 = {\"hello\": \"world\", \"value\": 23}\n" "value7 = fn () {}\n" "value8 = fn (value) {}\n" diff --git a/src/parser.c b/src/parser.c index 90c5a24..5e07f0e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -9,52 +9,74 @@ static void tsl_parser_init(TslParser *self, const char *code, size_t code_size) tsl_tokenizer_init(&self->tokenizer, code, code_size); } -typedef enum { - MAP_TYPE_UNKNOWN, - MAP_TYPE_LIST, - MAP_TYPE_MAP -} MapType; - static int tsl_parser_parse_map(TslParser *self) { - MapType map_type = MAP_TYPE_UNKNOWN; +#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); - token = tsl_tokenizer_next(&self->tokenizer); - if(token == TSL_TOKEN_COMMA) { - if(map_type == MAP_TYPE_MAP) { - /* TODO: Show which lines have mismatching element types */ - fprintf(stderr, "Error: You can't mix list elements and map elements in the same map\n"); - return -1; - } - map_type = MAP_TYPE_LIST; - } else if(token == TSL_TOKEN_COLON) { - if(map_type == MAP_TYPE_LIST) { - /* TODO: Show which lines have mismatching element types */ - fprintf(stderr, "Error: You can't mix list elements and map elements in the same map\n"); - return -1; - } - map_type = MAP_TYPE_LIST; - } else if(token == TSL_TOKEN_RBRACE) { - if(map_type == MAP_TYPE_MAP) { - /* TODO: Show why ':' is needed (because other elements in the map are map types) */ - fprintf(stderr, "Error: Expected ':', got '}'\n"); - return -1; - } - return 0; - } else { - /* TODO: Show only "expects '}' when not using key-value pair" */ - fprintf(stderr, "Error: Expected ',', ':' or '}', got TODO\n"); - return -1; - } + 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"); @@ -73,6 +95,10 @@ static int tsl_parser_parse_rhs(TslParser *self) { 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; diff --git a/src/tokenizer.c b/src/tokenizer.c index efc9eee..99ffce5 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -177,6 +177,12 @@ TslToken tsl_tokenizer_next(TslTokenizer *self) { } else if(c == '}') { ++self->code_index; return TSL_TOKEN_RBRACE; + } else if(c == '[') { + ++self->code_index; + return TSL_TOKEN_LBRACKET; + } else if(c == ']') { + ++self->code_index; + return TSL_TOKEN_RBRACKET; } else if(c == '\0') { return TSL_TOKEN_END_OF_FILE; } else { |