aboutsummaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2020-09-16 20:38:58 -0700
committerBruce Hill <bruce@bruce-hill.com>2020-09-16 20:38:58 -0700
commitf35d3c98b22ac3c708672493d27267de071989cd (patch)
tree6f49833558ec448768f5c90193d35b7d40c81664 /vm.c
parent6c237850e90dce317ede7b0d4e53125df15ab62b (diff)
Added tons of file and line number stuff
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c98
1 files changed, 57 insertions, 41 deletions
diff --git a/vm.c b/vm.c
index 637c4b8..da2b7df 100644
--- a/vm.c
+++ b/vm.c
@@ -1,6 +1,9 @@
/*
* vm.c - Code for the BPEG virtual machine that performs the matching.
*/
+
+#include <ctype.h>
+
#include "vm.h"
#include "grammar.h"
#include "utils.h"
@@ -54,7 +57,7 @@ static size_t push_backrefs(grammar_t *g, match_t *m)
if (m == NULL) return 0;
if (m->op->op == VM_REF) return 0;
size_t count = 0;
- if (m->is_capture && m->name_or_replacement) {
+ if (m->op->op == VM_CAPTURE && m->name_or_replacement) {
++count;
push_backref(g, m->name_or_replacement, m->child);
}
@@ -232,7 +235,6 @@ static match_t *_match(grammar_t *g, file_t *f, const char *str, vm_op_t *op, un
m->end = p->end;
m->op = op;
m->child = p;
- m->is_capture = 1;
if (op->args.capture.name)
m->name_or_replacement = op->args.capture.name;
return m;
@@ -292,7 +294,6 @@ static match_t *_match(grammar_t *g, file_t *f, const char *str, vm_op_t *op, un
} else {
m->end = m->start;
}
- m->is_replacement = 1;
m->name_or_replacement = op->args.replace.replacement;
return m;
}
@@ -333,7 +334,6 @@ static match_t *_match(grammar_t *g, file_t *f, const char *str, vm_op_t *op, un
m->op = op;
m->child = best;
m->name_or_replacement = op->args.s;
- m->is_ref = 1;
return m;
}
case VM_BACKREF: {
@@ -470,6 +470,10 @@ void print_pattern(vm_op_t *op)
fprintf(stderr, " with \"%s\"", op->args.replace.replacement);
break;
}
+ case VM_NODENT: {
+ fprintf(stderr, "the start of a line with the same indentation as the previous line");
+ break;
+ }
default: break;
}
}
@@ -481,8 +485,8 @@ static match_t *get_capture_n(match_t *m, int *n)
{
if (!m) return NULL;
if (*n == 0) return m;
- if (m->is_capture && *n == 1) return m;
- if (m->is_capture) --(*n);
+ if (m->op->op == VM_CAPTURE && *n == 1) return m;
+ if (m->op->op == VM_CAPTURE) --(*n);
for (match_t *c = m->child; c; c = c->nextsibling) {
match_t *cap = get_capture_n(c, n);
if (cap) return cap;
@@ -495,7 +499,7 @@ static match_t *get_capture_n(match_t *m, int *n)
*/
static match_t *get_capture_named(match_t *m, const char *name)
{
- if (m->is_capture && m->name_or_replacement && streq(m->name_or_replacement, name))
+ if (m->op->op == VM_CAPTURE && m->name_or_replacement && streq(m->name_or_replacement, name))
return m;
for (match_t *c = m->child; c; c = c->nextsibling) {
match_t *cap = get_capture_named(c, name);
@@ -504,12 +508,30 @@ static match_t *get_capture_named(match_t *m, const char *name)
return NULL;
}
+static match_t *get_cap(match_t *m, const char **r)
+{
+ if (isdigit(**r)) {
+ int n = (int)strtol(*r, (char**)r, 10);
+ return get_capture_n(m->child, &n);
+ } else if (**r == '[') {
+ char *closing = strchr(*r+1, ']');
+ if (!closing) return NULL;
+ ++(*r);
+ char *name = strndup(*r, (size_t)(closing-*r));
+ match_t *cap = get_capture_named(m, name);
+ free(name);
+ *r = closing + 1;
+ return cap;
+ }
+ return NULL;
+}
+
/*
* Print a match with replacements and highlighting.
*/
-void print_match(match_t *m, const char *color, int verbose)
+void print_match(file_t *f, match_t *m, const char *color, int verbose)
{
- if (m->is_replacement) {
+ if (m->op->op == VM_REPLACE) {
if (color) printf("\033[0;34m");
for (const char *r = m->name_or_replacement; *r; ) {
if (*r == '\\') {
@@ -523,42 +545,36 @@ void print_match(match_t *m, const char *color, int verbose)
}
++r;
- match_t *cap = NULL;
- switch (*r) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- int n = (int)strtol(r, (char**)&r, 10);
- cap = get_capture_n(m->child, &n);
- break;
- }
- case '[': {
- char *closing = strchr(r+1, ']');
- if (!closing) {
- fputc('@', stdout);
- break;
- }
- ++r;
- char *name = strndup(r, (size_t)(closing-r));
- cap = get_capture_named(m, name);
- free(name);
- r = closing + 1;
- break;
- }
- default: {
- fputc('@', stdout);
- break;
- }
+ if (*r == '@') {
+ fputc('@', stdout);
+ continue;
}
+ if (*r == '#') {
+ ++r;
+ printf("%ld", get_line_number(f, m->start));
+ continue;
+ } else if (*r == ':') {
+ ++r;
+ printf("%ld", get_char_number(f, m->start));
+ continue;
+ } else if (*r == '&') {
+ ++r;
+ printf("%s", f->filename ? f->filename : "-");
+ continue;
+ }
+ match_t *cap = get_cap(m, &r);
if (cap != NULL) {
- print_match(cap, color ? "\033[0;35m" : NULL, verbose);
+ print_match(f, cap, color ? "\033[0;35m" : NULL, verbose);
if (color) printf("\033[0;34m");
+ } else {
+ fputc('@', stdout);
}
}
} else {
const char *name = m->name_or_replacement;
- if (verbose && m->is_ref && name)
+ if (verbose && m->op->op == VM_REF && name)
printf(color ? "\033[0;2;35m{%s:" : "{%s", name);
- //if (m->is_capture && name)
+ //if (m->op->op == VM_CAPTURE && name)
// printf("\033[0;2;33m[%s:", name);
const char *prev = m->start;
for (match_t *child = m->child; child; child = child->nextsibling) {
@@ -568,14 +584,14 @@ void print_match(match_t *m, const char *color, int verbose)
continue;
if (child->start > prev)
printf("%s%.*s", color ? color : "", (int)(child->start - prev), prev);
- print_match(child, color ? (m->is_capture ? "\033[0;31;1m" : color) : NULL, verbose);
+ print_match(f, child, color ? (m->op->op == VM_CAPTURE ? "\033[0;31;1m" : color) : NULL, verbose);
prev = child->end;
}
if (m->end > prev)
printf("%s%.*s", color ? color : "", (int)(m->end - prev), prev);
- if (verbose && m->is_ref && name)
+ if (verbose && m->op->op == VM_REF && name)
printf(color ? "\033[0;2;35m}" : "}");
- //if (m->is_capture && name)
+ //if (m->op->op == VM_CAPTURE && name)
// printf("\033[0;2;33m]");
}
}
@@ -588,7 +604,7 @@ static match_t *match_backref(const char *str, vm_op_t *op, match_t *cap, unsign
ret->op = op;
match_t **dest = &ret->child;
- if (cap->is_replacement) {
+ if (cap->op->op == VM_REPLACE) {
for (const char *r = cap->name_or_replacement; *r; ) {
if (*r == '\\') {
++r;