diff options
| author | Akshay Nair <phenax5@gmail.com> | 2022-01-14 18:31:29 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2022-01-14 18:31:29 +0530 |
| commit | 70578d77d284b93f49b2918318c8a972521efb46 (patch) | |
| tree | 7dd16ffb6b206e7ec8be9c6aa27df90ad726013a | |
| parent | d10c241332cf14a0b9171739a76cbdafdbdf2826 (diff) | |
| download | elxr-70578d77d284b93f49b2918318c8a972521efb46.tar.gz elxr-70578d77d284b93f49b2918318c8a972521efb46.zip | |
fix: fixes quantifiers nested inside sequence
| -rw-r--r-- | src/eval/index.ts | 46 | ||||
| -rw-r--r-- | tests/basic.spec.ts | 47 |
2 files changed, 74 insertions, 19 deletions
diff --git a/src/eval/index.ts b/src/eval/index.ts index efede36..26a3ec5 100644 --- a/src/eval/index.ts +++ b/src/eval/index.ts @@ -10,7 +10,7 @@ import { some, } from 'fp-ts/lib/Option' import { Expr, ListExpr, Literal } from '../types' -import { match } from '../utils' +import { jlog, match } from '../utils' export interface MatchGroupIndexed<T = any> { value: T @@ -28,6 +28,16 @@ const group = <T>(value: T, index: number): MatchGroupIndexed<T> => ({ type index = number +const accumulateSkip = () => { + const skipIndexes = [] as index[] + return { + localSkip: + (i: index) => + <T>(x: T): T => (skipIndexes.push(i), x), + getSkips: () => skipIndexes, + } +} + const checkExpr = <T>( expr: Expr, item: T, @@ -58,8 +68,7 @@ const checkExpr = <T>( Group: ({ exprs }) => { const [head, ...tail] = exprs - const skipIndexes = [] as index[] - const localSkip = (i: index) => (x: any) => (skipIndexes.push(i), x) + const { getSkips, localSkip } = accumulateSkip() const matches = tail.reduce( (acc, exp) => pipe( @@ -78,16 +87,15 @@ const checkExpr = <T>( return pipe( matches, getOrElseW(() => []), - skip(Math.max(...skipIndexes) || 1), + skip(Math.max(...getSkips()) || 1), ) }, Or: ({ exprs }) => { - const match = exprs.find(expr => checkExpr(expr, item, list, index).length > 0) - return pipe( - match ? [group(item, index)] : [], - skip(1), + const match = exprs.find( + expr => checkExpr(expr, item, list, index).length > 0, ) + return pipe(match ? [group(item, index)] : [], skip(1)) }, PropertyMatch: ({ name, expr }) => @@ -112,26 +120,30 @@ const checkExpr = <T>( }, Sequence: ({ exprs }) => { + const { getSkips, localSkip } = accumulateSkip() const getGroups = () => { if (exprs.length > list.length) return [] - - const indexed = <T>(ls: T[]): Array<[number, T]> => ls.map((x, i) => [i, x]) + const indexed = <T>(ls: T[]): Array<[number, T]> => + ls.map((x, i) => [i, x]) const result = pipe( - zipWith(exprs, indexed(list), (expr, [i, val]) => checkExpr(expr, val, list, index + i)), + zipWith(exprs, indexed(list), (expr, [i, val]) => + checkExpr(expr, val, list.slice(i), index + i, localSkip), + ), filter(matches => !!matches.length), ) if (result.length !== exprs.length) return [] return [group(result, index)] - }; + } - return pipe( - getGroups(), - skip(exprs.length || 1), - ) + const groups = getGroups() + const skips = Math.max(1, getSkips().reduce((a, b) => a + b, -1)) + return pipe(groups, skip(skips)) }, - _: _ => { throw new Error(`TODO: ${expr.tag} not implemented for match`) }, + _: _ => { + throw new Error(`TODO: ${expr.tag} not implemented for match`) + }, }), ) } diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts index 482428a..72c7b40 100644 --- a/tests/basic.spec.ts +++ b/tests/basic.spec.ts @@ -123,11 +123,54 @@ describe('Basic tests', () => { it('should match sequence of matchers', () => { expect( + matchAll(/ [seperator true], [id \s\T]+ /, [ + // FIXME: Sequence doesn't work with Quantifiers + { seperator: true }, + { id: '1' }, + { id: '2' }, + { id: '3' }, + { seperator: true }, + { id: '4' }, + { id: '5' }, + { id: '6' }, + ]).groups, + ).toEqual([ + { + index: 0, + value: [ + [{ value: { seperator: true }, index: 0 }], + [{ value: [{ id: '1' }, { id: '2' }, { id: '3' }], index: 1 }], + ], + }, + { + index: 4, + value: [ + [{ value: { seperator: true }, index: 4 }], + [{ value: [{ id: '4' }, { id: '5' }, { id: '6' }], index: 5 }], + ], + }, + ]) + + expect( matchAll(/ true, \n, \s /, [true, 5, 'five', 1, 2, 3, true, 7, 'seven']) .groups, ).toEqual([ - { value: [ [{ value: true, index: 0 }], [{ value: 5, index: 1 }], [{ value: 'five', index: 2 }] ], index: 0 }, - { value: [ [{ value: true, index: 6 }], [{ value: 7, index: 7 }], [{ value: 'seven', index: 8 }] ], index: 6 }, + { + value: [ + [{ value: true, index: 0 }], + [{ value: 5, index: 1 }], + [{ value: 'five', index: 2 }], + ], + index: 0, + }, + { + value: [ + [{ value: true, index: 6 }], + [{ value: 7, index: 7 }], + [{ value: 'seven', index: 8 }], + ], + index: 6, + }, ]) }) }) |
