diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-24 21:24:48 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-24 21:24:48 +0200 |
commit | 9eb5c9bfa3fcf8d7b03efd7d4def71e39ae3f799 (patch) | |
tree | 12b6ac10b074ba2db7e0118fed9054571ae6811b | |
parent | 2e7daa8e0765d293b1029131f6fde0592546bc0d (diff) | |
download | bdl-9eb5c9bfa3fcf8d7b03efd7d4def71e39ae3f799.tar.gz bdl-9eb5c9bfa3fcf8d7b03efd7d4def71e39ae3f799.zip |
Change grammar for struct literals
-rw-r--r-- | src/parser.c | 80 | ||||
-rw-r--r-- | tests/variables.bad | 6 |
2 files changed, 44 insertions, 42 deletions
diff --git a/src/parser.c b/src/parser.c index 1283854..7b49b55 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -63,7 +63,6 @@ typedef enum NodeKind { | |||
63 | NODE_SYMBOL_IDX, | 63 | NODE_SYMBOL_IDX, |
64 | NODE_TYPE, | 64 | NODE_TYPE, |
65 | NODE_ARR_TYPE, | 65 | NODE_ARR_TYPE, |
66 | NODE_COMPOUND_TYPE, | ||
67 | NODE_VAL_FIELD, | 66 | NODE_VAL_FIELD, |
68 | NODE_BLOCK, | 67 | NODE_BLOCK, |
69 | } NodeKind; | 68 | } NodeKind; |
@@ -123,7 +122,6 @@ Str node_str[] = { | |||
123 | [NODE_TYPE] = cstr("TYPE"), | 122 | [NODE_TYPE] = cstr("TYPE"), |
124 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), | 123 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), |
125 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), | 124 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), |
126 | [NODE_COMPOUND_TYPE] = cstr("TYPE (COMPOUND)"), | ||
127 | [NODE_VAL_FIELD] = cstr("FIELD"), | 125 | [NODE_VAL_FIELD] = cstr("FIELD"), |
128 | [NODE_BLOCK] = cstr("BLOCK"), | 126 | [NODE_BLOCK] = cstr("BLOCK"), |
129 | }; | 127 | }; |
@@ -353,6 +351,15 @@ parse_advance(Parser *parser) { | |||
353 | parser->current = parser->tokens[parser->idx++]; | 351 | parser->current = parser->tokens[parser->idx++]; |
354 | } | 352 | } |
355 | 353 | ||
354 | TokenKind | ||
355 | parse_peek(Parser *parser) { | ||
356 | assert(parser); | ||
357 | if (parser->current.kind == TOK_EOF) { | ||
358 | return TOK_EOF; | ||
359 | } | ||
360 | return parser->tokens[parser->idx].kind; | ||
361 | } | ||
362 | |||
356 | bool | 363 | bool |
357 | parse_match(Parser *parser, TokenKind kind) { | 364 | parse_match(Parser *parser, TokenKind kind) { |
358 | assert(parser); | 365 | assert(parser); |
@@ -463,30 +470,16 @@ parse_type(Parser *parser) { | |||
463 | if (parse_match(parser, TOK_AT)) { | 470 | if (parse_match(parser, TOK_AT)) { |
464 | node->is_ptr = true; | 471 | node->is_ptr = true; |
465 | } | 472 | } |
466 | if (parse_match(parser, TOK_LCURLY)) { | 473 | parse_consume(parser, TOK_SYMBOL, cstr("no type given for struct field")); |
467 | node->kind = NODE_COMPOUND_TYPE; | 474 | node->value.sym = parser->previous.val; |
468 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 475 | // Optional array value? |
469 | parse_consume(parser, TOK_SYMBOL, cstr("expected name")); | 476 | if (parse_match(parser, TOK_LSQUARE)) { |
470 | parse_symbol(parser); | 477 | node->kind = NODE_ARR_TYPE, |
471 | Node *next = array_pop(parser->nodes); | 478 | parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); |
472 | parse_consume(parser, TOK_COLON, cstr("incomplete type")); | 479 | parse_number(parser); |
473 | parse_type(parser); | 480 | node->arr_size = array_pop(parser->nodes); |
474 | next->next = array_pop(parser->nodes); | 481 | parse_consume(parser, TOK_RSQUARE, |
475 | array_push(node->elements, next, parser->storage); | 482 | cstr("unmatched brackets ']' in array type")); |
476 | } | ||
477 | } else { | ||
478 | parse_consume(parser, TOK_SYMBOL, | ||
479 | cstr("no type given for struct field")); | ||
480 | node->value.sym = parser->previous.val; | ||
481 | // Optional array value? | ||
482 | if (parse_match(parser, TOK_LSQUARE)) { | ||
483 | node->kind = NODE_ARR_TYPE, | ||
484 | parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); | ||
485 | parse_number(parser); | ||
486 | node->arr_size = array_pop(parser->nodes); | ||
487 | parse_consume(parser, TOK_RSQUARE, | ||
488 | cstr("unmatched brackets ']' in array type")); | ||
489 | } | ||
490 | } | 483 | } |
491 | array_push(parser->nodes, node, parser->storage); | 484 | array_push(parser->nodes, node, parser->storage); |
492 | } | 485 | } |
@@ -570,11 +563,17 @@ parse_keyword(Parser *parser) { | |||
570 | cstr("invalid symbol name in struct field")); | 563 | cstr("invalid symbol name in struct field")); |
571 | return; | 564 | return; |
572 | } | 565 | } |
573 | parse_consume( | 566 | parse_consume(parser, TOK_COLON, |
574 | parser, TOK_COLON, | 567 | cstr("expected type in struct field")); |
575 | cstr("expected symbol name on struct definition")); | 568 | // TODO: if consume curly |
576 | parse_type(parser); | 569 | if (parse_match(parser, TOK_LCURLY)) { |
577 | field->field_type = array_pop(parser->nodes); | 570 | // TODO: nested struct |
571 | } else { | ||
572 | parse_type(parser); | ||
573 | field->field_type = array_pop(parser->nodes); | ||
574 | } | ||
575 | // while (!parse_match(parser, TOK_RCURLY) && | ||
576 | // !parser->panic) { | ||
578 | 577 | ||
579 | // Optional assignment. | 578 | // Optional assignment. |
580 | if (parse_match(parser, TOK_ASSIGN)) { | 579 | if (parse_match(parser, TOK_ASSIGN)) { |
@@ -629,8 +628,8 @@ parse_keyword(Parser *parser) { | |||
629 | tmp->case_expr = array_pop(parser->nodes); | 628 | tmp->case_expr = array_pop(parser->nodes); |
630 | array_push(node->match_cases, tmp, parser->storage); | 629 | array_push(node->match_cases, tmp, parser->storage); |
631 | } | 630 | } |
632 | // TODO: Check that we only have literals on the match case, this | 631 | // TODO: Check that we only have literals on the match case, |
633 | // could be done on the analysis step, but also here... | 632 | // this could be done on the analysis step, but also here... |
634 | // TODO: Check that there are no multiple default or duplicated | 633 | // TODO: Check that there are no multiple default or duplicated |
635 | // cases. | 634 | // cases. |
636 | } break; | 635 | } break; |
@@ -769,9 +768,9 @@ parse_keyword(Parser *parser) { | |||
769 | cstr("no array size given")); | 768 | cstr("no array size given")); |
770 | parse_number(parser); | 769 | parse_number(parser); |
771 | ret->arr_size = array_pop(parser->nodes); | 770 | ret->arr_size = array_pop(parser->nodes); |
772 | parse_consume( | 771 | parse_consume(parser, TOK_RSQUARE, |
773 | parser, TOK_RSQUARE, | 772 | cstr("unmatched brackets ']' in " |
774 | cstr("unmatched brackets ']' in array type")); | 773 | "array type")); |
775 | } | 774 | } |
776 | array_push(node->func_ret, ret, parser->storage); | 775 | array_push(node->func_ret, ret, parser->storage); |
777 | } | 776 | } |
@@ -946,7 +945,11 @@ parse_symbol(Parser *parser) { | |||
946 | cstr("expected symbol after '.' operator")); | 945 | cstr("expected symbol after '.' operator")); |
947 | parse_symbol(parser); | 946 | parse_symbol(parser); |
948 | node->next = array_pop(parser->nodes); | 947 | node->next = array_pop(parser->nodes); |
949 | } else if (parse_match(parser, TOK_LCURLY)) { | 948 | } else if (parser->current.kind == TOK_COLON && |
949 | parse_peek(parser) == TOK_LCURLY) { | ||
950 | parse_advance(parser); | ||
951 | parse_advance(parser); | ||
952 | |||
950 | // Struct literal. | 953 | // Struct literal. |
951 | node->kind = NODE_STRUCT_LIT; | 954 | node->kind = NODE_STRUCT_LIT; |
952 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 955 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
@@ -1076,8 +1079,7 @@ graph_node(Node *node) { | |||
1076 | case NODE_FUNCALL: | 1079 | case NODE_FUNCALL: |
1077 | case NODE_RETURN: | 1080 | case NODE_RETURN: |
1078 | case NODE_BLOCK: | 1081 | case NODE_BLOCK: |
1079 | case NODE_STRUCT_LIT: | 1082 | case NODE_STRUCT_LIT: { |
1080 | case NODE_COMPOUND_TYPE: { | ||
1081 | for (sz i = 0; i < array_size(node->elements); i++) { | 1083 | for (sz i = 0; i < array_size(node->elements); i++) { |
1082 | Node *next = node->elements[i]; | 1084 | Node *next = node->elements[i]; |
1083 | println("%d:e->%d:w;", node->id, next->id); | 1085 | println("%d:e->%d:w;", node->id, next->id); |
diff --git a/tests/variables.bad b/tests/variables.bad index 61d1956..88e04d1 100644 --- a/tests/variables.bad +++ b/tests/variables.bad | |||
@@ -44,14 +44,14 @@ struct entity { | |||
44 | } | 44 | } |
45 | 45 | ||
46 | ; Symbols followed by curly braces output struct literals. | 46 | ; Symbols followed by curly braces output struct literals. |
47 | let particle = entity { | 47 | let particle = entity : { |
48 | ; Two ways of initializing inner fields. | 48 | ; Two ways of initializing inner fields. |
49 | pos = vec { x = 1 y = 2 } | 49 | pos = vec : { x = 1 y = 2 } |
50 | attr.id = 1 | 50 | attr.id = 1 |
51 | attr.name = "particle" | 51 | attr.name = "particle" |
52 | 52 | ||
53 | ; Missing initialization fields default to zero. | 53 | ; Missing initialization fields default to zero. |
54 | vel = vec { y = -3 } | 54 | vel = vec : { y = -3 } |
55 | } | 55 | } |
56 | 56 | ||
57 | ; We can have static arrays and have indexed access. | 57 | ; We can have static arrays and have indexed access. |