diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2020-09-13 20:33:11 -0700 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2020-09-13 20:33:11 -0700 |
| commit | 1d1c3d35aae0e060a6527d6e83575dd7ff71328e (patch) | |
| tree | bc9e486906d47fac29d8d0f1e8c8915d2bf5ab9f /vm.c | |
| parent | ab5ef5a77af9f2fc7c3353f05bf716b1a6b93f73 (diff) | |
Added == operator
Diffstat (limited to 'vm.c')
| -rw-r--r-- | vm.c | 25 |
1 files changed, 23 insertions, 2 deletions
@@ -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); |
