diff options
| -rw-r--r-- | default.nix | 2 | ||||
| -rw-r--r-- | src/eval/index.ts | 41 | ||||
| -rw-r--r-- | src/index.ts | 5 | ||||
| -rw-r--r-- | src/parser/index.ts | 1 | ||||
| -rw-r--r-- | tests/basic.spec.ts | 31 | ||||
| -rw-r--r-- | tests/replace.spec.ts | 39 |
6 files changed, 108 insertions, 11 deletions
diff --git a/default.nix b/default.nix index 7b1a6c7..11ff735 100644 --- a/default.nix +++ b/default.nix @@ -5,8 +5,8 @@ mkShell rec { nodejs-16_x yarn efm-langserver - nodePackages.vls nodePackages.prettier + nodePackages.eslint nodePackages.typescript-language-server ]; } diff --git a/src/eval/index.ts b/src/eval/index.ts index b7f4de1..b1d55b9 100644 --- a/src/eval/index.ts +++ b/src/eval/index.ts @@ -2,7 +2,7 @@ import { identity, pipe } from 'fp-ts/function' import { filter, takeLeftWhile, zip, zipWith } from 'fp-ts/Array' import * as Option from 'fp-ts/Option' import { index, Expr, ListExpr, Literal } from '../types' -import { match } from '../utils' +import { jlog, match } from '../utils' export interface MatchGroupIndexed<T = any> { value: T @@ -25,7 +25,7 @@ const accumulateSkip = () => { return { localSkip: (i: index) => - <T>(x: T): T => (skipIndexes.push(i), x), + <T>(x: T): T => (skipIndexes.push(i), x), getSkips: () => skipIndexes, } } @@ -38,7 +38,7 @@ const checkExpr = <T>( skip: ( n: index, ) => (m: MatchGroupIndexed<any>[]) => MatchGroupIndexed<any>[] = _ => - identity, + identity, ): MatchGroupIndexed<any>[] => { return pipe( expr, @@ -144,7 +144,6 @@ const checkExpr = <T>( }, ZeroOrMore: ({ expr }) => { - // TODO: Nested quantified expressions? const matches = pipe( list, takeLeftWhile(a => checkExpr(expr, a, list, index).length > 0), @@ -168,10 +167,11 @@ const checkExpr = <T>( } const groups = getGroups() - const skips = Math.max( + const skips = groups.length === 0 ? 1 : Math.max( 1, - getSkips().reduce((a, b) => a + b, -1), + getSkips().reduce((a, b) => a + b, 0), ) + return pipe(groups, skip(skips)) }, @@ -193,8 +193,8 @@ export const matchAll = <T>( const next = (i: number = 1) => - (curMatch: MatchGroupIndexed[]) => - [...curMatch, ...check(index + i, ls.slice(i), expr)] + (curMatch: MatchGroupIndexed[]) => + [...curMatch, ...check(index + i, ls.slice(i), expr)] return checkExpr(expr, item, ls, index, next) } @@ -203,3 +203,28 @@ export const matchAll = <T>( groups: check(0, list, expr), } } + +export const replaceAll = <T>( + [startO, expr, endO]: ListExpr, + replacer: (v: T, match: MatchGroupIndexed<T>, i: index) => T[], + list: T[], +): T[] => { + const check = (index: number, ls: T[], expr: Expr): T[] => { + if (ls.length === 0) return [] + + const [item] = ls + + const next = + (skip: number = 1) => + (curMatch: MatchGroupIndexed[]): MatchGroupIndexed<T>[] => { + const [match] = curMatch + const vals = match ? replacer(item, match, index) : ls.slice(0, skip) + // console.log(i, curMatch, vals) + return [...vals, ...check(index + skip, ls.slice(skip), expr)] as any + } + + return checkExpr(expr, item, ls, index, next) as any + } + + return check(0, list, expr) +} diff --git a/src/index.ts b/src/index.ts index 5bcb4f9..1a52c95 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { flow, pipe } from 'fp-ts/function' import { fst } from 'fp-ts/Tuple' import * as ev from './eval' import { parser } from './parser' -import { ListExpr } from './types' +import { index, ListExpr } from './types' const toSourceString = (r: string | RegExp): string => typeof r === 'string' ? r : r.source @@ -19,3 +19,6 @@ export const liexp: (r: string | RegExp) => ListExpr = flow( export const matchAll = <T>(exp: string | RegExp, list: T[]) => pipe(exp, liexp, lxp => ev.matchAll(lxp, list)) + +export const replaceAll = <T>(exp: string | RegExp, replacer: (v: T, m: ev.MatchGroupIndexed<T>, i: index) => T[], list: T[]) => + pipe(exp, liexp, lxp => ev.replaceAll(lxp, replacer, list)) diff --git a/src/parser/index.ts b/src/parser/index.ts index ac5c8ed..cdb4af1 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -8,7 +8,6 @@ import { manyTill, mapTo, matchChar, - matchString, oneOf, optional, or, diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts index f02169c..67f63d6 100644 --- a/tests/basic.spec.ts +++ b/tests/basic.spec.ts @@ -219,6 +219,37 @@ describe('Basic tests', () => { index: 6, }, ]) + + expect( + matchAll(/"start", \s, \n/, [ + 1, + 'start', + 'x', + 2, + 'start', + 3, + 'start', + 'y', + 4, + ]).groups, + ).toEqual([ + { + value: [ + [{ value: 'start', index: 1 }], + [{ value: 'x', index: 2 }], + [{ value: 2, index: 3 }], + ], + index: 1, + }, + { + value: [ + [{ value: 'start', index: 6 }], + [{ value: 'y', index: 7 }], + [{ value: 4, index: 8 }], + ], + index: 6, + }, + ]) }) it('should match min-max quantified expressions', () => { diff --git a/tests/replace.spec.ts b/tests/replace.spec.ts new file mode 100644 index 0000000..dd82eaa --- /dev/null +++ b/tests/replace.spec.ts @@ -0,0 +1,39 @@ +import { jlog } from '../src/utils' +import { replaceAll } from '../src' + +describe('Basic tests', () => { + it('should', () => { + expect( + replaceAll(/"start", \s, \n/, _ => ['replaced'], [ + 1, + 'start', + 'x', + 2, + 'start', + 3, + 'start', + 'y', + 4, + ]), + ).toEqual([1, 'replaced', 'start', 3, 'replaced']) + }) + + it('should replace matching items', () => { + expect(replaceAll(/\F/, (_x, _i) => [69], [1, 5, 0, 0, 2, 9, 0])).toEqual([ + 1, 5, 69, 69, 2, 9, 69, + ]) + + expect( + replaceAll(/\s+/, (_x, m) => [(m.value as any).join(',')], [ + 1, + 'wow', + 'test', + [], + '0', + 2, + '', + 'nice', + ]), + ).toEqual([1, 'wow,test', [], '0', 2, ',nice']) + }) +}) |
