aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c2
-rw-r--r--src/parser.c94
-rw-r--r--src/tokenizer.c6
3 files changed, 67 insertions, 35 deletions
diff --git a/src/main.c b/src/main.c
index 04932d3..3cc01a9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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 {