aboutsummaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-10 15:15:38 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-10 15:15:38 -0400
commit8d3d5913129a8ede381462d5ad5e98f9c789e5c8 (patch)
tree074e1fd4489710af0810e2a901106a7161467021 /parse.c
parentcb6cebf12e2124503f0551bc1bf6b44f68d86746 (diff)
Add Sets to the language
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/parse.c b/parse.c
index 128a2aca..2b7b5816 100644
--- a/parse.c
+++ b/parse.c
@@ -513,6 +513,19 @@ type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos) {
return NewTypeAST(ctx->file, start, pos, TableTypeAST, .key=key_type, .value=value_type);
}
+type_ast_t *parse_set_type(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+ if (!match(&pos, "{")) return NULL;
+ whitespace(&pos);
+ type_ast_t *item_type = parse_type(ctx, pos);
+ if (!item_type) return NULL;
+ pos = item_type->end;
+ whitespace(&pos);
+ if (match(&pos, ":")) return NULL;
+ expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this set type");
+ return NewTypeAST(ctx->file, start, pos, SetTypeAST, .item=item_type);
+}
+
type_ast_t *parse_func_type(parse_ctx_t *ctx, const char *pos) {
const char *start = pos;
if (!match_word(&pos, "func")) return NULL;
@@ -576,6 +589,7 @@ type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos) {
|| (type=parse_pointer_type(ctx, pos))
|| (type=parse_array_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))
);
@@ -698,7 +712,7 @@ PARSER(parse_table) {
key_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a key type for this table");
whitespace(&pos);
if (!match(&pos, ":"))
- parser_err(ctx, pos, pos, "I expected an ':' for this table type");
+ return NULL;
value_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a value type for this table");
whitespace(&pos);
}
@@ -760,6 +774,50 @@ PARSER(parse_table) {
return NewAST(ctx->file, start, pos, Table, .key_type=key_type, .value_type=value_type, .entries=entries, .fallback=fallback, .default_value=default_val);
}
+PARSER(parse_set) {
+ const char *start = pos;
+ if (!match(&pos, "{")) return NULL;
+
+ whitespace(&pos);
+
+ ast_list_t *items = NULL;
+ type_ast_t *item_type = NULL;
+ if (match(&pos, ":")) {
+ whitespace(&pos);
+ item_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a key type for this set");
+ whitespace(&pos);
+ if (match(&pos, ":"))
+ return NULL;
+ whitespace(&pos);
+ }
+
+ for (;;) {
+ ast_t *item = optional(ctx, &pos, parse_extended_expr);
+ if (!item) break;
+ whitespace(&pos);
+ if (match(&pos, ":")) return NULL;
+ ast_t *suffixed = parse_comprehension_suffix(ctx, item);
+ while (suffixed) {
+ item = suffixed;
+ pos = suffixed->end;
+ suffixed = parse_comprehension_suffix(ctx, item);
+ }
+ items = new(ast_list_t, .ast=item, .next=items);
+ if (!match_separator(&pos))
+ break;
+ }
+
+ REVERSE_LIST(items);
+
+ if (!item_type && !items)
+ return NULL;
+
+ whitespace(&pos);
+ expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this set");
+
+ return NewAST(ctx->file, start, pos, Set, .item_type=item_type, .items=items);
+}
+
ast_t *parse_field_suffix(parse_ctx_t *ctx, ast_t *lhs) {
if (!lhs) return NULL;
const char *pos = lhs->end;
@@ -1287,6 +1345,7 @@ PARSER(parse_term_no_suffix) {
|| (term=parse_lambda(ctx, pos))
|| (term=parse_parens(ctx, pos))
|| (term=parse_table(ctx, pos))
+ || (term=parse_set(ctx, pos))
|| (term=parse_var(ctx, pos))
|| (term=parse_array(ctx, pos))
|| (term=parse_reduction(ctx, pos))