aboutsummaryrefslogtreecommitdiff
path: root/src/parse/text.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-25 01:03:31 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-25 01:03:31 -0400
commit47d38fb5ac183180edd297830261cedd8afee2d3 (patch)
tree2ad93b15686a9c7d94e163d9a5f46350374f4571 /src/parse/text.c
parent3cf0d5f0bee3787a3d46126d5c0e1310e35a7cb9 (diff)
Split out binops
Diffstat (limited to 'src/parse/text.c')
-rw-r--r--src/parse/text.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/parse/text.c b/src/parse/text.c
index b9827644..5fe58da4 100644
--- a/src/parse/text.c
+++ b/src/parse/text.c
@@ -183,3 +183,45 @@ ast_t *parse_inline_c(parse_ctx_t *ctx, const char *pos) {
return NewAST(ctx->file, start, pos, InlineCCode, .chunks = chunks, .type_ast = type);
}
+
+public
+ast_t *parse_path(parse_ctx_t *ctx, const char *pos) {
+ // "(" ("~/" / "./" / "../" / "/") ... ")"
+ const char *start = pos;
+
+ if (!match(&pos, "(")) return NULL;
+
+ if (!(*pos == '~' || *pos == '.' || *pos == '/')) return NULL;
+
+ const char *path_start = pos;
+ size_t len = 1;
+ int paren_depth = 1;
+ while (pos + len < ctx->file->text + ctx->file->len - 1) {
+ if (pos[len] == '\\') {
+ len += 2;
+ continue;
+ } else if (pos[len] == '(') {
+ paren_depth += 1;
+ } else if (pos[len] == ')') {
+ paren_depth -= 1;
+ if (paren_depth <= 0) break;
+ } else if (pos[len] == '\r' || pos[len] == '\n') {
+ parser_err(ctx, path_start, &pos[len - 1], "This path was not closed");
+ }
+ len += 1;
+ }
+ pos += len + 1;
+ char *path = String(string_slice(path_start, .length = len));
+ for (char *src = path, *dest = path;;) {
+ if (src[0] == '\\') {
+ *(dest++) = src[1];
+ src += 2;
+ } else if (*src) {
+ *(dest++) = *(src++);
+ } else {
+ *(dest++) = '\0';
+ break;
+ }
+ }
+ return NewAST(ctx->file, start, pos, Path, .path = path);
+}