diff options
| author | EuAndreh <eu@euandre.org> | 2025-07-11 21:26:16 -0300 |
|---|---|---|
| committer | EuAndreh <eu@euandre.org> | 2025-07-11 21:48:39 -0300 |
| commit | 0f5b23bbcde9324c02f033da078677553c923d16 (patch) | |
| tree | 4c33c77c1d933f8ac0fb895480ebe68d10588234 | |
| parent | src/paca.mjs (tokenizeRegexStep): Fix missing concat when escaping (diff) | |
| download | paca-0f5b23bbcde9324c02f033da078677553c923d16.tar.gz paca-0f5b23bbcde9324c02f033da078677553c923d16.tar.xz | |
tests/paca.mjs (test_tokenizeRegexStep): Simplify table values
Diffstat (limited to '')
| -rw-r--r-- | tests/paca.mjs | 1026 |
1 files changed, 322 insertions, 704 deletions
diff --git a/tests/paca.mjs b/tests/paca.mjs index 0c69547..0ba2d61 100644 --- a/tests/paca.mjs +++ b/tests/paca.mjs @@ -1,4 +1,4 @@ -import { explode, reduced, runTests } from "sjs"; +import { explode, reduced, reductions, runTests } from "sjs"; import { SyntaxError, @@ -108,805 +108,423 @@ const test_numFromDigits = t => { const test_tokenizeRegexStep = t => { t.start("tokenizeRegexStep()"); + const cat = { operator: "concat" }; + const union = { operator: "|" }; + const oparen = { operator: "(" }; + const cparen = { operator: ")" }; + const star = { operator: "*" }; + + t.testing("when escaping we get whatever the char is", () => { - const regex = "ab|(cd)*" + const regex = "ab\\|\\(cd\\)\\*"; const stepFn = tokenizeRegexStep(regex); const steps = [{ - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ESCAPING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["b"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["|"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["("], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", cat], + state: ConcatStep.ESCAPING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["c", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", cat, "|", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["d"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", cat, "|", cat], + state: ConcatStep.ESCAPING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: [")"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", cat, "|", cat, "(", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["*"], - state: ConcatStep.ACCEPTING, - context: null, - }, - }]; - for (const i in regex) { - const step = steps[i]; - const char = regex[i]; - t.assertEq( - stepFn(step.in, char, Number(i)), - step.out, - ); - } - }); - - t.testing("escape makes it enter escaping mode", () => { - const regex = "\\a\\*"; - const stepFn = tokenizeRegexStep(regex); - const steps = [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, + out: [ + "a", cat, "b", cat, "|", cat, "(", cat, "c", + cat, + ], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [ + "a", cat, "b", cat, "|", cat, "(", cat, "c", + cat, "d", cat, + ], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, + out: [ + "a", cat, "b", cat, "|", cat, "(", cat, "c", + cat, "d", cat, + ], + state: ConcatStep.ESCAPING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ESCAPING, - context: null, - }, - out: { - out: ["*"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [ + "a", cat, "b", cat, "|", cat, "(", cat, "c", + cat, "d", cat, ")", cat, + ], + state: ConcatStep.ACCEPTING, + context: null, + }, { + out: [ + "a", cat, "b", cat, "|", cat, "(", cat, "c", + cat, "d", cat, ")", cat, + ], + state: ConcatStep.ESCAPING, + context: null, + }, { + out: [ + "a", cat, "b", cat, "|", cat, "(", cat, "c", + cat, "d", cat, ")", cat, "*", + ], + state: ConcatStep.ACCEPTING, + context: null, }]; - for (const i in regex) { - const step = steps[i]; - const char = regex[i]; - t.assertEq( - stepFn(step.in, char, Number(i)), - step.out, - ); - } + const given = reductions( + steps, + (acc, el, i) => { + const ret = stepFn(acc, regex[i], i); + t.assertEq(ret, el); + return ret; + }, + ); + t.assertEq(given, steps); }); t.testing("operators get detected as such", () => { const regex = "ab|(cd)*"; const stepFn = tokenizeRegexStep(regex); const steps = [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["b"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [{ operator: "|" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b"], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [{ operator: "(" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", union], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["c", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", union, oparen], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["d"], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", union, oparen, "c", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [{ operator: ")" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: ["a", cat, "b", union, oparen, "c", cat, "d"], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [{ operator: "*" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [ + "a", cat, "b", union, oparen, "c", cat, "d", + cparen, + ], + state: ConcatStep.ACCEPTING, + context: null, + }, { + out: [ + "a", cat, "b", union, oparen, "c", cat, "d", + cparen, star + ], + state: ConcatStep.ACCEPTING, + context: null, }]; - for (const i in regex) { - const step = steps[i]; - const char = regex[i]; - t.assertEq( - stepFn(step.in, char, Number(i)), - step.out, - ); - } + const given = reductions( + steps, + (acc, el, i) => { + const ret = stepFn(acc, regex[i], i); + t.assertEq(ret, el); + return ret; + }, + ); + t.assertEq(given, steps); }); - t.testing("multichar range operator {m,n} is parsed", () => { + t.testing("multichar range operator {m,n} is parsed right", () => { const table = [{ regex: "a{1,2}", steps: [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "from", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "to", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1" ], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "to", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [ "2" ], - where: "to", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1" ], + to: [], + where: "to", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [ "2" ], - where: "to", - }, - }, - out: { - out: [{ - operator: "range", - from: 1, - to: 2, - }], - state: ConcatStep.ACCEPTING, - context: null, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1" ], + to: [ "2" ], + where: "to", }, + }, { + out: ["a", cat, { + operator: "range", + from: 1, + to: 2, + }], + state: ConcatStep.ACCEPTING, + context: null, }], }, { regex: "a{,2}", steps: [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "to", - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "to", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [ "2" ], - where: "to", - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "to", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [ "2" ], - where: "to", - }, - }, - out: { - out: [{ - operator: "range", - from: -1, - to: 2, - }], - state: ConcatStep.ACCEPTING, - context: null, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [], + to: [ "2" ], + where: "to", }, + }, { + out: ["a", cat, { + operator: "range", + from: -1, + to: 2, + }], + state: ConcatStep.ACCEPTING, + context: null, }], }, { regex: "a{1,}", steps: [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "from", - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "to", - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [ "1" ], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "to", - }, - }, - out: { - out: [{ - operator: "range", - from: 1, - to: -1, - }], - state: ConcatStep.ACCEPTING, - context: null, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [ "1" ], + to: [], + where: "to", }, + }, { + out: ["a", cat, { + operator: "range", + from: 1, + to: -1, + }], + state: ConcatStep.ACCEPTING, + context: null, }], }, { regex: "a{,}", steps: [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "to", - }, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "to", - }, - }, - out: { - out: [{ - operator: "range", - from: -1, - to: -1, - }], - state: ConcatStep.ACCEPTING, - context: null, + out: ["a", { operator: "concat" }], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "to", }, + }, { + out: ["a", cat, { + operator: "range", + from: -1, + to: -1, + }], + state: ConcatStep.ACCEPTING, + context: null, }], }, { regex: "a{123,456}", steps: [{ - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: ["a", { operator: "concat" }], - state: ConcatStep.ACCEPTING, - context: null, - }, + out: [], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.ACCEPTING, - context: null, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, + out: ["a", cat], + state: ConcatStep.ACCEPTING, + context: null, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "from", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1" ], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2" ], - to: [], - where: "from", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1" ], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2" ], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [], - where: "from", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1", "2" ], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [], - where: "from", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [], - where: "to", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1", "2", "3" ], + to: [], + where: "from", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [], - where: "to", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [ "4" ], - where: "to", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1", "2", "3" ], + to: [], + where: "to", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [ "4" ], - where: "to", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [ "4", "5" ], - where: "to", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1", "2", "3" ], + to: [ "4" ], + where: "to", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [ "4", "5" ], - where: "to", - }, - }, - out: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [ "4", "5", "6" ], - where: "to", - }, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1", "2", "3" ], + to: [ "4", "5" ], + where: "to", }, }, { - in: { - out: [], - state: ConcatStep.RANGE, - context: { - from: [ "1", "2", "3" ], - to: [ "4", "5", "6" ], - where: "to", - }, - }, - out: { - out: [{ - operator: "range", - from: 123, - to: 456, - }], - state: ConcatStep.ACCEPTING, - context: null, + out: ["a", cat], + state: ConcatStep.RANGE, + context: { + from: [ "1", "2", "3" ], + to: [ "4", "5", "6" ], + where: "to", }, + }, { + out: ["a", cat, { + operator: "range", + from: 123, + to: 456, + }], + state: ConcatStep.ACCEPTING, + context: null, }], }]; - for (const case_ of table) { - const stepFn = tokenizeRegexStep(case_.regex); - for (const i in case_.regex) { - const step = case_.steps[i]; - const char = case_.regex[i]; - t.assertEq( - stepFn(step.in, char, Number(i)), - step.out, - ); - } + for (const { regex, steps } of table) { + const stepFn = tokenizeRegexStep(regex); + const given = reductions( + steps, + (acc, el, i) => { + const ret = stepFn(acc, regex[i], i); + t.assertEq(ret, el); + return ret; + }, + ); + t.assertEq(given, steps); } }); }; |
