aboutsummaryrefslogtreecommitdiff
path: root/print.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2021-09-19 17:48:00 -0700
committerBruce Hill <bruce@bruce-hill.com>2021-09-19 17:48:00 -0700
commitae7f21b53149b52512dc4cb84aa20847c78526eb (patch)
tree15fc805fb4ebd7c411cd1466c58b411d31177aac /print.c
parent5fa09eb636892a36c4396308d4925077cf94ee3a (diff)
Moved capture retrieval logic into print.c
Diffstat (limited to 'print.c')
-rw-r--r--print.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/print.c b/print.c
index cb2ea34..a006a5e 100644
--- a/print.c
+++ b/print.c
@@ -2,6 +2,7 @@
// print.c - Code for printing and visualizing matches.
//
+#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -114,6 +115,64 @@ static const char *context_after(printer_t *pr, const char *pos)
}
//
+// Get a specific numbered pattern capture.
+//
+__attribute__((nonnull))
+static match_t *get_capture_by_num(match_t *m, int *n)
+{
+ if (*n == 0) return m;
+ if (m->pat->type == BP_CAPTURE && *n == 1) return m;
+ if (m->pat->type == BP_CAPTURE) --(*n);
+ if (m->children) {
+ for (int i = 0; m->children[i]; i++) {
+ match_t *cap = get_capture_by_num(m->children[i], n);
+ if (cap) return cap;
+ }
+ }
+ return NULL;
+}
+
+//
+// Get a capture with a specific name.
+//
+__attribute__((nonnull, pure))
+static match_t *get_capture_by_name(match_t *m, const char *name)
+{
+ if (m->pat->type == BP_CAPTURE && m->pat->args.capture.name
+ && strncmp(m->pat->args.capture.name, name, m->pat->args.capture.namelen) == 0)
+ return m;
+ if (m->children) {
+ for (int i = 0; m->children[i]; i++) {
+ match_t *cap = get_capture_by_name(m->children[i], name);
+ if (cap) return cap;
+ }
+ }
+ return NULL;
+}
+
+//
+// Get a capture by identifier (name or number).
+// Update *id to point to after the identifier (if found).
+//
+__attribute__((nonnull))
+static match_t *get_capture(match_t *m, const char **id)
+{
+ if (isdigit(**id)) {
+ int n = (int)strtol(*id, (char**)id, 10);
+ return get_capture_by_num(m, &n);
+ } else {
+ const char *end = after_name(*id);
+ if (end == *id) return NULL;
+ char *name = strndup(*id, (size_t)(end-*id));
+ match_t *cap = get_capture_by_name(m, name);
+ delete(&name);
+ *id = end;
+ if (**id == ';') ++(*id);
+ return cap;
+ }
+}
+
+//
// Print the text of a match (no context).
//
static void _print_match(FILE *out, printer_t *pr, match_t *m)