diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/parse/containers.c | 127 | ||||
| -rw-r--r-- | src/parse/containers.h | 9 | ||||
| -rw-r--r-- | src/parse/files.c | 2 | ||||
| -rw-r--r-- | src/parse/parse.c | 116 | ||||
| -rw-r--r-- | src/parse/parse.h | 3 |
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); |
