aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-14 18:31:29 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-14 18:31:29 +0530
commit70578d77d284b93f49b2918318c8a972521efb46 (patch)
tree7dd16ffb6b206e7ec8be9c6aa27df90ad726013a
parentd10c241332cf14a0b9171739a76cbdafdbdf2826 (diff)
downloadelxr-70578d77d284b93f49b2918318c8a972521efb46.tar.gz
elxr-70578d77d284b93f49b2918318c8a972521efb46.zip
fix: fixes quantifiers nested inside sequence
-rw-r--r--src/eval/index.ts46
-rw-r--r--tests/basic.spec.ts47
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,
+ },
])
})
})