diff options
Diffstat (limited to 'src/parse')
| -rw-r--r-- | src/parse/functions.c | 7 | ||||
| -rw-r--r-- | src/parse/types.c | 51 | ||||
| -rw-r--r-- | src/parse/types.h | 3 |
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); |
