aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-18 19:12:13 +0200
committerBad Diode <bd@badd10de.dev>2024-06-18 19:12:13 +0200
commita0068318895ff8dea6d3c3f0db381fbca83e3f40 (patch)
tree200a987c8ac3eb10cc1d6400328baeee986837a7 /src
parentc80020d23599a9ea7b60f83449dbb93762ca9770 (diff)
downloadbdl-a0068318895ff8dea6d3c3f0db381fbca83e3f40.tar.gz
bdl-a0068318895ff8dea6d3c3f0db381fbca83e3f40.zip
Add parsing for match-case statements
Diffstat (limited to 'src')
-rw-r--r--src/main.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/src/main.c b/src/main.c
index 0679558..1bb5ff6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -76,6 +76,8 @@ typedef enum NodeKind {
76 NODE_SET, 76 NODE_SET,
77 NODE_STRUCT, 77 NODE_STRUCT,
78 NODE_IF, 78 NODE_IF,
79 NODE_MATCH,
80 NODE_CASE,
79 // Helpers. 81 // Helpers.
80 NODE_SYMBOL_IDX, 82 NODE_SYMBOL_IDX,
81 NODE_TYPE, 83 NODE_TYPE,
@@ -123,6 +125,8 @@ Str node_str[] = {
123 [NODE_SET] = cstr("SET"), 125 [NODE_SET] = cstr("SET"),
124 [NODE_STRUCT] = cstr("STRUCT DEF"), 126 [NODE_STRUCT] = cstr("STRUCT DEF"),
125 [NODE_IF] = cstr("IF"), 127 [NODE_IF] = cstr("IF"),
128 [NODE_MATCH] = cstr("MATCH"),
129 [NODE_CASE] = cstr("CASE"),
126 // Helpers. 130 // Helpers.
127 [NODE_TYPE] = cstr("TYPE"), 131 [NODE_TYPE] = cstr("TYPE"),
128 [NODE_ARR_TYPE] = cstr("TYPE (ARR)"), 132 [NODE_ARR_TYPE] = cstr("TYPE (ARR)"),
@@ -169,6 +173,14 @@ typedef struct Node {
169 struct Node *field_type; 173 struct Node *field_type;
170 struct Node *field_val; 174 struct Node *field_val;
171 }; 175 };
176 struct {
177 struct Node *match_expr;
178 struct Node **match_cases;
179 };
180 struct {
181 struct Node *case_value;
182 struct Node *case_expr;
183 };
172 struct Node **struct_field; 184 struct Node **struct_field;
173 struct Node **elements; 185 struct Node **elements;
174 struct Node **statements; 186 struct Node **statements;
@@ -280,7 +292,6 @@ ParseRule parse_rules[] = {
280 [TOK_STRUCT] = {parse_keyword, NULL, PREC_NONE}, 292 [TOK_STRUCT] = {parse_keyword, NULL, PREC_NONE},
281 [TOK_IF] = {parse_keyword, NULL, PREC_NONE}, 293 [TOK_IF] = {parse_keyword, NULL, PREC_NONE},
282 [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, 294 [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE},
283 [TOK_CASE] = {parse_keyword, NULL, PREC_NONE},
284 [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, 295 [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE},
285 [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, 296 [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE},
286 [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, 297 [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE},
@@ -345,11 +356,11 @@ parse_consume(Parser *parser, TokenKind kind, Str msg) {
345 parse_emit_err(parser, parser->current, msg); 356 parse_emit_err(parser, parser->current, msg);
346} 357}
347 358
348void 359void
349parse_block(Parser *parser) { 360parse_block(Parser *parser) {
350#if DEBUG == 1 361#if DEBUG == 1
351 print("parsing block "); 362 print("parsing block ");
352 print_token(prev); 363 print_token(parser->previous);
353#endif 364#endif
354 Node *block = node_alloc(parser, NODE_BLOCK, parser->previous); 365 Node *block = node_alloc(parser, NODE_BLOCK, parser->previous);
355 if (!block) return; 366 if (!block) return;
@@ -563,6 +574,34 @@ parse_keyword(Parser *parser) {
563 node->cond_else = array_pop(parser->nodes); 574 node->cond_else = array_pop(parser->nodes);
564 } 575 }
565 } break; 576 } break;
577 case TOK_MATCH: {
578 node = node_alloc(parser, NODE_MATCH, prev);
579 if (!node) return;
580 parse_expr(parser, PREC_LOW);
581 node->match_expr = array_pop(parser->nodes);
582 parse_consume(parser, TOK_LCURLY,
583 cstr("expected block of match cases"));
584 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) {
585 parse_consume(parser, TOK_CASE,
586 cstr("expected case statement"));
587 Node *tmp = node_alloc(parser, NODE_CASE, parser->previous);
588 if (!tmp) return;
589 // Are we on the default case.
590 if (!parse_match(parser, TOK_ASSIGN)) {
591 parse_expr(parser, PREC_LOW);
592 tmp->case_value = array_pop(parser->nodes);
593 parse_consume(parser, TOK_ASSIGN,
594 cstr("malformed case statement"));
595 }
596 parse_expr(parser, PREC_LOW);
597 tmp->case_expr = array_pop(parser->nodes);
598 array_push(node->match_cases, tmp, parser->storage);
599 }
600 // TODO: Check that we only have literals on the match case, this
601 // could be done on the analysis step, but also here...
602 // TODO: Check that there are no multiple default or duplicated
603 // cases.
604 } break;
566 default: return; // Unreachable. 605 default: return; // Unreachable.
567 } 606 }
568 array_push(parser->nodes, node, parser->storage); 607 array_push(parser->nodes, node, parser->storage);
@@ -770,6 +809,17 @@ graph_node(Node *node) {
770 println("\"];"); 809 println("\"];");
771 810
772 switch (node->kind) { 811 switch (node->kind) {
812 case NODE_MATCH: {
813 if (node->match_expr) {
814 println("%d:e->%d:w;", node->id, node->match_expr->id);
815 graph_node(node->match_expr);
816 }
817 for (sz i = 0; i < array_size(node->match_cases); i++) {
818 Node *next = node->match_cases[i];
819 println("%d:e->%d:w;", node->id, next->id);
820 graph_node(next);
821 }
822 } break;
773 case NODE_BLOCK: 823 case NODE_BLOCK:
774 case NODE_STRUCT_LIT: 824 case NODE_STRUCT_LIT:
775 case NODE_COMPOUND_TYPE: { 825 case NODE_COMPOUND_TYPE: {
@@ -929,7 +979,8 @@ print_usage(void) {
929 printf("\n"); 979 printf("\n");
930 printf("\t-h \t\tShow usage.\n"); 980 printf("\t-h \t\tShow usage.\n");
931 printf( 981 printf(
932 "\t-p [l|p|s|t]\tPrint mode for [l]exing, [p]arsing, [s]emantic " 982 "\t-p [l|p|s|t]\tPrint mode for [l]exing, [p]arsing, "
983 "[s]emantic "
933 "analysis, symbol [t]ables\n"); 984 "analysis, symbol [t]ables\n");
934 printf("\n"); 985 printf("\n");
935} 986}