aboutsummaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-09-20 14:07:26 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-09-20 14:26:08 -0400
commitb9a8ddea2c0b5f170e461b9216eb14f2d86588eb (patch)
treecb45901e3046b3d28823df9c85a719a38981804d /src/parse
parente937e3056b934c6d426abc3db8de1c99433a434b (diff)
WIP on inline enums
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/functions.c7
-rw-r--r--src/parse/types.c51
-rw-r--r--src/parse/types.h3
3 files changed, 55 insertions, 6 deletions
diff --git a/src/parse/functions.c b/src/parse/functions.c
index ceb0a8bc..ea20e385 100644
--- a/src/parse/functions.c
+++ b/src/parse/functions.c
@@ -47,15 +47,14 @@ arg_ast_t *parse_args(parse_ctx_t *ctx, const char **pos) {
}
if (match(pos, ":")) {
- type = expect(ctx, *pos - 1, pos, parse_type, "I expected a type here");
+ type = expect(ctx, *pos, pos, parse_type, "I expected a type here");
whitespace(ctx, pos);
- if (match(pos, "="))
- default_val = expect(ctx, *pos - 1, pos, parse_term, "I expected a value after this '='");
+ if (match(pos, "=")) default_val = expect(ctx, *pos, pos, parse_term, "I expected a value here");
names =
new (name_list_t, .start = name_start, .end = *pos, .name = name, .alias = alias, .next = names);
break;
} else if (strncmp(*pos, "==", 2) != 0 && match(pos, "=")) {
- default_val = expect(ctx, *pos - 1, pos, parse_term, "I expected a value after this '='");
+ default_val = expect(ctx, *pos, pos, parse_term, "I expected a value here");
names =
new (name_list_t, .start = name_start, .end = *pos, .name = name, .alias = alias, .next = names);
break;
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);
diff --git a/src/parse/types.h b/src/parse/types.h
index 186d5322..ac6c22fb 100644
--- a/src/parse/types.h
+++ b/src/parse/types.h
@@ -6,8 +6,9 @@
type_ast_t *parse_type_str(const char *str);
-type_ast_t *parse_list_type(parse_ctx_t *ctx, const char *pos);
+type_ast_t *parse_enum_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_func_type(parse_ctx_t *ctx, const char *pos);
+type_ast_t *parse_list_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_non_optional_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_pointer_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_set_type(parse_ctx_t *ctx, const char *pos);