diff options
Diffstat (limited to '')
| -rw-r--r-- | src/paca.mjs | 22 | ||||
| -rw-r--r-- | tests/paca.mjs | 74 |
2 files changed, 72 insertions, 24 deletions
diff --git a/src/paca.mjs b/src/paca.mjs index 7a01407..ccff1ca 100644 --- a/src/paca.mjs +++ b/src/paca.mjs @@ -24,7 +24,7 @@ const shouldConcat = (char, next) => char !== "{" && !nonConcatOperators.has(next); -const operatorChars = new Set([...nonConcatOperators, "(", "."]); +const operatorChars = new Set([...nonConcatOperators, "("]); const isOperator = char => operatorChars.has(char); @@ -167,8 +167,8 @@ const classStateStep = ({ out, state, context }, char, _index, _next) => { return { out: out.concat({ - operator: "class", - set: context.set, + meta: "class", + set: context.set, }), state: ConcatStep.ACCEPTING, context: null, @@ -327,6 +327,15 @@ const transitionChars = new Set(Object.keys(TRANSITION_FNS)); const isTransition = char => transitionChars.has(char); +const metaChars = new Set(["."]); +const isMeta = char => + metaChars.has(char); + +const opFor = char => + isOperator(char) ? { operator: char } + : isMeta(char) ? { meta: char } + : char; + const tokenizeRegexStep = chars => ({ out, state, context }, char, index) => { const next = chars[index + 1]; @@ -357,10 +366,9 @@ const tokenizeRegexStep = chars => ({ out, state, context }, char, index) => { ); } - const op = isOperator(char) ? { operator: char } : char; return { out: out.concat( - op, + opFor(char), shouldConcat(char, next) ? [{ operator: "concat" }] : [], @@ -398,8 +406,6 @@ const PRECEDENCE = { "range": 3, "concat": 2, "|": 1, - "class": 1, - ".": 1, }; const shouldPush = (stack, token) => @@ -414,7 +420,7 @@ const findLowerPrecedenceItem = (stack, token) => ); const toPostfixStep = ({ out, stack }, token, _index, tokens) => { - if (typeof token === "string") { + if (!token.operator) { return { out: out.concat(token), stack, diff --git a/tests/paca.mjs b/tests/paca.mjs index 789f959..55185f7 100644 --- a/tests/paca.mjs +++ b/tests/paca.mjs @@ -94,7 +94,6 @@ const test_isOperator = t => { t.assertEq(isOperator("?"), true); t.assertEq(isOperator("("), true); t.assertEq(isOperator(")"), true); - t.assertEq(isOperator("."), true); }); t.testing("false for everyday non-meta chars", () => { @@ -356,8 +355,8 @@ const test_classStateStep = t => { ); const expected = { out: [ 1, 2, 3, { - operator: "class", - set: [ 4, 5, 6 ], + meta: "class", + set: [ 4, 5, 6 ], }], state: "accepting", context: null, @@ -912,22 +911,22 @@ const test_tokenizeRegexStep = t => { }, }, { out: [caret, { - operator: "class", - set: [ "b", "e", "h", "i", "l", "o", "s" ], + meta: "class", + set: [ "b", "e", "h", "i", "l", "o", "s" ], }], state: "accepting", context: null, }, { out: [caret, { - operator: "class", - set: [ "b", "e", "h", "i", "l", "o", "s" ], + meta: "class", + set: [ "b", "e", "h", "i", "l", "o", "s" ], }, star], state: "accepting", context: null, }, { out: [caret, { - operator: "class", - set: [ "b", "e", "h", "i", "l", "o", "s" ], + meta: "class", + set: [ "b", "e", "h", "i", "l", "o", "s" ], }, star, dollar], state: "accepting", context: null, @@ -1444,6 +1443,29 @@ const test_toPostfixStep = t => { ); }); + t.testing("non-operators go directly to out", () => { + t.assertEq( + toPostfixStep( + { out: ["a"], stack: [{ operator: "(" }] }, + { meta: "." }, + ), + { + out: ["a", { meta: "." }], + stack: [{ operator: "(" }], + }, + ); + t.assertEq( + toPostfixStep( + { out: ["a"], stack: [{ operator: "*" }] }, + { meta: "class" }, + ), + { + out: ["a", { meta: "class" }], + stack: [{ operator: "*" }], + }, + ); + }); + t.testing("parens put things on the stack", () => { t.assertEq( toPostfixStep({ @@ -1628,7 +1650,8 @@ const test_toPostfix = t => { t.start("toPostfix()"); t.testing("regex table", () => { - const concat = { operator: "concat" }; + const concat = { operator: "concat" }; + const wildcard = { meta: "." }; const table = [{ in: [], expected: [] @@ -1693,6 +1716,25 @@ const test_toPostfix = t => { ], expected: [ ], + }, { + in: [ + "a", + concat, + "b", + concat, + wildcard, + concat, + "c", + ], + expected: [ + "a", + "b", + concat, + wildcard, + concat, + "c", + concat, + ], }]; for (const test of table) { t.assertEq( @@ -2006,7 +2048,7 @@ const test_zeroOrOne = t => { const test_OPERATORS_FNS = t => { t.start("OPERATORS_FNS"); - const arr = []; + let arr = []; const fn = ret => (...args) => { arr.push({ args, @@ -2018,7 +2060,7 @@ const test_OPERATORS_FNS = t => { t.testing("star", () => { - arr.splice(0); + arr = []; t.assertEq( OPERATORS_FNS({ zeroOrMoreFn: fn(111) })["*"](input), [1, 2, 111], @@ -2027,7 +2069,7 @@ const test_OPERATORS_FNS = t => { }); t.testing("plus", () => { - arr.splice(0); + arr = []; t.assertEq( OPERATORS_FNS({ oneOrMoreFn: fn(222) })["+"](input), [1, 2, 222], @@ -2036,7 +2078,7 @@ const test_OPERATORS_FNS = t => { }); t.testing("question mark", () => { - arr.splice(0); + arr = []; t.assertEq( OPERATORS_FNS({ zeroOrOneFn: fn(333) })["?"](input), [1, 2, 333], @@ -2045,7 +2087,7 @@ const test_OPERATORS_FNS = t => { }); t.testing("pipe", () => { - arr.splice(0); + arr = []; t.assertEq( OPERATORS_FNS({ unionFn: fn(444) })["|"](input), [1, 444], @@ -2054,7 +2096,7 @@ const test_OPERATORS_FNS = t => { }); t.testing("concat", () => { - arr.splice(0); + arr = []; t.assertEq( OPERATORS_FNS({ concatFn: fn(555) })["concat"](input), [1, 555], |
