code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(60 lines)
1 // Logic for parsing path literals
3 #include <stdarg.h>
4 #include <stdbool.h>
5 #include <string.h>
7 #include <unictype.h>
8 #include <uniname.h>
10 #include "../ast.h"
11 #include "context.h"
12 #include "errors.h"
14 ast_t *parse_path(parse_ctx_t *ctx, const char *pos) {
15 // [~./] ("\" . / [^ \r\n\t])*
16 const char *start = pos;
18 if (!(*pos == '~' || *pos == '.' || *pos == '/')) return NULL;
20 int paren_depth = 0;
21 const char *path_start = pos;
22 size_t len = 1;
23 while (pos + len < ctx->file->text + ctx->file->len - 1) {
24 if (pos[len] == '\\') {
25 len += 2;
26 continue;
27 } else if (pos[len] == '(') {
28 paren_depth += 1;
29 } else if (pos[len] == ')') {
30 paren_depth -= 1;
31 if (paren_depth < 0) {
32 pos += len;
33 break;
35 } else if ((pos[len] == ' ' || pos[len] == '\t') && paren_depth == 0) {
36 pos += len;
37 break;
38 } else if (pos[len] == '\r' || pos[len] == '\n') {
39 if (paren_depth == 0) {
40 pos += len;
41 break;
43 parser_err(ctx, path_start, &pos[len], "This path was not closed");
45 len += 1;
47 char *path = String(string_slice(path_start, .length = len));
48 for (char *src = path, *dest = path;;) {
49 if (src[0] == '\\') {
50 *(dest++) = src[1];
51 src += 2;
52 } else if (*src) {
53 *(dest++) = *(src++);
54 } else {
55 *(dest++) = '\0';
56 break;
59 return NewAST(ctx->file, start, pos, Path, .path = path);