aboutsummaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2020-09-14 01:21:49 -0700
committerBruce Hill <bruce@bruce-hill.com>2020-09-14 01:21:49 -0700
commita82164505e89dc8257ef87844dfef1476e235a7f (patch)
treef545e4a76b0ff0472bf6046b951230672ad18ce4 /vm.c
parent9f2d5464d6fd2c2aeb6dc234c64bd3aafe22d6e0 (diff)
Added nodent support (|)
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/vm.c b/vm.c
index 2a44dd7..9974547 100644
--- a/vm.c
+++ b/vm.c
@@ -30,6 +30,7 @@ static const char *opcode_names[] = {
[VM_EQUAL] = "EQUAL",
[VM_REF] = "REF",
[VM_BACKREF] = "BACKREF",
+ [VM_NODENT] = "NODENT",
};
const char *opcode_name(enum VMOpcode o)
@@ -337,6 +338,35 @@ static match_t *_match(grammar_t *g, const char *str, vm_op_t *op, recursive_ref
case VM_BACKREF: {
return match_backref(str, op, (match_t*)op->args.backref);
}
+ case VM_NODENT: {
+ if (str[-1] == '\0') { // First line
+ match_t *m = calloc(sizeof(match_t), 1);
+ m->start = str;
+ m->end = str;
+ m->op = op;
+ return m;
+ } else if (str[-1] != '\n') {
+ return NULL; // Not at beginning of line
+ }
+ const char *p = &str[-1];
+ while (*p == '\n') --p; // Skip blank lines
+ while (p[-1] && p[-1] != '\n') --p; // Backtrack to start of last (nonblank) line
+ // Count indentation:
+ char denter = *p;
+ int dents = 0;
+ if (denter == ' ' || denter == '\t') {
+ for (; *p == denter; ++p) ++dents;
+ }
+ for (int i = 0; i < dents; i++) {
+ if (str[i] != denter) return NULL;
+ }
+
+ match_t *m = calloc(sizeof(match_t), 1);
+ m->start = str;
+ m->end = &str[dents];
+ m->op = op;
+ return m;
+ }
default: {
fprintf(stderr, "Unknown opcode: %d", op->op);
_exit(1);