diff options
| -rw-r--r-- | src/eval/index.ts | 37 | ||||
| -rw-r--r-- | src/index.ts | 24 | ||||
| -rw-r--r-- | src/parser/index.ts | 64 | ||||
| -rw-r--r-- | tests/basic.spec.ts | 42 | ||||
| -rw-r--r-- | tests/eval.spec.ts | 74 |
5 files changed, 76 insertions, 165 deletions
diff --git a/src/eval/index.ts b/src/eval/index.ts index 26a3ec5..3bf0290 100644 --- a/src/eval/index.ts +++ b/src/eval/index.ts @@ -137,7 +137,10 @@ const checkExpr = <T>( } const groups = getGroups() - const skips = Math.max(1, getSkips().reduce((a, b) => a + b, -1)) + const skips = Math.max( + 1, + getSkips().reduce((a, b) => a + b, -1), + ) return pipe(groups, skip(skips)) }, @@ -169,35 +172,3 @@ export const matchAll = <T>( groups: check(0, list, expr), } } - -export const find = <T>([startO, expr, 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)), - PropertyMatch: ({ name, expr }) => - name in x && check(expr)(x[name], i, ls), - OneOrMore: ({ expr }) => { - // TODO: Nested quantified expression - const x = pipe( - list.slice(i), - takeLeftWhile(x => check(expr)(x, i, list)), - ) - return true - }, - _: _ => false, - }), - ) - } - - return list.filter((x, i, ls) => check(expr)(x, i, ls)) -} diff --git a/src/index.ts b/src/index.ts index db6630c..6c19fd3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,29 +1,21 @@ import { getOrElseW, map } from 'fp-ts/lib/Either' import { flow, pipe } from 'fp-ts/lib/function' -import {fst} from 'fp-ts/lib/Tuple' +import { fst } from 'fp-ts/lib/Tuple' import * as ev from './eval' import { parser } from './parser' -import {ListExpr} from './types' +import { ListExpr } from './types' -const toSourceString = (r: string | RegExp): string => typeof r === 'string' ? r : r.source +const toSourceString = (r: string | RegExp): string => + typeof r === 'string' ? r : r.source export const liexp: (r: string | RegExp) => ListExpr = flow( toSourceString, parser, map(fst), - getOrElseW(([e, _]) => { throw new Error(e) }) + getOrElseW(([e, _]) => { + throw new Error(e) + }), ) export const matchAll = <T>(exp: string | RegExp, list: T[]) => - pipe( - exp, - liexp, - lxp => ev.matchAll(lxp, list), - ) - -export const filter = <T>(exp: string | RegExp, list: T[]): T[] => - pipe( - exp, - liexp, - lxp => ev.find(lxp, list), - ) + pipe(exp, liexp, lxp => ev.matchAll(lxp, list)) diff --git a/src/parser/index.ts b/src/parser/index.ts index 50f2786..cbdc02b 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -22,8 +22,8 @@ import { whitespaces0, } from './utils' import { Expr, ListExpr, Literal } from '../types' -import {getOrElse, map} from 'fp-ts/lib/Option' -import {mapFst, snd} from 'fp-ts/lib/Tuple' +import { getOrElse, map } from 'fp-ts/lib/Option' +import { mapFst, snd } from 'fp-ts/lib/Tuple' const start = mapTo(symbol('^'), _ => Expr.Start()) const end = mapTo(symbol('$'), _ => Expr.End()) @@ -65,17 +65,20 @@ const objectProperty = (input: string) => pair(propertyName, many0(expressionP)), symbol(']'), ), - ([name, exprs]) => Expr.PropertyMatch({ name, expr: exprsToGroup(exprs) }), + ([name, exprs]) => + Expr.PropertyMatch({ name, expr: exprsToGroup(exprs) }), ), ) -const unsignedNum: Parser<number> = mapTo(pair(digits, optional(pair(matchChar('.'), digits))), ([int, decimal]) => - pipe( - decimal, - map(snd), - getOrElse(() => '0'), - n => parseFloat(`${int}.${n}`), - ) +const unsignedNum: Parser<number> = mapTo( + pair(digits, optional(pair(matchChar('.'), digits))), + ([int, decimal]) => + pipe( + decimal, + map(snd), + getOrElse(() => '0'), + n => parseFloat(`${int}.${n}`), + ), ) const numberLiteral: Parser<Literal> = mapTo( @@ -86,8 +89,7 @@ const numberLiteral: Parser<Literal> = mapTo( getOrElse(() => '+'), sign => (sign === '-' ? -1 : 1) * n, Literal.Number, - ) - , + ), ) const booleanLiteral: Parser<Literal> = mapTo(oneOf(['true', 'false']), b => @@ -100,25 +102,38 @@ const literalP: Parser<Literal> = delimited( whitespaces0, ) -const infixOp = (op: Parser<any>): Parser<Expr[]> => (input: string) => pipe( - input, - sepBy1(op, groupP), - chain(([exprs, nextInput]) => exprs.length === 1 - ? left(['Infix operator parsing error', input]) - : right([exprs, nextInput])), -) +const infixOp = + (op: Parser<any>): Parser<Expr[]> => + (input: string) => + pipe( + input, + sepBy1(op, groupP), + chain(([exprs, nextInput]) => + exprs.length === 1 + ? left(['Infix operator parsing error', input]) + : right([exprs, nextInput]), + ), + ) -const altP: Parser<Expr> = mapTo(infixOp(symbol('|')), exprs => Expr.Or({ exprs })) +const altP: Parser<Expr> = mapTo(infixOp(symbol('|')), exprs => + Expr.Or({ exprs }), +) -const sequenceP: Parser<Expr> = mapTo(infixOp(symbol(',')), exprs => Expr.Sequence({ exprs })) +const sequenceP: Parser<Expr> = mapTo(infixOp(symbol(',')), exprs => + Expr.Sequence({ exprs }), +) -const expressionP: Parser<Expr> = (input: string) => or([ altP, sequenceP, groupP ])(input) +const expressionP: Parser<Expr> = (input: string) => + or([altP, sequenceP, groupP])(input) const atomP: Parser<Expr> = (input: string) => pipe( input, or([ - mapTo(delimited(symbol('('), many1(expressionP), symbol(')')), exprsToGroup), + mapTo( + delimited(symbol('('), many1(expressionP), symbol(')')), + exprsToGroup, + ), objectProperty, anyItem, anyString, @@ -131,7 +146,8 @@ const atomP: Parser<Expr> = (input: string) => wrapQuantifiers, ) -const exprsToGroup = (exprs: Expr[]) => exprs.length === 1 ? exprs[0] : Expr.Group({ exprs }) +const exprsToGroup = (exprs: Expr[]) => + exprs.length === 1 ? exprs[0] : Expr.Group({ exprs }) const groupP: Parser<Expr> = mapTo(many1(atomP), exprsToGroup) export const parser: Parser<ListExpr> = tuple3( diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts index 72c7b40..6fb5921 100644 --- a/tests/basic.spec.ts +++ b/tests/basic.spec.ts @@ -1,24 +1,30 @@ -import { jlog } from '../src/utils' -import { filter, matchAll } from '../src' +import { matchAll } from '../src' describe('Basic tests', () => { - it('should filter shit', () => { - expect(filter(/\s/, [1, '2', 3, '4'])).toEqual(['2', '4']) - expect(filter(/\n/, [1, '2', 3, '4'])).toEqual([1, 3]) - expect(filter(/\T/, [1, 0, '4', ''])).toEqual([1, '4']) - expect(filter(/\F/, [1, 0, '4', ''])).toEqual([0, '']) - expect(filter(/\F\T/, [1, 0, '4', ''])).toEqual([]) - expect(filter(/\s\T/, [1, 0, '4', ''])).toEqual(['4']) - }) - - it('should do it', () => { - // jlog(matchAll(/[age \n]+/, [ {}, { age: 1 }, { age: 2 }, { age: 0 }, '' ])) - // jlog(matchAll(/[age \n]+/, [ {}, { age: 1 }, '' ])) - // jlog(matchAll(/([age \n])+/, [ {}, { age: 1 }, { age: 2 }, { age: 0 }, '' ])) - // jlog(matchAll(/\n+/, [ '', 1, 2, 0, '6', 5, '' ])) - }) - describe('matchAll', () => { + it('should filter shit', () => { + expect(matchAll(/\s/, [1, '2', 3, '4']).groups).toEqual([ + { value: '2', index: 1 }, + { value: '4', index: 3 }, + ]) + expect(matchAll(/\n/, [1, '2', 3, '4']).groups).toEqual([ + { value: 1, index: 0 }, + { value: 3, index: 2 }, + ]) + expect(matchAll(/\T/, [1, 0, '4', '']).groups).toEqual([ + { value: 1, index: 0 }, + { value: '4', index: 2 }, + ]) + expect(matchAll(/\F/, [1, 0, '4', '']).groups).toEqual([ + { value: 0, index: 1 }, + { value: '', index: 3 }, + ]) + expect(matchAll(/\F\T/, [1, 0, '4', '']).groups).toEqual([]) + expect(matchAll(/\s\T/, [1, 0, '4', '']).groups).toEqual([ + { value: '4', index: 2 }, + ]) + }) + it('should match literals', () => { expect( matchAll(/ -2.05 /, [2, NaN, -2.05, '-2.05', -2.05, 2.05]).groups, diff --git a/tests/eval.spec.ts b/tests/eval.spec.ts deleted file mode 100644 index ab91948..0000000 --- a/tests/eval.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { left, right } from 'fp-ts/Either' -import { none, some } from 'fp-ts/Option' -import { Expr, ListExpr } from '../src/types' -import { jlog } from '../src/utils' -import { find, matchAll } from '../src/eval' - -describe('Eval', () => { - it('should do stuff', () => { - const ls = [-1, 1, 2, '3', 4, '5', 6, 7, ''] - - const liexp: ListExpr = [ - none, - Expr.OneOrMore({ - expr: Expr.Group({ - exprs: [Expr.AnyNumber(), Expr.Truthy()], - }), - }), - none, - ] - - //jlog(matchAll(liexp, ls)) - }) - - it('basic evaluation', () => { - const list = [0, 1, '2', 3, [4], 5] - - const liexp: ListExpr = [none, Expr.Group({ exprs: [Expr.AnyNumber(), Expr.Truthy()] }), none] - expect(find(liexp, list)).toEqual([1, 3, 5]) - - const liexp2: ListExpr = [none, Expr.Group({ exprs: [Expr.Falsey(), Expr.Truthy()] }), none] - expect(find(liexp2, list)).toEqual([]) - }) - - it('with groups', () => { - const list = [0, 1, '2', 3, [4], 5] - - const liexp: ListExpr = [ - none, - Expr.Group({ exprs: [ - Expr.AnyItem(), - Expr.Group({ exprs: [Expr.AnyNumber(), Expr.Truthy()] }), - ] }), - 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.Group({ exprs: [ - Expr.PropertyMatch({ - name: 'name', - expr: Expr.Group({ exprs: [Expr.AnyString(), Expr.Truthy()] }), - }), - Expr.PropertyMatch({ - name: 'age', - expr: Expr.Group({ exprs: [Expr.AnyNumber()] }), - }), - ] }), - none, - ] - - expect(find(liexp, list)).toEqual([{ name: 'gello', age: 20 }]) - }) -}) |
