aboutsummaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-25 00:53:00 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-25 00:53:00 -0400
commit75376335580c539512d459292d73e8ad4d7fe1af (patch)
tree4594eccfef6c9d02b51427c61b74d282c91d61b1 /src/parse
parent1f93e82303f19029394c3e1d2c375c23d56a6498 (diff)
Split out container type parsing
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/containers.c127
-rw-r--r--src/parse/containers.h9
-rw-r--r--src/parse/files.c2
-rw-r--r--src/parse/parse.c116
-rw-r--r--src/parse/parse.h3
5 files changed, 138 insertions, 119 deletions
diff --git a/src/parse/containers.c b/src/parse/containers.c
new file mode 100644
index 00000000..5c39eb5b
--- /dev/null
+++ b/src/parse/containers.c
@@ -0,0 +1,127 @@
+// Logic for parsing container types (lists, sets, tables)
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "../ast.h"
+#include "../stdlib/util.h"
+#include "context.h"
+#include "errors.h"
+#include "parse.h"
+#include "utils.h"
+
+ast_t *parse_list(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+ if (!match(&pos, "[")) return NULL;
+
+ whitespace(&pos);
+
+ ast_list_t *items = NULL;
+ for (;;) {
+ ast_t *item = optional(ctx, &pos, parse_extended_expr);
+ if (!item) break;
+ 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;
+ }
+ whitespace(&pos);
+ expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this list");
+
+ REVERSE_LIST(items);
+ return NewAST(ctx->file, start, pos, List, .items = items);
+}
+
+ast_t *parse_table(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+ if (!match(&pos, "{")) return NULL;
+
+ whitespace(&pos);
+
+ ast_list_t *entries = NULL;
+ for (;;) {
+ const char *entry_start = pos;
+ ast_t *key = optional(ctx, &pos, parse_extended_expr);
+ if (!key) break;
+ whitespace(&pos);
+ if (!match(&pos, "=")) return NULL;
+ ast_t *value = expect(ctx, pos - 1, &pos, parse_expr, "I couldn't parse the value for this table entry");
+ ast_t *entry = NewAST(ctx->file, entry_start, pos, TableEntry, .key = key, .value = value);
+ ast_t *suffixed = parse_comprehension_suffix(ctx, entry);
+ while (suffixed) {
+ entry = suffixed;
+ pos = suffixed->end;
+ suffixed = parse_comprehension_suffix(ctx, entry);
+ }
+ entries = new (ast_list_t, .ast = entry, .next = entries);
+ if (!match_separator(&pos)) break;
+ }
+
+ REVERSE_LIST(entries);
+
+ whitespace(&pos);
+
+ ast_t *fallback = NULL, *default_value = NULL;
+ if (match(&pos, ";")) {
+ for (;;) {
+ whitespace(&pos);
+ const char *attr_start = pos;
+ if (match_word(&pos, "fallback")) {
+ whitespace(&pos);
+ if (!match(&pos, "=")) parser_err(ctx, attr_start, pos, "I expected an '=' after 'fallback'");
+ if (fallback) parser_err(ctx, attr_start, pos, "This table already has a fallback");
+ fallback = expect(ctx, attr_start, &pos, parse_expr, "I expected a fallback table");
+ } else if (match_word(&pos, "default")) {
+ whitespace(&pos);
+ if (!match(&pos, "=")) parser_err(ctx, attr_start, pos, "I expected an '=' after 'default'");
+ if (default_value) parser_err(ctx, attr_start, pos, "This table already has a default");
+ default_value = expect(ctx, attr_start, &pos, parse_expr, "I expected a default value");
+ } else {
+ break;
+ }
+ whitespace(&pos);
+ if (!match(&pos, ",")) break;
+ }
+ }
+
+ whitespace(&pos);
+ expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this table");
+
+ return NewAST(ctx->file, start, pos, Table, .default_value = default_value, .entries = entries,
+ .fallback = fallback);
+}
+
+ast_t *parse_set(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+ if (match(&pos, "||")) return NewAST(ctx->file, start, pos, Set);
+
+ if (!match(&pos, "|")) return NULL;
+ whitespace(&pos);
+
+ ast_list_t *items = NULL;
+ for (;;) {
+ ast_t *item = optional(ctx, &pos, parse_extended_expr);
+ if (!item) break;
+ whitespace(&pos);
+ 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);
+
+ whitespace(&pos);
+ expect_closing(ctx, &pos, "|", "I wasn't able to parse the rest of this set");
+
+ return NewAST(ctx->file, start, pos, Set, .items = items);
+}
diff --git a/src/parse/containers.h b/src/parse/containers.h
new file mode 100644
index 00000000..6bf75274
--- /dev/null
+++ b/src/parse/containers.h
@@ -0,0 +1,9 @@
+// Logic for parsing container types (lists, sets, tables)
+#pragma once
+
+#include "../ast.h"
+#include "context.h"
+
+ast_t *parse_list(parse_ctx_t *ctx, const char *pos);
+ast_t *parse_set(parse_ctx_t *ctx, const char *pos);
+ast_t *parse_table(parse_ctx_t *ctx, const char *pos);
diff --git a/src/parse/files.c b/src/parse/files.c
index 316c6234..def740dd 100644
--- a/src/parse/files.c
+++ b/src/parse/files.c
@@ -12,8 +12,8 @@
#include "context.h"
#include "errors.h"
#include "files.h"
+#include "functions.h"
#include "parse.h"
-#include "types.h"
#include "utils.h"
// The cache of {filename -> parsed AST} will hold at most this many entries:
diff --git a/src/parse/parse.c b/src/parse/parse.c
index a3f30c64..df3694cf 100644
--- a/src/parse/parse.c
+++ b/src/parse/parse.c
@@ -13,6 +13,7 @@
#include "../stdlib/print.h"
#include "../stdlib/text.h"
#include "../stdlib/util.h"
+#include "containers.h"
#include "context.h"
#include "errors.h"
#include "files.h"
@@ -194,121 +195,6 @@ type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos) {
return type;
}
-ast_t *parse_list(parse_ctx_t *ctx, const char *pos) {
- const char *start = pos;
- if (!match(&pos, "[")) return NULL;
-
- whitespace(&pos);
-
- ast_list_t *items = NULL;
- for (;;) {
- ast_t *item = optional(ctx, &pos, parse_extended_expr);
- if (!item) break;
- 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;
- }
- whitespace(&pos);
- expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this list");
-
- REVERSE_LIST(items);
- return NewAST(ctx->file, start, pos, List, .items = items);
-}
-
-ast_t *parse_table(parse_ctx_t *ctx, const char *pos) {
- const char *start = pos;
- if (!match(&pos, "{")) return NULL;
-
- whitespace(&pos);
-
- ast_list_t *entries = NULL;
- for (;;) {
- const char *entry_start = pos;
- ast_t *key = optional(ctx, &pos, parse_extended_expr);
- if (!key) break;
- whitespace(&pos);
- if (!match(&pos, "=")) return NULL;
- ast_t *value = expect(ctx, pos - 1, &pos, parse_expr, "I couldn't parse the value for this table entry");
- ast_t *entry = NewAST(ctx->file, entry_start, pos, TableEntry, .key = key, .value = value);
- ast_t *suffixed = parse_comprehension_suffix(ctx, entry);
- while (suffixed) {
- entry = suffixed;
- pos = suffixed->end;
- suffixed = parse_comprehension_suffix(ctx, entry);
- }
- entries = new (ast_list_t, .ast = entry, .next = entries);
- if (!match_separator(&pos)) break;
- }
-
- REVERSE_LIST(entries);
-
- whitespace(&pos);
-
- ast_t *fallback = NULL, *default_value = NULL;
- if (match(&pos, ";")) {
- for (;;) {
- whitespace(&pos);
- const char *attr_start = pos;
- if (match_word(&pos, "fallback")) {
- whitespace(&pos);
- if (!match(&pos, "=")) parser_err(ctx, attr_start, pos, "I expected an '=' after 'fallback'");
- if (fallback) parser_err(ctx, attr_start, pos, "This table already has a fallback");
- fallback = expect(ctx, attr_start, &pos, parse_expr, "I expected a fallback table");
- } else if (match_word(&pos, "default")) {
- whitespace(&pos);
- if (!match(&pos, "=")) parser_err(ctx, attr_start, pos, "I expected an '=' after 'default'");
- if (default_value) parser_err(ctx, attr_start, pos, "This table already has a default");
- default_value = expect(ctx, attr_start, &pos, parse_expr, "I expected a default value");
- } else {
- break;
- }
- whitespace(&pos);
- if (!match(&pos, ",")) break;
- }
- }
-
- whitespace(&pos);
- expect_closing(ctx, &pos, "}", "I wasn't able to parse the rest of this table");
-
- return NewAST(ctx->file, start, pos, Table, .default_value = default_value, .entries = entries,
- .fallback = fallback);
-}
-
-ast_t *parse_set(parse_ctx_t *ctx, const char *pos) {
- const char *start = pos;
- if (match(&pos, "||")) return NewAST(ctx->file, start, pos, Set);
-
- if (!match(&pos, "|")) return NULL;
- whitespace(&pos);
-
- ast_list_t *items = NULL;
- for (;;) {
- ast_t *item = optional(ctx, &pos, parse_extended_expr);
- if (!item) break;
- whitespace(&pos);
- 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);
-
- whitespace(&pos);
- expect_closing(ctx, &pos, "|", "I wasn't able to parse the rest of this set");
-
- return NewAST(ctx->file, start, pos, Set, .items = items);
-}
-
ast_t *parse_field_suffix(parse_ctx_t *ctx, ast_t *lhs) {
if (!lhs) return NULL;
const char *pos = lhs->end;
diff --git a/src/parse/parse.h b/src/parse/parse.h
index ece99ea9..c0eff43c 100644
--- a/src/parse/parse.h
+++ b/src/parse/parse.h
@@ -25,7 +25,6 @@ type_ast_t *parse_set_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos);
type_ast_t *parse_type_name(parse_ctx_t *ctx, const char *pos);
-ast_t *parse_list(parse_ctx_t *ctx, const char *pos);
ast_t *parse_assignment(parse_ctx_t *ctx, const char *pos);
ast_t *parse_block(parse_ctx_t *ctx, const char *pos);
ast_t *parse_bool(parse_ctx_t *ctx, const char *pos);
@@ -54,13 +53,11 @@ ast_t *parse_path(parse_ctx_t *ctx, const char *pos);
ast_t *parse_reduction(parse_ctx_t *ctx, const char *pos);
ast_t *parse_repeat(parse_ctx_t *ctx, const char *pos);
ast_t *parse_return(parse_ctx_t *ctx, const char *pos);
-ast_t *parse_set(parse_ctx_t *ctx, const char *pos);
ast_t *parse_skip(parse_ctx_t *ctx, const char *pos);
ast_t *parse_stack_reference(parse_ctx_t *ctx, const char *pos);
ast_t *parse_statement(parse_ctx_t *ctx, const char *pos);
ast_t *parse_stop(parse_ctx_t *ctx, const char *pos);
ast_t *parse_struct_def(parse_ctx_t *ctx, const char *pos);
-ast_t *parse_table(parse_ctx_t *ctx, const char *pos);
ast_t *parse_term(parse_ctx_t *ctx, const char *pos);
ast_t *parse_term_no_suffix(parse_ctx_t *ctx, const char *pos);
ast_t *parse_text(parse_ctx_t *ctx, const char *pos);