diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lexer.c | 12 | ||||
-rw-r--r-- | src/main.c | 55 |
2 files changed, 57 insertions, 10 deletions
diff --git a/src/lexer.c b/src/lexer.c index 36a5636..2d2b6fc 100644 --- a/src/lexer.c +++ b/src/lexer.c | |||
@@ -23,11 +23,13 @@ typedef enum TokenKind { | |||
23 | // Keywords. | 23 | // Keywords. |
24 | TOK_BREAK, // break | 24 | TOK_BREAK, // break |
25 | TOK_CASE, // case | 25 | TOK_CASE, // case |
26 | TOK_COND, // match | ||
26 | TOK_CONTINUE, // continue | 27 | TOK_CONTINUE, // continue |
28 | TOK_ELSE, // else | ||
29 | TOK_ENUM, // enum | ||
27 | TOK_FALSE, // false | 30 | TOK_FALSE, // false |
28 | TOK_FUN, // fun | 31 | TOK_FUN, // fun |
29 | TOK_IF, // if | 32 | TOK_IF, // if |
30 | TOK_ELSE, // else | ||
31 | TOK_LET, // let | 33 | TOK_LET, // let |
32 | TOK_MATCH, // match | 34 | TOK_MATCH, // match |
33 | TOK_NIL, // nil | 35 | TOK_NIL, // nil |
@@ -93,8 +95,10 @@ Str token_str[] = { | |||
93 | // Keywords. | 95 | // Keywords. |
94 | [TOK_BREAK] = cstr("BREAK"), | 96 | [TOK_BREAK] = cstr("BREAK"), |
95 | [TOK_CASE] = cstr("CASE"), | 97 | [TOK_CASE] = cstr("CASE"), |
98 | [TOK_COND] = cstr("COND"), | ||
96 | [TOK_CONTINUE] = cstr("CONTINUE"), | 99 | [TOK_CONTINUE] = cstr("CONTINUE"), |
97 | [TOK_ELSE] = cstr("ELSE"), | 100 | [TOK_ELSE] = cstr("ELSE"), |
101 | [TOK_ENUM] = cstr("ENUM"), | ||
98 | [TOK_FALSE] = cstr("FALSE"), | 102 | [TOK_FALSE] = cstr("FALSE"), |
99 | [TOK_FUN] = cstr("FUN"), | 103 | [TOK_FUN] = cstr("FUN"), |
100 | [TOK_IF] = cstr("IF"), | 104 | [TOK_IF] = cstr("IF"), |
@@ -540,11 +544,17 @@ scan_token(Scanner *scanner) { | |||
540 | if (str_has_prefix(val, cstr("continue"))) { | 544 | if (str_has_prefix(val, cstr("continue"))) { |
541 | return emit_token(current, scanner, TOK_CONTINUE); | 545 | return emit_token(current, scanner, TOK_CONTINUE); |
542 | } | 546 | } |
547 | if (str_has_prefix(val, cstr("cond"))) { | ||
548 | return emit_token(current, scanner, TOK_COND); | ||
549 | } | ||
543 | } break; | 550 | } break; |
544 | case 'e': { | 551 | case 'e': { |
545 | if (str_has_prefix(val, cstr("else"))) { | 552 | if (str_has_prefix(val, cstr("else"))) { |
546 | return emit_token(current, scanner, TOK_ELSE); | 553 | return emit_token(current, scanner, TOK_ELSE); |
547 | } | 554 | } |
555 | if (str_has_prefix(val, cstr("enum"))) { | ||
556 | return emit_token(current, scanner, TOK_ENUM); | ||
557 | } | ||
548 | } break; | 558 | } break; |
549 | case 'f': { | 559 | case 'f': { |
550 | if (str_has_prefix(val, cstr("false"))) { | 560 | if (str_has_prefix(val, cstr("false"))) { |
@@ -78,12 +78,14 @@ typedef enum NodeKind { | |||
78 | NODE_IF, | 78 | NODE_IF, |
79 | NODE_MATCH, | 79 | NODE_MATCH, |
80 | NODE_CASE, | 80 | NODE_CASE, |
81 | NODE_COND, | ||
82 | NODE_ENUM, | ||
81 | // Helpers. | 83 | // Helpers. |
82 | NODE_SYMBOL_IDX, | 84 | NODE_SYMBOL_IDX, |
83 | NODE_TYPE, | 85 | NODE_TYPE, |
84 | NODE_ARR_TYPE, | 86 | NODE_ARR_TYPE, |
85 | NODE_COMPOUND_TYPE, | 87 | NODE_COMPOUND_TYPE, |
86 | NODE_STRUCT_FIELD, | 88 | NODE_VAL_FIELD, |
87 | NODE_BLOCK, | 89 | NODE_BLOCK, |
88 | } NodeKind; | 90 | } NodeKind; |
89 | 91 | ||
@@ -127,12 +129,14 @@ Str node_str[] = { | |||
127 | [NODE_IF] = cstr("IF"), | 129 | [NODE_IF] = cstr("IF"), |
128 | [NODE_MATCH] = cstr("MATCH"), | 130 | [NODE_MATCH] = cstr("MATCH"), |
129 | [NODE_CASE] = cstr("CASE"), | 131 | [NODE_CASE] = cstr("CASE"), |
132 | [NODE_COND] = cstr("COND"), | ||
133 | [NODE_ENUM] = cstr("ENUM"), | ||
130 | // Helpers. | 134 | // Helpers. |
131 | [NODE_TYPE] = cstr("TYPE"), | 135 | [NODE_TYPE] = cstr("TYPE"), |
132 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), | 136 | [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), |
133 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), | 137 | [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), |
134 | [NODE_COMPOUND_TYPE] = cstr("TYPE (COMPOUND)"), | 138 | [NODE_COMPOUND_TYPE] = cstr("TYPE (COMPOUND)"), |
135 | [NODE_STRUCT_FIELD] = cstr("FIELD"), | 139 | [NODE_VAL_FIELD] = cstr("FIELD"), |
136 | [NODE_BLOCK] = cstr("BLOCK"), | 140 | [NODE_BLOCK] = cstr("BLOCK"), |
137 | }; | 141 | }; |
138 | 142 | ||
@@ -290,8 +294,10 @@ ParseRule parse_rules[] = { | |||
290 | [TOK_LET] = {parse_keyword, NULL, PREC_NONE}, | 294 | [TOK_LET] = {parse_keyword, NULL, PREC_NONE}, |
291 | [TOK_SET] = {parse_keyword, NULL, PREC_NONE}, | 295 | [TOK_SET] = {parse_keyword, NULL, PREC_NONE}, |
292 | [TOK_STRUCT] = {parse_keyword, NULL, PREC_NONE}, | 296 | [TOK_STRUCT] = {parse_keyword, NULL, PREC_NONE}, |
297 | [TOK_ENUM] = {parse_keyword, NULL, PREC_NONE}, | ||
293 | [TOK_IF] = {parse_keyword, NULL, PREC_NONE}, | 298 | [TOK_IF] = {parse_keyword, NULL, PREC_NONE}, |
294 | [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, | 299 | [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, |
300 | [TOK_COND] = {parse_keyword, NULL, PREC_NONE}, | ||
295 | [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, | 301 | [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, |
296 | [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, | 302 | [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, |
297 | [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, | 303 | [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, |
@@ -535,14 +541,15 @@ parse_keyword(Parser *parser) { | |||
535 | 541 | ||
536 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 542 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
537 | Node *field = | 543 | Node *field = |
538 | node_alloc(parser, NODE_STRUCT_FIELD, parser->current); | 544 | node_alloc(parser, NODE_VAL_FIELD, parser->current); |
539 | if (!field) return; | 545 | if (!field) return; |
540 | parse_consume( | 546 | parse_consume( |
541 | parser, TOK_SYMBOL, | 547 | parser, TOK_SYMBOL, |
542 | cstr("expected symbol name on struct definition")); | 548 | cstr("expected symbol name on struct definition")); |
543 | parse_symbol(parser); | 549 | parse_symbol(parser); |
544 | field->field_name = array_pop(parser->nodes); | 550 | field->field_name = array_pop(parser->nodes); |
545 | if (field->field_name->next) { | 551 | if (field->field_name->next || |
552 | field->field_name->kind == NODE_SYMBOL_IDX) { | ||
546 | parse_emit_err(parser, prev, | 553 | parse_emit_err(parser, prev, |
547 | cstr("invalid symbol name in struct field")); | 554 | cstr("invalid symbol name in struct field")); |
548 | return; | 555 | return; |
@@ -589,12 +596,12 @@ parse_keyword(Parser *parser) { | |||
589 | // Are we on the default case. | 596 | // Are we on the default case. |
590 | if (!parse_match(parser, TOK_ELSE)) { | 597 | if (!parse_match(parser, TOK_ELSE)) { |
591 | parse_consume(parser, TOK_CASE, | 598 | parse_consume(parser, TOK_CASE, |
592 | cstr("expected case statement")); | 599 | cstr("expected case statement")); |
593 | parse_expr(parser, PREC_LOW); | 600 | parse_expr(parser, PREC_LOW); |
594 | tmp->case_value = array_pop(parser->nodes); | 601 | tmp->case_value = array_pop(parser->nodes); |
595 | } | 602 | } |
596 | parse_consume(parser, TOK_ASSIGN, | 603 | parse_consume(parser, TOK_ASSIGN, |
597 | cstr("malformed case statement")); | 604 | cstr("malformed case statement")); |
598 | parse_expr(parser, PREC_LOW); | 605 | parse_expr(parser, PREC_LOW); |
599 | tmp->case_expr = array_pop(parser->nodes); | 606 | tmp->case_expr = array_pop(parser->nodes); |
600 | array_push(node->match_cases, tmp, parser->storage); | 607 | array_push(node->match_cases, tmp, parser->storage); |
@@ -604,6 +611,36 @@ parse_keyword(Parser *parser) { | |||
604 | // TODO: Check that there are no multiple default or duplicated | 611 | // TODO: Check that there are no multiple default or duplicated |
605 | // cases. | 612 | // cases. |
606 | } break; | 613 | } break; |
614 | case TOK_ENUM: { | ||
615 | node = node_alloc(parser, NODE_ENUM, prev); | ||
616 | if (!node) return; | ||
617 | parse_consume(parser, TOK_SYMBOL, | ||
618 | cstr("expected symbol name on enum definition")); | ||
619 | // Just consume this to avoid conflicts with struct literals. | ||
620 | node->value.sym = parser->previous.val; | ||
621 | parse_consume(parser, TOK_LCURLY, | ||
622 | cstr("expected '{' on enum definition")); | ||
623 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | ||
624 | Node *field = | ||
625 | node_alloc(parser, NODE_VAL_FIELD, parser->current); | ||
626 | if (!field) return; | ||
627 | parse_consume(parser, TOK_SYMBOL, | ||
628 | cstr("expected symbol name on enum definition")); | ||
629 | parse_symbol(parser); | ||
630 | field->field_name = array_pop(parser->nodes); | ||
631 | if (field->field_name->next || | ||
632 | field->field_name->kind == NODE_SYMBOL_IDX) { | ||
633 | parse_emit_err(parser, prev, | ||
634 | cstr("invalid symbol name in enum field")); | ||
635 | return; | ||
636 | } | ||
637 | if (parse_match(parser, TOK_ASSIGN)) { | ||
638 | parse_expr(parser, PREC_LOW); | ||
639 | field->field_val = array_pop(parser->nodes); | ||
640 | } | ||
641 | array_push(node->struct_field, field, parser->storage); | ||
642 | } | ||
643 | } break; | ||
607 | default: return; // Unreachable. | 644 | default: return; // Unreachable. |
608 | } | 645 | } |
609 | array_push(parser->nodes, node, parser->storage); | 646 | array_push(parser->nodes, node, parser->storage); |
@@ -741,8 +778,7 @@ parse_symbol(Parser *parser) { | |||
741 | // Struct literal. | 778 | // Struct literal. |
742 | node->kind = NODE_STRUCT_LIT; | 779 | node->kind = NODE_STRUCT_LIT; |
743 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | 780 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { |
744 | Node *field = | 781 | Node *field = node_alloc(parser, NODE_VAL_FIELD, parser->current); |
745 | node_alloc(parser, NODE_STRUCT_FIELD, parser->current); | ||
746 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); | 782 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); |
747 | parse_symbol(parser); | 783 | parse_symbol(parser); |
748 | field->field_name = array_pop(parser->nodes); | 784 | field->field_name = array_pop(parser->nodes); |
@@ -831,6 +867,7 @@ graph_node(Node *node) { | |||
831 | graph_node(next); | 867 | graph_node(next); |
832 | } | 868 | } |
833 | } break; | 869 | } break; |
870 | case NODE_ENUM: | ||
834 | case NODE_STRUCT: { | 871 | case NODE_STRUCT: { |
835 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 872 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
836 | Node *next = node->struct_field[i]; | 873 | Node *next = node->struct_field[i]; |
@@ -852,7 +889,7 @@ graph_node(Node *node) { | |||
852 | graph_node(node->cond_else); | 889 | graph_node(node->cond_else); |
853 | } | 890 | } |
854 | } break; | 891 | } break; |
855 | case NODE_STRUCT_FIELD: | 892 | case NODE_VAL_FIELD: |
856 | case NODE_SET: | 893 | case NODE_SET: |
857 | case NODE_LET: { | 894 | case NODE_LET: { |
858 | if (node->var_name) { | 895 | if (node->var_name) { |