aboutsummaryrefslogtreecommitdiff
path: root/src/parse/files.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-25 01:26:47 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-25 01:26:47 -0400
commitfbc6b59305d8414bb1cb471ea3f85a8d926beb4f (patch)
tree0e2c7f32d7cc64f5fdc56d3086766d5bfcbe9d25 /src/parse/files.c
parentbbcc85eec5ccccd7cd7573f15510ceccfe42cc0d (diff)
Further split out files for parsing
Diffstat (limited to 'src/parse/files.c')
-rw-r--r--src/parse/files.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/src/parse/files.c b/src/parse/files.c
index 416adc92..6ff01af1 100644
--- a/src/parse/files.c
+++ b/src/parse/files.c
@@ -14,7 +14,10 @@
#include "files.h"
#include "functions.h"
#include "parse.h"
+#include "statements.h"
#include "text.h"
+#include "typedefs.h"
+#include "types.h"
#include "utils.h"
// The cache of {filename -> parsed AST} will hold at most this many entries:
@@ -28,7 +31,6 @@ static ast_t *parse_top_declaration(parse_ctx_t *ctx, const char *pos) {
return declaration;
}
-public
ast_t *parse_file_body(parse_ctx_t *ctx, const char *pos) {
const char *start = pos;
whitespace(&pos);
@@ -111,3 +113,69 @@ ast_t *parse_file(const char *path, jmp_buf *on_err) {
Table$str_set(&cached, path, ast);
return ast;
}
+
+ast_t *parse_use(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+
+ ast_t *var = parse_var(ctx, pos);
+ if (var) {
+ pos = var->end;
+ spaces(&pos);
+ if (!match(&pos, ":=")) return NULL;
+ spaces(&pos);
+ }
+
+ if (!match_word(&pos, "use")) return NULL;
+ spaces(&pos);
+ size_t name_len = strcspn(pos, " \t\r\n;");
+ if (name_len < 1) parser_err(ctx, start, pos, "There is no module name here to use");
+ char *name = GC_strndup(pos, name_len);
+ pos += name_len;
+ while (match(&pos, ";"))
+ continue;
+ int what;
+ if (name[0] == '<' || ends_with(name, ".h")) {
+ what = USE_HEADER;
+ } else if (starts_with(name, "-l")) {
+ what = USE_SHARED_OBJECT;
+ } else if (ends_with(name, ".c")) {
+ what = USE_C_CODE;
+ } else if (ends_with(name, ".S") || ends_with(name, ".s")) {
+ what = USE_ASM;
+ } else if (starts_with(name, "./") || starts_with(name, "/") || starts_with(name, "../")
+ || starts_with(name, "~/")) {
+ what = USE_LOCAL;
+ } else {
+ what = USE_MODULE;
+ }
+ return NewAST(ctx->file, start, pos, Use, .var = var, .path = name, .what = what);
+}
+
+ast_t *parse_extern(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+ if (!match_word(&pos, "extern")) return NULL;
+ spaces(&pos);
+ const char *name = get_id(&pos);
+ spaces(&pos);
+ if (!match(&pos, ":")) parser_err(ctx, start, pos, "I couldn't get a type for this extern");
+ type_ast_t *type = expect(ctx, start, &pos, parse_type, "I couldn't parse the type for this extern");
+ return NewAST(ctx->file, start, pos, Extern, .name = name, .type = type);
+}
+
+public
+ast_t *parse_file_str(const char *str) {
+ file_t *file = spoof_file("<string>", str);
+ parse_ctx_t ctx = {
+ .file = file,
+ .on_err = NULL,
+ };
+
+ const char *pos = file->text;
+ whitespace(&pos);
+ ast_t *ast = parse_file_body(&ctx, pos);
+ pos = ast->end;
+ whitespace(&pos);
+ if (pos < file->text + file->len && *pos != '\0')
+ parser_err(&ctx, pos, pos + strlen(pos), "I couldn't parse this part of the string");
+ return ast;
+}