diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-25 01:03:31 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-25 01:03:31 -0400 |
| commit | 47d38fb5ac183180edd297830261cedd8afee2d3 (patch) | |
| tree | 2ad93b15686a9c7d94e163d9a5f46350374f4571 /src/parse/text.c | |
| parent | 3cf0d5f0bee3787a3d46126d5c0e1310e35a7cb9 (diff) | |
Split out binops
Diffstat (limited to 'src/parse/text.c')
| -rw-r--r-- | src/parse/text.c | 42 |
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); +} |
