aboutsummaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2020-09-13 20:33:11 -0700
committerBruce Hill <bruce@bruce-hill.com>2020-09-13 20:33:11 -0700
commit1d1c3d35aae0e060a6527d6e83575dd7ff71328e (patch)
treebc9e486906d47fac29d8d0f1e8c8915d2bf5ab9f /vm.c
parentab5ef5a77af9f2fc7c3353f05bf716b1a6b93f73 (diff)
Added == operator
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/vm.c b/vm.c
index c1427a5..8e0957d 100644
--- a/vm.c
+++ b/vm.c
@@ -28,6 +28,7 @@ static const char *opcode_names[] = {
[VM_OTHERWISE] = "OTHERWISE",
[VM_CHAIN] = "CHAIN",
[VM_REPLACE] = "REPLACE",
+ [VM_EQUAL] = "EQUAL",
[VM_REF] = "REF",
[VM_BACKREF] = "BACKREF",
};
@@ -253,6 +254,25 @@ static match_t *_match(grammar_t *g, const char *str, vm_op_t *op, recursive_ref
m1->nextsibling = m2;
return m;
}
+ case VM_EQUAL: {
+ match_t *m1 = _match(g, str, op->args.multiple.first, rec);
+ if (m1 == NULL) return NULL;
+
+ // <p1>==<p2> matches iff both have the same start and end point:
+ match_t *m2 = _match(g, str, op->args.multiple.second, rec);
+ if (m2 == NULL || m2->end != m1->end) {
+ destroy_match(&m1);
+ destroy_match(&m2);
+ return NULL;
+ }
+ match_t *m = calloc(sizeof(match_t), 1);
+ m->start = str;
+ m->end = m2->end;
+ m->op = op;
+ m->child = m1;
+ m1->nextsibling = m2;
+ return m;
+ }
case VM_REPLACE: {
match_t *m = calloc(sizeof(match_t), 1);
m->start = str;
@@ -512,8 +532,8 @@ void print_match(match_t *m, const char *color, int verbose)
const char *prev = m->start;
for (match_t *child = m->child; child; child = child->nextsibling) {
// Skip children from e.g. zero-width matches like >@foo
- if (!(m->start <= child->start && child->start <= m->end &&
- m->start <= child->end && child->end <= m->end))
+ if (!(prev <= child->start && child->start <= m->end &&
+ prev <= child->end && child->end <= m->end))
continue;
if (child->start > prev)
printf("%s%.*s", color ? color : "", (int)(child->start - prev), prev);
@@ -608,6 +628,7 @@ static match_t *match_backref(const char *str, vm_op_t *op, match_t *cap)
str += len;
prev = child->start;
}
+ if (child->start < prev) continue;
*dest = match_backref(str, op, child);
if (*dest == NULL) {
destroy_match(&ret);