diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-20 14:20:24 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-20 14:20:24 +0200 |
commit | eca9cb305b08e0e292d01008797b9300d47f72d5 (patch) | |
tree | 0fd1131586e457ee92325f078033404c0fe7caec /src/parser.c | |
parent | 972c453a085bedb3de8d598cc4ae4486e24f0144 (diff) | |
download | bdl-eca9cb305b08e0e292d01008797b9300d47f72d5.tar.gz bdl-eca9cb305b08e0e292d01008797b9300d47f72d5.zip |
Add parsing support for functions
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/parser.c b/src/parser.c index 84f3424..dbab4af 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -53,6 +53,11 @@ typedef enum NodeKind { | |||
53 | NODE_BREAK, | 53 | NODE_BREAK, |
54 | NODE_CONTINUE, | 54 | NODE_CONTINUE, |
55 | NODE_WHILE, | 55 | NODE_WHILE, |
56 | // Functions. | ||
57 | NODE_FUN, | ||
58 | NODE_FUN_PARAM, | ||
59 | NODE_FUNCALL, | ||
60 | NODE_RETURN, | ||
56 | // Helpers. | 61 | // Helpers. |
57 | NODE_SYMBOL_IDX, | 62 | NODE_SYMBOL_IDX, |
58 | NODE_TYPE, | 63 | NODE_TYPE, |
@@ -95,6 +100,11 @@ Str node_str[] = { | |||
95 | [NODE_FALSE] = cstr("FALSE"), | 100 | [NODE_FALSE] = cstr("FALSE"), |
96 | [NODE_NIL] = cstr("NIL"), | 101 | [NODE_NIL] = cstr("NIL"), |
97 | [NODE_STRUCT_LIT] = cstr("STRUCT LIT"), | 102 | [NODE_STRUCT_LIT] = cstr("STRUCT LIT"), |
103 | // Functions. | ||
104 | [NODE_FUN] = cstr("FUNCTION"), | ||
105 | [NODE_FUN_PARAM] = cstr("PARAM"), | ||
106 | [NODE_FUNCALL] = cstr("FUNCALL"), | ||
107 | [NODE_RETURN] = cstr("RETURN"), | ||
98 | // Keywords. | 108 | // Keywords. |
99 | [NODE_LET] = cstr("LET"), | 109 | [NODE_LET] = cstr("LET"), |
100 | [NODE_SET] = cstr("SET"), | 110 | [NODE_SET] = cstr("SET"), |
@@ -158,6 +168,10 @@ typedef struct Node { | |||
158 | struct Node *field_val; | 168 | struct Node *field_val; |
159 | }; | 169 | }; |
160 | struct { | 170 | struct { |
171 | struct Node *param_name; | ||
172 | struct Node *param_type; | ||
173 | }; | ||
174 | struct { | ||
161 | struct Node *match_expr; | 175 | struct Node *match_expr; |
162 | struct Node **match_cases; | 176 | struct Node **match_cases; |
163 | }; | 177 | }; |
@@ -168,6 +182,13 @@ typedef struct Node { | |||
168 | struct Node **struct_field; | 182 | struct Node **struct_field; |
169 | struct Node **elements; | 183 | struct Node **elements; |
170 | struct Node **statements; | 184 | struct Node **statements; |
185 | struct Node **expressions; | ||
186 | struct { | ||
187 | struct Node *func_name; | ||
188 | struct Node **func_params; | ||
189 | struct Node **func_ret; | ||
190 | struct Node *func_body; | ||
191 | }; | ||
171 | }; | 192 | }; |
172 | bool is_ptr; | 193 | bool is_ptr; |
173 | } Node; | 194 | } Node; |
@@ -671,6 +692,107 @@ parse_keyword(Parser *parser) { | |||
671 | parse_expr(parser, PREC_LOW); | 692 | parse_expr(parser, PREC_LOW); |
672 | node->while_expr = array_pop(parser->nodes); | 693 | node->while_expr = array_pop(parser->nodes); |
673 | } break; | 694 | } break; |
695 | case TOK_FUN: { | ||
696 | node = node_alloc(parser, NODE_FUN, prev); | ||
697 | if (!node) return; | ||
698 | parse_consume(parser, TOK_SYMBOL, cstr("expected function name")); | ||
699 | parse_consume(parser, TOK_LPAREN, | ||
700 | cstr("expected '(' on function definition")); | ||
701 | // Parameters. | ||
702 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | ||
703 | Node *param = | ||
704 | node_alloc(parser, NODE_FUN_PARAM, parser->current); | ||
705 | if (!param) return; | ||
706 | Node *name = node_alloc(parser, NODE_SYMBOL, prev); | ||
707 | if (!name) return; | ||
708 | parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); | ||
709 | name->value.sym = parser->previous.val; | ||
710 | param->param_name = name; | ||
711 | |||
712 | Node *type = node_alloc(parser, NODE_TYPE, prev); | ||
713 | if (!type) return; | ||
714 | parse_consume(parser, TOK_COLON, cstr("expected param type")); | ||
715 | if (parse_match(parser, TOK_AT)) { | ||
716 | type->is_ptr = true; | ||
717 | } | ||
718 | parse_consume(parser, TOK_SYMBOL, cstr("expected param type")); | ||
719 | type->value.sym = parser->previous.val; | ||
720 | param->param_type = type; | ||
721 | if (parse_match(parser, TOK_LSQUARE)) { | ||
722 | type->kind = NODE_ARR_TYPE, | ||
723 | parse_consume(parser, TOK_NUM_INT, | ||
724 | cstr("no array size given")); | ||
725 | parse_number(parser); | ||
726 | type->arr_size = array_pop(parser->nodes); | ||
727 | parse_consume(parser, TOK_RSQUARE, | ||
728 | cstr("unmatched brackets ']' in array type")); | ||
729 | } | ||
730 | array_push(node->func_params, param, parser->storage); | ||
731 | } | ||
732 | parse_consume(parser, TOK_COLON, cstr("expected param type")); | ||
733 | |||
734 | // Return type(s). | ||
735 | if (!parse_match(parser, TOK_NIL)) { | ||
736 | if (parse_match(parser, TOK_LPAREN)) { | ||
737 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | ||
738 | Node *ret = node_alloc(parser, NODE_TYPE, prev); | ||
739 | if (!ret) return; | ||
740 | if (parse_match(parser, TOK_AT)) { | ||
741 | ret->is_ptr = true; | ||
742 | } | ||
743 | parse_consume(parser, TOK_SYMBOL, | ||
744 | cstr("expected type name")); | ||
745 | ret->value.sym = parser->previous.val; | ||
746 | if (parse_match(parser, TOK_LSQUARE)) { | ||
747 | ret->kind = NODE_ARR_TYPE, | ||
748 | parse_consume(parser, TOK_NUM_INT, | ||
749 | cstr("no array size given")); | ||
750 | parse_number(parser); | ||
751 | ret->arr_size = array_pop(parser->nodes); | ||
752 | parse_consume( | ||
753 | parser, TOK_RSQUARE, | ||
754 | cstr("unmatched brackets ']' in array type")); | ||
755 | } | ||
756 | array_push(node->func_ret, ret, parser->storage); | ||
757 | } | ||
758 | } else { | ||
759 | Node *ret = node_alloc(parser, NODE_TYPE, prev); | ||
760 | if (!ret) return; | ||
761 | if (parse_match(parser, TOK_AT)) { | ||
762 | ret->is_ptr = true; | ||
763 | } | ||
764 | parse_consume(parser, TOK_SYMBOL, | ||
765 | cstr("expected type name")); | ||
766 | ret->value.sym = parser->previous.val; | ||
767 | if (parse_match(parser, TOK_LSQUARE)) { | ||
768 | ret->kind = NODE_ARR_TYPE, | ||
769 | parse_consume(parser, TOK_NUM_INT, | ||
770 | cstr("no array size given")); | ||
771 | parse_number(parser); | ||
772 | ret->arr_size = array_pop(parser->nodes); | ||
773 | parse_consume( | ||
774 | parser, TOK_RSQUARE, | ||
775 | cstr("unmatched brackets ']' in array type")); | ||
776 | } | ||
777 | array_push(node->func_ret, ret, parser->storage); | ||
778 | } | ||
779 | } | ||
780 | |||
781 | // Body. | ||
782 | parse_expr(parser, PREC_LOW); | ||
783 | node->func_body = array_pop(parser->nodes); | ||
784 | } break; | ||
785 | case TOK_RETURN: { | ||
786 | node = node_alloc(parser, NODE_RETURN, prev); | ||
787 | if (!node) return; | ||
788 | parse_consume(parser, TOK_LPAREN, | ||
789 | cstr("expected '(' after return")); | ||
790 | while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { | ||
791 | parse_expr(parser, PREC_LOW); | ||
792 | array_push(node->expressions, array_pop(parser->nodes), | ||
793 | parser->storage); | ||
794 | } | ||
795 | } break; | ||
674 | default: return; // Unreachable. | 796 | default: return; // Unreachable. |
675 | } | 797 | } |
676 | array_push(parser->nodes, node, parser->storage); | 798 | array_push(parser->nodes, node, parser->storage); |
@@ -865,6 +987,7 @@ graph_node(Node *node) { | |||
865 | case NODE_STRUCT: | 987 | case NODE_STRUCT: |
866 | case NODE_STRUCT_LIT: print("| Name: %s", node->value.sym); break; | 988 | case NODE_STRUCT_LIT: print("| Name: %s", node->value.sym); break; |
867 | case NODE_SYMBOL: | 989 | case NODE_SYMBOL: |
990 | case NODE_ARR_TYPE: | ||
868 | case NODE_TYPE: { | 991 | case NODE_TYPE: { |
869 | if (node->is_ptr) { | 992 | if (node->is_ptr) { |
870 | print("| Name: @%s", node->value.sym); | 993 | print("| Name: @%s", node->value.sym); |
@@ -877,6 +1000,26 @@ graph_node(Node *node) { | |||
877 | println("\"];"); | 1000 | println("\"];"); |
878 | 1001 | ||
879 | switch (node->kind) { | 1002 | switch (node->kind) { |
1003 | case NODE_FUN: { | ||
1004 | for (sz i = 0; i < array_size(node->func_params); i++) { | ||
1005 | Node *next = node->func_params[i]; | ||
1006 | println("%d:e->%d:w;", node->id, next->id); | ||
1007 | graph_node(next); | ||
1008 | } | ||
1009 | for (sz i = 0; i < array_size(node->func_ret); i++) { | ||
1010 | Node *next = node->func_ret[i]; | ||
1011 | println("%d:e->%d:w;", node->id, next->id); | ||
1012 | graph_node(next); | ||
1013 | } | ||
1014 | if (node->func_name) { | ||
1015 | println("%d:e->%d:w;", node->id, node->func_name->id); | ||
1016 | graph_node(node->func_name); | ||
1017 | } | ||
1018 | if (node->func_body) { | ||
1019 | println("%d:e->%d:w;", node->id, node->func_body->id); | ||
1020 | graph_node(node->func_body); | ||
1021 | } | ||
1022 | } break; | ||
880 | case NODE_COND: | 1023 | case NODE_COND: |
881 | case NODE_MATCH: { | 1024 | case NODE_MATCH: { |
882 | if (node->match_expr) { | 1025 | if (node->match_expr) { |
@@ -889,6 +1032,7 @@ graph_node(Node *node) { | |||
889 | graph_node(next); | 1032 | graph_node(next); |
890 | } | 1033 | } |
891 | } break; | 1034 | } break; |
1035 | case NODE_RETURN: | ||
892 | case NODE_BLOCK: | 1036 | case NODE_BLOCK: |
893 | case NODE_STRUCT_LIT: | 1037 | case NODE_STRUCT_LIT: |
894 | case NODE_COMPOUND_TYPE: { | 1038 | case NODE_COMPOUND_TYPE: { |