summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c126
1 files changed, 68 insertions, 58 deletions
diff --git a/main.c b/main.c
index d5b913d..3ecb921 100644
--- a/main.c
+++ b/main.c
@@ -216,26 +216,35 @@ static inline int bracket_dir(u32 c) {
}
int match_bracket(TxtLoc l, TxtLoc *out, u32 c) {
- u32 depth = 1;
- u32 o = bracket_opp(c);
- if (txt_chr(l) != c) return 0;
- int dir = bracket_dir(c);
- if (dir < 0) {
- while (!at_start(l) && depth > 0) {
- l = cprev(l);
- u32 x = txt_chr(l);
- if (x == c) depth++;
- else if (x == o) depth--;
- }
- } else if (dir > 0) {
- while (!at_end(l) && depth > 0) {
- l = cnext(l);
- u32 x = txt_chr(l);
- if (x == c) depth++;
- else if (x == o) depth--;
- }
-
- }
+ u32 depth = 1;
+ u32 o = bracket_opp(c);
+ if (txt_chr(l) != c) return 0;
+ int dir = bracket_dir(c);
+ int in_str = 0, in_chr = 0;
+ while (depth > 0) {
+ if (dir < 0 && at_start(l)) break;
+ if (dir > 0 && at_end(l)) break;
+ l = dir < 0 ? cprev(l) : cnext(l);
+ u32 x = txt_chr(l);
+ if (dir > 0 && x == '\\') {
+ l = cnext(l);
+ continue;
+ } else if (dir < 0 && txt_chr(cprev(l)) == '\\') {
+ l = cprev(l);
+ continue;
+ } else {
+ if (in_chr) {
+ if (x == '\'') in_chr = 0;
+ } else if (in_str) {
+ if (x == '"') in_str = 0;
+ } else {
+ if (x == '\'') in_chr = 1;
+ else if (x == '"') in_str = 1;
+ else if (x == c) depth++;
+ else if (x == o) depth--;
+ }
+ }
+ }
if (depth == 0) {
*out = l;
return 1;
@@ -244,22 +253,35 @@ int match_bracket(TxtLoc l, TxtLoc *out, u32 c) {
}
}
-TxtLoc next_func_end(TxtLoc l) {
- l = start_of_line(l);
- while (!at_end(l)) {
- l = next_line_start(l);
- if (txt_chr(l) == '}' && txt_chr(cnext(l)) == '\n') break;
+static inline int is_func_end(TxtLoc l) {
+ TxtLoc n = cnext(l);
+ return txt_chr(l) == '}' && (txt_chr(n) == '\n' || at_end(n));
+}
+
+int next_func_end(TxtLoc l, TxtLoc *out) {
+ l = cnext(l);
+ for (;;) {
+ TxtLoc n = next_line_start(l);
+ if (!txt_before(l, n)) break;
+ if (is_func_end(l)) {
+ *out = l;
+ return 1;
+ }
+ l = n;
}
- return l;
+ return 0;
}
-TxtLoc prev_func_end(TxtLoc l) {
- l = start_of_line(l);
+int prev_func_end(TxtLoc l, TxtLoc *out) {
+ l = cprev(l);
while (!at_start(l)) {
l = prev_line_start(l);
- if (txt_chr(l) == '}' && txt_chr(cnext(l)) == '\n') break;
+ if (is_func_end(l)) {
+ *out = l;
+ return 1;
+ }
}
- return l;
+ return 0;
}
int empty_line(TxtLoc l) {
@@ -268,29 +290,23 @@ int empty_line(TxtLoc l) {
;
}
-int match_func_start(TxtLoc l, TxtLoc *out) {
- l = start_of_line(l);
- if (txt_chr(l) != '}' || txt_chr(cnext(l)) != '\n') return 0;
- for (;;) {
- if (!empty_line(l) && !is_space(txt_chr(l)) && txt_chr(cprev(end_of_line(l))) == '{') {
- *out = l;
- return 1;
- }
- if (at_start(l)) return 0;
- l = prev_line_start(l);
+int prev_func(TxtLoc start, TxtLoc *out) {
+ TxtLoc l;
+ if (prev_func_end(start, &l) && match_bracket(l, &l, '}')) {
+ *out = l;
+ return 1;
}
return 0;
}
-TxtLoc prev_func(TxtLoc l) {
- match_func_start(prev_func_end(l), &l);
- return l;
-}
-
-TxtLoc next_func(TxtLoc l) {
- match_bracket(l, &l, '{');
- match_func_start(next_func_end(l), &l);
- return l;
+int next_func(TxtLoc start, TxtLoc *out) {
+ TxtLoc l = start;
+ match_bracket(l, &l, '{');
+ if (next_func_end(l, &l) && match_bracket(l, &l, '}')) {
+ *out = l;
+ return 1;
+ }
+ return 0;
}
TxtLoc next_par(TxtLoc l) {
@@ -801,10 +817,10 @@ loop:
l = next_par(l);
break;
case '[':
- l = prev_func(l);
+ if (!prev_func(l, &l)) return 0;
break;
case ']':
- l = next_func(l);
+ if (!next_func(l, &l)) return 0;
break;
case '%':
if (!match_bracket(l, &l, txt_chr(l))) return 0;
@@ -1254,13 +1270,7 @@ int select_buf(void) {
int select_func(Txt *t, TxtLoc *out) {
TxtLoc l = txt_start(t);
DYNARR(TxtLoc) loc = { 0 };
- while (!at_end(l)) {
- l = next_func_end(l);
- TxtLoc fn;
- if (match_func_start(l, &fn)) {
- DA_APUSH(&loc, &e.scratch, fn);
- }
- }
+ while (next_func(l, &l)) DA_APUSH(&loc, &e.scratch, l);
Str *opt = new_arr(&e.scratch, Str, loc.n);
for (u32 i = 0; i < loc.n; i++) {
opt[i] = txt_collect_range(start_of_line(loc.v[i]), end_of_line(loc.v[i]), &e.scratch);