aboutsummaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/expressions.c2
-rw-r--r--src/parse/files.c41
-rw-r--r--src/parse/text.c12
-rw-r--r--src/parse/text.h4
4 files changed, 48 insertions, 11 deletions
diff --git a/src/parse/expressions.c b/src/parse/expressions.c
index b43e4f3a..d031c49f 100644
--- a/src/parse/expressions.c
+++ b/src/parse/expressions.c
@@ -168,7 +168,7 @@ ast_t *parse_term_no_suffix(parse_ctx_t *ctx, const char *pos) {
(void)(false || (term = parse_none(ctx, pos)) || (term = parse_num(ctx, pos)) // Must come before int
|| (term = parse_int(ctx, pos)) || (term = parse_negative(ctx, pos)) // Must come after num/int
|| (term = parse_heap_alloc(ctx, pos)) || (term = parse_stack_reference(ctx, pos))
- || (term = parse_bool(ctx, pos)) || (term = parse_text(ctx, pos)) || (term = parse_path(ctx, pos))
+ || (term = parse_bool(ctx, pos)) || (term = parse_text(ctx, pos, true)) || (term = parse_path(ctx, pos))
|| (term = parse_lambda(ctx, pos)) || (term = parse_parens(ctx, pos)) || (term = parse_table(ctx, pos))
|| (term = parse_var(ctx, pos)) || (term = parse_list(ctx, pos)) || (term = parse_reduction(ctx, pos))
|| (term = parse_pass(ctx, pos)) || (term = parse_defer(ctx, pos)) || (term = parse_skip(ctx, pos))
diff --git a/src/parse/files.c b/src/parse/files.c
index 23e940e9..f5d9554a 100644
--- a/src/parse/files.c
+++ b/src/parse/files.c
@@ -7,8 +7,11 @@
#include <string.h>
#include "../ast.h"
+#include "../stdlib/datatypes.h"
+#include "../stdlib/paths.h"
#include "../stdlib/stdlib.h"
#include "../stdlib/tables.h"
+#include "../stdlib/text.h"
#include "../stdlib/util.h"
#include "context.h"
#include "errors.h"
@@ -31,6 +34,35 @@ static ast_t *parse_top_declaration(parse_ctx_t *ctx, const char *pos) {
return declaration;
}
+static ast_t *parse_metadata(parse_ctx_t *ctx, const char *pos) {
+ const char *start = pos;
+ const char *key = get_id(&pos);
+ if (!key) return NULL;
+ spaces(&pos);
+ if (!match(&pos, ":")) return NULL;
+ spaces(&pos);
+ ast_t *value = parse_text(ctx, pos, false);
+ Text_t value_text = EMPTY_TEXT;
+ if (value) {
+ for (ast_list_t *child = Match(value, TextJoin)->children; child; child = child->next) {
+ if (child->ast->tag != TextLiteral)
+ parser_err(ctx, child->ast->start, child->ast->end, "Text interpolations are not allowed in metadata");
+ value_text = Texts(value_text, Match(child->ast, TextLiteral)->text);
+ }
+ } else {
+ value = parse_path(ctx, pos);
+ if (!value) return NULL;
+ Path_t path = Path$from_str(Match(value, Path)->path);
+ path = Path$resolved(path, Path$parent(Path$from_str(ctx->file->filename)));
+ OptionalText_t contents = Path$read(path);
+ if (contents.tag == TEXT_NONE) parser_err(ctx, value->start, value->end, "File not found: ", path);
+ value_text = Text$trim(contents, Text("\r\n\t "), true, true);
+ }
+ pos = value->end;
+
+ return NewAST(ctx->file, start, pos, Metadata, .key = Text$from_str(key), .value = value_text);
+}
+
ast_t *parse_file_body(parse_ctx_t *ctx, const char *pos) {
const char *start = pos;
whitespace(ctx, &pos);
@@ -40,10 +72,11 @@ ast_t *parse_file_body(parse_ctx_t *ctx, const char *pos) {
whitespace(ctx, &next);
if (get_indent(ctx, next) != 0) break;
ast_t *stmt;
- if ((stmt = optional(ctx, &pos, parse_struct_def)) || (stmt = optional(ctx, &pos, parse_func_def))
- || (stmt = optional(ctx, &pos, parse_enum_def)) || (stmt = optional(ctx, &pos, parse_lang_def))
- || (stmt = optional(ctx, &pos, parse_convert_def)) || (stmt = optional(ctx, &pos, parse_use))
- || (stmt = optional(ctx, &pos, parse_inline_c)) || (stmt = optional(ctx, &pos, parse_top_declaration))) {
+ if ((stmt = optional(ctx, &pos, parse_metadata)) || (stmt = optional(ctx, &pos, parse_struct_def))
+ || (stmt = optional(ctx, &pos, parse_func_def)) || (stmt = optional(ctx, &pos, parse_enum_def))
+ || (stmt = optional(ctx, &pos, parse_lang_def)) || (stmt = optional(ctx, &pos, parse_convert_def))
+ || (stmt = optional(ctx, &pos, parse_use)) || (stmt = optional(ctx, &pos, parse_inline_c))
+ || (stmt = optional(ctx, &pos, parse_top_declaration))) {
statements = new (ast_list_t, .ast = stmt, .next = statements);
pos = stmt->end;
whitespace(ctx, &pos); // TODO: check for newline
diff --git a/src/parse/text.c b/src/parse/text.c
index 7650955c..e23b8417 100644
--- a/src/parse/text.c
+++ b/src/parse/text.c
@@ -17,7 +17,7 @@
#include "types.h"
#include "utils.h"
-static ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos) {
+static ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos, bool allow_interps) {
const char *pos = *out_pos;
int64_t starting_indent = get_indent(ctx, pos);
@@ -41,6 +41,8 @@ static ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos) {
parser_err(ctx, pos, pos, "I expected a valid text here");
}
+ if (!allow_interps) interp = NULL;
+
ast_list_t *chunks = NULL;
Text_t chunk = EMPTY_TEXT;
const char *chunk_start = pos;
@@ -123,9 +125,9 @@ static ast_list_t *_parse_text_helper(parse_ctx_t *ctx, const char **out_pos) {
return chunks;
}
-ast_t *parse_text(parse_ctx_t *ctx, const char *pos) {
+ast_t *parse_text(parse_ctx_t *ctx, const char *pos, bool allow_interps) {
// ('"' ... '"' / "'" ... "'" / "`" ... "`")
- // "$" [name] [interp-char] quote-char ... close-quote
+ // "$" [name] quote-char ... close-quote
const char *start = pos;
const char *lang = NULL;
@@ -136,7 +138,7 @@ ast_t *parse_text(parse_ctx_t *ctx, const char *pos) {
if (!(*pos == '"' || *pos == '\'' || *pos == '`')) return NULL;
- ast_list_t *chunks = _parse_text_helper(ctx, &pos);
+ ast_list_t *chunks = _parse_text_helper(ctx, &pos, allow_interps);
bool colorize = match(&pos, "~") && match_word(&pos, "colorized");
return NewAST(ctx->file, start, pos, TextJoin, .lang = lang, .children = chunks, .colorize = colorize);
}
@@ -157,7 +159,7 @@ ast_t *parse_inline_c(parse_ctx_t *ctx, const char *pos) {
parser_err(ctx, pos, pos + 1,
"This is not a valid string quotation character. Valid characters are: \"'`|/;([{<");
- ast_list_t *chunks = _parse_text_helper(ctx, &pos);
+ ast_list_t *chunks = _parse_text_helper(ctx, &pos, true);
return NewAST(ctx->file, start, pos, InlineCCode, .chunks = chunks, .type_ast = type);
}
diff --git a/src/parse/text.h b/src/parse/text.h
index 6ab3cab2..865bc5a4 100644
--- a/src/parse/text.h
+++ b/src/parse/text.h
@@ -1,9 +1,11 @@
// Logic for parsing text literals
#pragma once
+#include <stdbool.h>
+
#include "../ast.h"
#include "context.h"
-ast_t *parse_text(parse_ctx_t *ctx, const char *pos);
+ast_t *parse_text(parse_ctx_t *ctx, const char *pos, bool allow_interps);
ast_t *parse_inline_c(parse_ctx_t *ctx, const char *pos);
ast_t *parse_path(parse_ctx_t *ctx, const char *pos);