aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-08 21:17:10 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-08 21:17:10 +0530
commitb3b2c39df680f88e1e6d3615245754ae5f0380d0 (patch)
tree4af350ce393244d2c8dbcfdb0bd46cbb91ee41ef
parente246f2341ee13926f4273c6d634cef4fe07f040e (diff)
downloadelxr-b3b2c39df680f88e1e6d3615245754ae5f0380d0.tar.gz
elxr-b3b2c39df680f88e1e6d3615245754ae5f0380d0.zip
feat(eval): implements object property matching
-rw-r--r--src/eval/index.ts38
-rw-r--r--src/parser/index.ts30
-rw-r--r--src/parser/utils.ts16
-rw-r--r--tests/eval.spec.ts34
-rw-r--r--tests/parser.spec.ts5
5 files changed, 84 insertions, 39 deletions
diff --git a/src/eval/index.ts b/src/eval/index.ts
index f80c04d..b4dcf48 100644
--- a/src/eval/index.ts
+++ b/src/eval/index.ts
@@ -1,23 +1,27 @@
-import {pipe} from 'fp-ts/function';
+import { pipe } from 'fp-ts/function'
import { Expr, ListExpr } from '../types'
-import {match} from '../utils';
+import { match } from '../utils'
export const find = <T>([startO, exprs, endO]: ListExpr, list: T[]): any => {
- const check = (expr: Expr) => <T>(x: T, i: number, ls: T[]): boolean => {
- return pipe(
- expr,
- match<boolean, Expr>({
- AnyItem: _ => true,
- AnyNumber: _ => typeof x === 'number',
- AnyString: _ => typeof x === 'string',
- AnyBool: _ => typeof x === 'boolean',
- Truthy: _ => !!x,
- Falsey: _ => !x,
- Group: ({ exprs }) => exprs.every(e => check(e)(x, i, ls)),
- _: _ => false,
- })
- )
- };
+ const check =
+ (expr: Expr) =>
+ <T>(x: T, i: number, ls: T[]): boolean => {
+ return pipe(
+ expr,
+ match<boolean, Expr>({
+ AnyItem: _ => true,
+ AnyNumber: _ => typeof x === 'number',
+ AnyString: _ => typeof x === 'string',
+ AnyBool: _ => typeof x === 'boolean',
+ Truthy: _ => !!x,
+ Falsey: _ => !x,
+ Group: ({ exprs }) => exprs.every(e => check(e)(x, i, ls)),
+ PropertyMatch: ({ name, exprs }) =>
+ name in x && exprs.every(e => check(e)(x[name], i, ls)),
+ _: _ => false,
+ }),
+ )
+ }
const cs = exprs.map(check)
diff --git a/src/parser/index.ts b/src/parser/index.ts
index 2f5781e..386fa94 100644
--- a/src/parser/index.ts
+++ b/src/parser/index.ts
@@ -30,8 +30,8 @@ const anyBool = mapTo(symbol('\\b'), _ => Expr.AnyBool(null))
const truthy = mapTo(symbol('\\T'), _ => Expr.Truthy(null))
const falsey = mapTo(symbol('\\F'), _ => Expr.Falsey(null))
-const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
- chain(([expr, input]) =>
+const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
+ ([expr, input]) =>
pipe(
input,
or([
@@ -41,7 +41,7 @@ const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
]),
orElse(_ => right([expr, input])),
),
- )
+)
const wrapAlt: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
([expr, input]) =>
@@ -63,12 +63,18 @@ export const propertyName: Parser<string> = pipe(
p => suffixed(p, whitespaces0),
)
-const objectProperty = (input: string) => pipe(
- input,
- mapTo(delimited(symbol('['), pair(propertyName, many0(expressionP)), symbol(']')), ([name, exprs]) =>
- Expr.PropertyMatch({ name, exprs }),
- ),
-)
+const objectProperty = (input: string) =>
+ pipe(
+ input,
+ mapTo(
+ delimited(
+ symbol('['),
+ pair(propertyName, many0(expressionP)),
+ symbol(']'),
+ ),
+ ([name, exprs]) => Expr.PropertyMatch({ name, exprs }),
+ ),
+ )
const expressionP: Parser<Expr> = (input: string) =>
pipe(
@@ -90,7 +96,11 @@ const expressionP: Parser<Expr> = (input: string) =>
wrapAlt,
)
-export const parser: Parser<ListExpr> = tuple3(optional(start), many1(expressionP), optional(end))
+export const parser: Parser<ListExpr> = tuple3(
+ optional(start),
+ many1(expressionP),
+ optional(end),
+)
/*
diff --git a/src/parser/utils.ts b/src/parser/utils.ts
index 9e05286..841d77c 100644
--- a/src/parser/utils.ts
+++ b/src/parser/utils.ts
@@ -40,14 +40,16 @@ export const many0 = <T>(parser: Parser<T>): Parser<Array<T>> =>
)
export const many1 = <T>(parser: Parser<T>): Parser<Array<T>> =>
- recoverInput(flow(
- many0(parser),
- chain(([res, inp]) =>
- res.length > 0
- ? right([res, inp])
- : left([`many1 failed to parse at ${inp}`, inp]),
+ recoverInput(
+ flow(
+ many0(parser),
+ chain(([res, inp]) =>
+ res.length > 0
+ ? right([res, inp])
+ : left([`many1 failed to parse at ${inp}`, inp]),
+ ),
),
- ))
+ )
const recoverInput =
<T>(p: Parser<T>): Parser<T> =>
diff --git a/tests/eval.spec.ts b/tests/eval.spec.ts
index 9bf3000..dada762 100644
--- a/tests/eval.spec.ts
+++ b/tests/eval.spec.ts
@@ -10,14 +10,14 @@ describe('Eval', () => {
const liexp: ListExpr = [
none,
- [ Expr.AnyNumber(null), Expr.Truthy(null) ],
+ [Expr.AnyNumber(null), Expr.Truthy(null)],
none,
]
expect(find(liexp, list)).toEqual([1, 3, 5])
const liexp2: ListExpr = [
none,
- [ Expr.Falsey(null), Expr.Truthy(null) ],
+ [Expr.Falsey(null), Expr.Truthy(null)],
none,
]
expect(find(liexp2, list)).toEqual([])
@@ -28,10 +28,36 @@ describe('Eval', () => {
const liexp: ListExpr = [
none,
- [ Expr.AnyItem(null), Expr.Group({ exprs: [ Expr.AnyNumber(null), Expr.Truthy(null)] }) ],
+ [
+ Expr.AnyItem(null),
+ Expr.Group({ exprs: [Expr.AnyNumber(null), Expr.Truthy(null)] }),
+ ],
none,
]
expect(find(liexp, list)).toEqual([1, 3, 5])
})
-})
+ it('object property', () => {
+ const list = [
+ { name: 20, age: 'hello' },
+ { name: 'gello', age: 20 },
+ { name: '', age: 20 },
+ { name: 'Wow' },
+ { age: 20 },
+ ]
+
+ const liexp: ListExpr = [
+ none,
+ [
+ Expr.PropertyMatch({
+ name: 'name',
+ exprs: [Expr.AnyString(null), Expr.Truthy(null)],
+ }),
+ Expr.PropertyMatch({ name: 'age', exprs: [Expr.AnyNumber(null)] }),
+ ],
+ none,
+ ]
+
+ expect(find(liexp, list)).toEqual([{ name: 'gello', age: 20 }])
+ })
+})
diff --git a/tests/parser.spec.ts b/tests/parser.spec.ts
index 1ebd290..4db0894 100644
--- a/tests/parser.spec.ts
+++ b/tests/parser.spec.ts
@@ -91,7 +91,10 @@ describe('Foobar', () => {
[
none,
[
- Expr.PropertyMatch({ name: 'name', exprs: [Expr.AnyString(null), Expr.Truthy(null)] }),
+ Expr.PropertyMatch({
+ name: 'name',
+ exprs: [Expr.AnyString(null), Expr.Truthy(null)],
+ }),
Expr.PropertyMatch({ name: 'age', exprs: [Expr.AnyNumber(null)] }),
],
none,