From 9341081a4dd414171e16210bc55c0112e8ba3134 Mon Sep 17 00:00:00 2001 From: Autumn! Date: Mon, 12 Sep 2022 23:05:31 +0100 Subject: [PATCH] Made peg 'not' and 'if-not' drop their captures on success --- src/core/peg.c | 32 +++++++++++++++++++++++++++----- test/suite0014.janet | 20 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 test/suite0014.janet diff --git a/src/core/peg.c b/src/core/peg.c index 8bfbb348..a5af27eb 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -261,24 +261,46 @@ tail: goto tail; } - case RULE_IF: - case RULE_IFNOT: { + case RULE_IF: { const uint32_t *rule_a = s->bytecode + rule[1]; const uint32_t *rule_b = s->bytecode + rule[2]; down1(s); const uint8_t *result = peg_rule(s, rule_a, text); up1(s); - if (rule[0] == RULE_IF ? !result : !!result) return NULL; + if (!result) return NULL; rule = rule_b; goto tail; } + case RULE_IFNOT: { + const uint32_t *rule_a = s->bytecode + rule[1]; + const uint32_t *rule_b = s->bytecode + rule[2]; + down1(s); + CapState cs = cap_save(s); + const uint8_t *result = peg_rule(s, rule_a, text); + if (!!result) { + up1(s); + return NULL; + } else { + cap_load(s, cs); + up1(s); + rule = rule_b; + goto tail; + } + } case RULE_NOT: { const uint32_t *rule_a = s->bytecode + rule[1]; down1(s); + CapState cs = cap_save(s); const uint8_t *result = peg_rule(s, rule_a, text); - up1(s); - return (result) ? NULL : text; + if (result) { + up1(s); + return NULL; + } else { + cap_load(s, cs); + up1(s); + return text; + } } case RULE_THRU: diff --git a/test/suite0014.janet b/test/suite0014.janet new file mode 100644 index 00000000..c4fb40fa --- /dev/null +++ b/test/suite0014.janet @@ -0,0 +1,20 @@ +(import ./helper :prefix "" :exit true) +(start-suite 14) + +(assert (deep= + (peg/match '(not (* (constant 7) "a")) "hello") + @[]) "peg not") + +(assert (deep= + (peg/match '(if-not (* (constant 7) "a") "hello") "hello") + @[]) "peg if-not") + +(assert (deep= + (peg/match '(if-not (drop (* (constant 7) "a")) "hello") "hello") + @[]) "peg if-not drop") + +(assert (deep= + (peg/match '(if (not (* (constant 7) "a")) "hello") "hello") + @[]) "peg if not") + +(end-suite)