summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2026-01-01 04:20:20 -0500
committerWormHeamer2026-01-01 04:20:20 -0500
commitfafa797d33d1e6fd0fa0cee9a8cd7eb90ba85782 (patch)
tree547c072101f9c511232b82d7867216c162100a2f
parentd862b833292133948e67bfd39a20d825bc80733e (diff)
regex error reporting
-rw-r--r--main.c12
-rw-r--r--regex.c31
-rw-r--r--regex.h8
3 files changed, 42 insertions, 9 deletions
diff --git a/main.c b/main.c
index a1281a9..a6caab0 100644
--- a/main.c
+++ b/main.c
@@ -531,8 +531,9 @@ done:;
int search_next_regex(TxtLoc l, Str src, TxtLoc *out) {
RegEx re = { 0 };
ReSearch s = { 0 };
- if (re_comp_ex(&re, src, &e.scratch, &e.scratch, RE_COMP_NO_GROUPS)) {
- /* TODO: report parse error */
+ int err = re_comp_ex(&re, src, &e.scratch, &e.scratch, RE_COMP_NO_GROUPS);
+ if (err) {
+ e.msg = str_printf(&e.scratch, "Regex error: %s", re_comp_strerror(err));
return 0;
}
TxtLoc t = l;
@@ -561,8 +562,9 @@ search_from_start:
int search_prev_regex(TxtLoc start, Str src, TxtLoc *out) {
RegEx re = { 0 };
ReSearch s = { 0 };
- if (re_comp_ex(&re, src, &e.scratch, &e.scratch, RE_COMP_NO_GROUPS)) {
- /* TODO: report parse error */
+ int err = re_comp_ex(&re, src, &e.scratch, &e.scratch, RE_COMP_NO_GROUPS);
+ if (err) {
+ e.msg = str_printf(&e.scratch, "Regex error: %s", re_comp_strerror(err));
return 0;
}
int match_found = 0;
@@ -1251,4 +1253,4 @@ int main(int argc, const char **argv) {
vui_fini();
arena_free(&e.scratch);
return 0;
-} \ No newline at end of file
+}
diff --git a/regex.c b/regex.c
index 6a362e4..88f926e 100644
--- a/regex.c
+++ b/regex.c
@@ -33,6 +33,7 @@ typedef struct {
Arena *perm, *scratch;
DYNARR(u32) lbl;
ReCompFlags flags;
+ ReCompErr err;
Str s;
int i;
} ReParser;
@@ -90,7 +91,10 @@ ReNode *re_parse_group(ReParser *s) {
/* TODO */
skip(s, 1);
ReNode *n = re_new_node(s, N_GROUP, re_parse_expr(s), NULL);
- if (ch(s) != ')') FAIL_WITH_MSG("expected )");
+ if (ch(s) != ')') {
+ s->err = RE_COMP_ENORPAREN;
+ return NULL;
+ }
skip(s, 1);
return n;
}
@@ -177,7 +181,7 @@ ReNode *re_parse_atom(ReParser *s) {
} break;
case 0:
/* should never happen? */
- FAIL_WITH_MSG("atom parsed at end");
+ s->err = RE_COMP_EEOF;
return NULL;
default: {
ReNode *n = re_new_node_char(s, ch(s));
@@ -586,14 +590,33 @@ int re_comp_ex(RegEx *re, Str src, Arena *perm, Arena *scratch, ReCompFlags flag
.perm = perm,
.scratch = scratch,
.s = src,
- .flags = flags
+ .flags = flags,
+ .err = RE_COMP_ENONE
};
ReNode *n = re_parse_expr(&s);
+ if (!s.err) {
+ if (s.s.n > 0 && s.s.s[s.s.n - 1] == ')') {
+ s.err = RE_COMP_ENOLPAREN;
+ }
+ }
if (re_comp_node(&s, n)) return -1;
if (re_comp_fin(&s)) return -1;
- return 0;
+ return s.err;
+}
+
+const char *re_comp_strerror(ReCompErr err) {
+ switch (err) {
+ case RE_COMP_ENONE:
+ return "success";
+ case RE_COMP_ENORPAREN:
+ return "no closing )";
+ case RE_COMP_ENOLPAREN:
+ return "no opening (";
+ case RE_COMP_EEOF:
+ return "unexpected end of pattern";
+ }
}
int re_comp(RegEx *re, Str src, Arena *perm, Arena *scratch) {
diff --git a/regex.h b/regex.h
index b6ee9c7..c21c708 100644
--- a/regex.h
+++ b/regex.h
@@ -111,8 +111,16 @@ typedef enum {
RE_COMP_NO_GROUPS = 1
} ReCompFlags;
+typedef enum {
+ RE_COMP_ENONE,
+ RE_COMP_ENORPAREN,
+ RE_COMP_ENOLPAREN,
+ RE_COMP_EEOF,
+} ReCompErr;
+
int re_comp(RegEx *re, Str src, Arena *perm, Arena *scratch);
int re_comp_ex(RegEx *re, Str src, Arena *perm, Arena *scratch, ReCompFlags flags);
+const char *re_comp_strerror(ReCompErr err);
void re_search_start(ReSearch *s, RegEx *re, Arena *a);
void re_search_chunk(ReSearch *s, const char *buf, size_t n);