aboutsummaryrefslogtreecommitdiff
path: root/src/parse/types.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse/types.c')
-rw-r--r--src/parse/types.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/parse/types.c b/src/parse/types.c
index ffb7d869..683e51ce 100644
--- a/src/parse/types.c
+++ b/src/parse/types.c
@@ -6,7 +6,9 @@
#include <uniname.h>
#include "../ast.h"
+#include "../stdlib/datatypes.h"
#include "../stdlib/print.h"
+#include "../stdlib/text.h"
#include "context.h"
#include "errors.h"
#include "expressions.h"
@@ -90,6 +92,52 @@ type_ast_t *parse_pointer_type(parse_ctx_t *ctx, const char *pos) {
return ptr_type;
}
+type_ast_t *parse_enum_type(parse_ctx_t *ctx, const char *pos) {
+ // tagged union: enum(A, B(x:Int,y:Int)=5, ...)
+ const char *start = pos;
+ if (!match_word(&pos, "enum")) return NULL;
+ spaces(&pos);
+ if (!match(&pos, "(")) return NULL;
+
+ tag_ast_t *tags = NULL;
+ whitespace(ctx, &pos);
+ for (;;) {
+ spaces(&pos);
+ const char *tag_start = pos;
+ const char *tag_name = get_id(&pos);
+ if (!tag_name) break;
+
+ spaces(&pos);
+ arg_ast_t *fields;
+ bool secret = false;
+ if (match(&pos, "(")) {
+ whitespace(ctx, &pos);
+ fields = parse_args(ctx, &pos);
+ whitespace(ctx, &pos);
+ if (match(&pos, ";")) { // Extra flags
+ whitespace(ctx, &pos);
+ secret = match_word(&pos, "secret");
+ whitespace(ctx, &pos);
+ }
+ expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this tagged union member");
+ } else {
+ fields = NULL;
+ }
+
+ tags = new (tag_ast_t, .start = tag_start, .end = pos, .name = tag_name, .fields = fields, .secret = secret,
+ .next = tags);
+
+ if (!match_separator(ctx, &pos)) break;
+ }
+
+ whitespace(ctx, &pos);
+ expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this enum definition");
+
+ REVERSE_LIST(tags);
+ Text_t name = Texts("enum$", (int64_t)(start - ctx->file->text));
+ return NewTypeAST(ctx->file, start, pos, EnumTypeAST, .name = name, .tags = tags);
+}
+
type_ast_t *parse_type_name(parse_ctx_t *ctx, const char *pos) {
const char *start = pos;
const char *id = get_id(&pos);
@@ -111,7 +159,8 @@ type_ast_t *parse_non_optional_type(parse_ctx_t *ctx, const char *pos) {
type_ast_t *type = NULL;
bool success = (false || (type = parse_pointer_type(ctx, pos)) || (type = parse_list_type(ctx, pos))
|| (type = parse_table_type(ctx, pos)) || (type = parse_set_type(ctx, pos))
- || (type = parse_type_name(ctx, pos)) || (type = parse_func_type(ctx, pos)));
+ || (type = parse_enum_type(ctx, pos)) || (type = parse_type_name(ctx, pos))
+ || (type = parse_func_type(ctx, pos)));
if (!success && match(&pos, "(")) {
whitespace(ctx, &pos);
type = optional(ctx, &pos, parse_type);