1 // Parsing logic for parsing type annotations
11 #include "../stdlib/datatypes.h"
12 #include "../stdlib/print.h"
13 #include "../stdlib/text.h"
16 #include "expressions.h"
17 #include "functions.h"
21 type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos) {
22 const char *start = pos;
23 if (!match(&pos, "{")) return NULL;
24 whitespace(ctx, &pos);
25 type_ast_t *key_type = parse_type(ctx, pos);
26 if (!key_type) return NULL;
28 whitespace(ctx, &pos);
29 type_ast_t *value_type = NULL;
30 if (match(&pos, ":")) {
31 value_type = expect(ctx, start, &pos, parse_type, "I couldn't parse the rest of this table type");
34 ast_t *default_value = NULL;
35 if (match(&pos, "=")) {
37 expect(ctx, start, &pos, parse_extended_expr, "I couldn't parse the default value for this table");
39 whitespace(ctx, &pos);
40 expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this table type");
41 return NewTypeAST(ctx->file, start, pos, TableTypeAST, .key = key_type, .value = value_type,
42 .default_value = default_value);
45 type_ast_t *parse_func_type(parse_ctx_t *ctx, const char *pos) {
46 const char *start = pos;
47 if (!match_word(&pos, "func")) return NULL;
49 expect_str(ctx, start, &pos, "(", "I expected a parenthesis here");
50 arg_ast_t *args = parse_args(ctx, &pos);
52 type_ast_t *ret = match(&pos, "->") ? optional(ctx, &pos, parse_type) : NULL;
53 expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this function type");
54 return NewTypeAST(ctx->file, start, pos, FunctionTypeAST, .args = args, .ret = ret);
57 type_ast_t *parse_list_type(parse_ctx_t *ctx, const char *pos) {
58 const char *start = pos;
59 if (!match(&pos, "[")) return NULL;
60 type_ast_t *type = expect(ctx, start, &pos, parse_type, "I couldn't parse a list item type after this point");
61 expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this list type");
62 return NewTypeAST(ctx->file, start, pos, ListTypeAST, .item = type);
65 type_ast_t *parse_pointer_type(parse_ctx_t *ctx, const char *pos) {
66 const char *start = pos;
68 if (match(&pos, "@")) is_stack = false;
69 else if (match(&pos, "&")) is_stack = true;
74 expect(ctx, start, &pos, parse_non_optional_type, "I couldn't parse a pointer type after this point");
75 type_ast_t *ptr_type = NewTypeAST(ctx->file, start, pos, PointerTypeAST, .pointed = type, .is_stack = is_stack);
77 while (match(&pos, "?"))
78 ptr_type = NewTypeAST(ctx->file, start, pos, OptionalTypeAST, .type = ptr_type);
82 type_ast_t *parse_enum_type(parse_ctx_t *ctx, const char *pos) {
83 // tagged union: enum(A, B(x:Int,y:Int)=5, ...)
84 const char *start = pos;
85 if (!match_word(&pos, "enum")) return NULL;
87 if (!match(&pos, "(")) return NULL;
89 tag_ast_t *tags = NULL;
90 whitespace(ctx, &pos);
93 const char *tag_start = pos;
94 const char *tag_name = get_id(&pos);
100 if (match(&pos, "(")) {
101 whitespace(ctx, &pos);
102 fields = parse_args(ctx, &pos);
103 whitespace(ctx, &pos);
104 if (match(&pos, ";")) { // Extra flags
105 whitespace(ctx, &pos);
106 secret = match_word(&pos, "secret");
107 whitespace(ctx, &pos);
109 expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this tagged union member");
114 tags = new (tag_ast_t, .file = ctx->file, .start = tag_start, .end = pos, .name = tag_name, .fields = fields,
115 .secret = secret, .next = tags);
117 if (!match_separator(ctx, &pos)) break;
120 whitespace(ctx, &pos);
121 expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this enum definition");
124 Text_t name = Texts("enum$", (int64_t)(start - ctx->file->text));
125 return NewTypeAST(ctx->file, start, pos, EnumTypeAST, .name = name, .tags = tags);
128 type_ast_t *parse_type_name(parse_ctx_t *ctx, const char *pos) {
129 const char *start = pos;
130 const char *id = get_id(&pos);
131 if (!id) return NULL;
133 const char *next = pos;
135 if (!match(&next, ".")) break;
136 const char *next_id = get_id(&next);
138 id = String(id, ".", next_id);
141 return NewTypeAST(ctx->file, start, pos, VarTypeAST, .name = id);
144 type_ast_t *parse_non_optional_type(parse_ctx_t *ctx, const char *pos) {
145 const char *start = pos;
146 type_ast_t *type = NULL;
147 bool success = (false || (type = parse_pointer_type(ctx, pos)) || (type = parse_list_type(ctx, pos))
148 || (type = parse_table_type(ctx, pos)) || (type = parse_enum_type(ctx, pos))
149 || (type = parse_type_name(ctx, pos)) || (type = parse_func_type(ctx, pos)));
150 if (!success && match(&pos, "(")) {
151 whitespace(ctx, &pos);
152 type = optional(ctx, &pos, parse_type);
153 if (!type) return NULL;
154 whitespace(ctx, &pos);
155 expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this type");
163 type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos) {
164 const char *start = pos;
165 type_ast_t *type = parse_non_optional_type(ctx, pos);
166 if (!type) return NULL;
169 while (match(&pos, "?"))
170 type = NewTypeAST(ctx->file, start, pos, OptionalTypeAST, .type = type);
174 type_ast_t *parse_type_str(const char *str) {
175 file_t *file = spoof_file("<type>", str);
181 const char *pos = file->text;
182 whitespace(&ctx, &pos);
183 type_ast_t *ast = parse_type(&ctx, pos);
184 if (!ast) return ast;
186 whitespace(&ctx, &pos);
187 if (strlen(pos) > 0) {
188 parser_err(&ctx, pos, pos + strlen(pos), "I couldn't parse this part of the type");