From 70578d77d284b93f49b2918318c8a972521efb46 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 14 Jan 2022 18:31:29 +0530 Subject: fix: fixes quantifiers nested inside sequence --- src/eval/index.ts | 46 +++++++++++++++++++++++++++++----------------- 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 { value: T @@ -28,6 +28,16 @@ const group = (value: T, index: number): MatchGroupIndexed => ({ type index = number +const accumulateSkip = () => { + const skipIndexes = [] as index[] + return { + localSkip: + (i: index) => + (x: T): T => (skipIndexes.push(i), x), + getSkips: () => skipIndexes, + } +} + const checkExpr = ( expr: Expr, item: T, @@ -58,8 +68,7 @@ const checkExpr = ( 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 = ( 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 = ( }, Sequence: ({ exprs }) => { + const { getSkips, localSkip } = accumulateSkip() const getGroups = () => { if (exprs.length > list.length) return [] - - const indexed = (ls: T[]): Array<[number, T]> => ls.map((x, i) => [i, x]) + const indexed = (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 @@ -122,12 +122,55 @@ 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, + }, ]) }) }) -- cgit v1.3.1