From b5893d68ce4eacbc3ae431ca48f821657236c7aa Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 14 Jan 2022 19:10:49 +0530 Subject: refactor: refactors imports + formatting --- TODO.md | 4 +-- package.json | 2 +- src/eval/index.ts | 28 +++++++------------- src/index.ts | 10 +++---- src/parser/index.ts | 29 ++++++++++----------- src/parser/utils.ts | 73 ++++++++++++++++++++++++---------------------------- src/types.ts | 49 ++++++++++++++++------------------- src/utils.ts | 2 +- tests/basic.spec.ts | 1 - tests/parser.spec.ts | 6 +---- 10 files changed, 90 insertions(+), 114 deletions(-) diff --git a/TODO.md b/TODO.md index c0aeca0..581b233 100644 --- a/TODO.md +++ b/TODO.md @@ -2,11 +2,11 @@ ## Features - [ ] Eval: Quantifiers - - [ ] Eval: Next item + - [X] Eval: Next item/Sequence - [ ] Parse: `{2, 5}` quantifiers - [ ] Eval: `^$` start-end - - [ ] Func: filter - [ ] Func: replace + - [X] Func: matchAll - [ ] Not/Inverse - [ ] Named capture groups - [ ] Non-capture groups diff --git a/package.json b/package.json index c27633e..0977c8f 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "scripts": { "tsc": "tsc --emitDeclarationOnly --outDir lib", "test": "jest", - "format": "prettier --write ./src/**/*.ts", + "format": "prettier --write ./src/**/*.ts ./tests/**/*.ts", "build": "rimraf lib && node ./esbuild.js && npm run tsc" }, "devDependencies": { diff --git a/src/eval/index.ts b/src/eval/index.ts index 3bf0290..f56ff92 100644 --- a/src/eval/index.ts +++ b/src/eval/index.ts @@ -1,16 +1,8 @@ import { identity, pipe } from 'fp-ts/function' -import { filter, takeLeftWhile, zip, zipWith } from 'fp-ts/lib/Array' -import { - chain, - getOrElseW, - isSome, - map, - none, - Option, - some, -} from 'fp-ts/lib/Option' -import { Expr, ListExpr, Literal } from '../types' -import { jlog, match } from '../utils' +import { filter, takeLeftWhile, zip, zipWith } from 'fp-ts/Array' +import * as Option from 'fp-ts/Option' +import { Expr, ListExpr } from '../types' +import { match } from '../utils' export interface MatchGroupIndexed { value: T @@ -73,20 +65,20 @@ const checkExpr = ( (acc, exp) => pipe( acc, - chain(ac => + Option.chain(ac => pipe( checkExpr(exp, item, list, index, localSkip), zip(ac), z => z.map(([res, _cur]) => res), - z => (z.length === 0 ? none : some(z)), + z => (z.length === 0 ? Option.none : Option.some(z)), ), ), ), - some(checkExpr(head, item, list, index, localSkip)), + Option.some(checkExpr(head, item, list, index, localSkip)), ) return pipe( matches, - getOrElseW(() => []), + Option.getOrElseW(() => []), skip(Math.max(...getSkips()) || 1), ) }, @@ -103,12 +95,12 @@ const checkExpr = ( Object.prototype.hasOwnProperty.call(item ?? {}, name) ? checkExpr(expr, item[name], list, index) : [], - res => (res.length > 0 ? [group(item, index)] : []), // FIXME: doesn't allow nested matching + res => (res.length > 0 ? [group(item, index)] : []), // TODO: doesn't allow nested matching skip(1), ), OneOrMore: ({ expr }) => { - // TODO: Nested quantified expression + // TODO: Nested quantified expressions? const matches = pipe( list, takeLeftWhile(a => checkExpr(expr, a, list, index).length > 0), diff --git a/src/index.ts b/src/index.ts index 6c19fd3..5bcb4f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ -import { getOrElseW, map } from 'fp-ts/lib/Either' -import { flow, pipe } from 'fp-ts/lib/function' -import { fst } from 'fp-ts/lib/Tuple' +import * as Either from 'fp-ts/Either' +import { flow, pipe } from 'fp-ts/function' +import { fst } from 'fp-ts/Tuple' import * as ev from './eval' import { parser } from './parser' import { ListExpr } from './types' @@ -11,8 +11,8 @@ const toSourceString = (r: string | RegExp): string => export const liexp: (r: string | RegExp) => ListExpr = flow( toSourceString, parser, - map(fst), - getOrElseW(([e, _]) => { + Either.map(fst), + Either.getOrElseW(([e, _]) => { throw new Error(e) }), ) diff --git a/src/parser/index.ts b/src/parser/index.ts index cbdc02b..d1da542 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -1,5 +1,5 @@ -import { flow, pipe } from 'fp-ts/function' -import { chain, map as mapE, left, orElse, right } from 'fp-ts/lib/Either' +import { pipe } from 'fp-ts/function' +import * as Either from 'fp-ts/Either' import { delimited, digits, @@ -13,7 +13,6 @@ import { pair, Parser, ParserResult, - prefixed, satifyChar, sepBy1, suffixed, @@ -22,8 +21,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 * as Option from 'fp-ts/Option' +import { snd } from 'fp-ts/Tuple' const start = mapTo(symbol('^'), _ => Expr.Start()) const end = mapTo(symbol('$'), _ => Expr.End()) @@ -34,8 +33,8 @@ const anyBool = mapTo(symbol('\\b'), _ => Expr.AnyBool()) const truthy = mapTo(symbol('\\T'), _ => Expr.Truthy()) const falsey = mapTo(symbol('\\F'), _ => Expr.Falsey()) -const wrapQuantifiers: (e: ParserResult) => ParserResult = chain( - ([expr, input]) => +const wrapQuantifiers: (e: ParserResult) => ParserResult = + Either.chain(([expr, input]) => pipe( input, or([ @@ -43,9 +42,9 @@ const wrapQuantifiers: (e: ParserResult) => ParserResult = chain( mapTo(symbol('+'), _ => Expr.OneOrMore({ expr })), mapTo(symbol('?'), _ => Expr.Optional({ expr })), ]), - orElse(_ => right([expr, input])), + Either.orElse(_ => Either.right([expr, input])), ), -) + ) const propRegex = /^[A-Za-z0-9_-]$/ @@ -75,8 +74,8 @@ const unsignedNum: Parser = mapTo( ([int, decimal]) => pipe( decimal, - map(snd), - getOrElse(() => '0'), + Option.map(snd), + Option.getOrElse(() => '0'), n => parseFloat(`${int}.${n}`), ), ) @@ -86,7 +85,7 @@ const numberLiteral: Parser = mapTo( ([signO, n]) => pipe( signO, - getOrElse(() => '+'), + Option.getOrElse(() => '+'), sign => (sign === '-' ? -1 : 1) * n, Literal.Number, ), @@ -108,10 +107,10 @@ const infixOp = pipe( input, sepBy1(op, groupP), - chain(([exprs, nextInput]) => + Either.chain(([exprs, nextInput]) => exprs.length === 1 - ? left(['Infix operator parsing error', input]) - : right([exprs, nextInput]), + ? Either.left(['Infix operator parsing error', input]) + : Either.right([exprs, nextInput]), ), ) diff --git a/src/parser/utils.ts b/src/parser/utils.ts index cee1de7..4b68aff 100644 --- a/src/parser/utils.ts +++ b/src/parser/utils.ts @@ -1,49 +1,44 @@ import { flow, pipe } from 'fp-ts/function' -import { - Either, - left, - right, - map, - chain, - orElse, - fold, - orElseW, -} from 'fp-ts/Either' -import { none, some, Option, getOrElse } from 'fp-ts/Option' +import * as Either from 'fp-ts/Either' +import * as Option from 'fp-ts/Option' import { fst, mapFst, mapSnd, snd } from 'fp-ts/Tuple' import { eq } from '../utils' -import { prepend } from 'fp-ts/lib/Array' +import { prepend } from 'fp-ts/Array' export type char = string export type ParserState = [T, string] export type ParserError = [string, string] -export type ParserResult = Either> +export type ParserResult = Either.Either> export type Parser = (input: string) => ParserResult export const constP = (v: T): Parser => (inp: string) => - right([v, inp]) + Either.right([v, inp]) export const sepBy1 = (sep: Parser, parser: Parser): Parser => flow( parser, - chain(([val, nextInput]) => - pipe(nextInput, many0(prefixed(sep, parser)), map(mapFst(prepend(val)))), + Either.chain(([val, nextInput]) => + pipe( + nextInput, + many0(prefixed(sep, parser)), + Either.map(mapFst(prepend(val))), + ), ), ) export const many0 = (parser: Parser): Parser> => flow( parser, - chain(([a, nextInput]) => - pipe(nextInput, many0(parser), map(mapFst(prepend(a)))), + Either.chain(([a, nextInput]) => + pipe(nextInput, many0(parser), Either.map(mapFst(prepend(a)))), ), - orElse( + Either.orElse( flow( mapFst(_ => [] as T[]), - right, + Either.right, ), ), ) @@ -52,10 +47,10 @@ export const many1 = (parser: Parser): Parser> => recoverInput( flow( many0(parser), - chain(([res, inp]) => + Either.chain(([res, inp]) => res.length > 0 - ? right([res, inp]) - : left([`many1 failed to parse at '${inp}'`, inp]), + ? Either.right([res, inp]) + : Either.left([`many1 failed to parse at '${inp}'`, inp]), ), ), ) @@ -66,10 +61,10 @@ const recoverInput = pipe( input, p, - orElseW( + Either.orElseW( flow( mapSnd(_ => input), - left, + Either.left, ), ), ) @@ -90,27 +85,27 @@ export const satifyChar = (f: (c: char) => boolean): Parser => (input: string) => { const c = input.charAt(0) - if (f(c)) return right([c, input.slice(1)]) - return left([`Expected to satisfy ${f}, got "${c}"`, input]) + if (f(c)) return Either.right([c, input.slice(1)]) + return Either.left([`Expected to satisfy ${f}, got "${c}"`, input]) } export const digit = satifyChar(c => /^[0-9]$/g.test(c)) export const digits: Parser = flow( many1(digit), - map(mapFst(ds => ds.join(''))), + Either.map(mapFst(ds => ds.join(''))), ) export const or = (parsers: Parser[]): Parser => { const run = ([p, ...ps]: Parser[]) => flow( p, - orElse(([_, inp]) => or(ps)(inp)), + Either.orElse(([_, inp]) => or(ps)(inp)), ) return parsers.length > 0 ? run(parsers) - : (inp: string) => left(['unable to match', inp]) + : (inp: string) => Either.left(['unable to match', inp]) } export const matchChar = (ch: char): Parser => satifyChar(eq(ch)) @@ -119,8 +114,8 @@ export const matchString = (s: string): Parser => (input: string) => input.slice(0, s.length) === s - ? right([s, input.slice(s.length)]) - : left([`Expected ${s} but got ${input.slice(0, 1)}`, input]) + ? Either.right([s, input.slice(s.length)]) + : Either.left([`Expected ${s} but got ${input.slice(0, 1)}`, input]) export const oneOf = (xs: string[]): Parser => or(xs.map(matchString)) @@ -131,25 +126,25 @@ export const symbol = (s: string): Parser => delimited(whitespaces0, matchString(s), whitespaces0) export const mapTo = (p: Parser, f: (p: I) => R): Parser => - flow(p, map(mapFst(f))) + flow(p, Either.map(mapFst(f))) export const andThen = (f: (p: I) => Parser) => (p: Parser): Parser => flow( p, - chain(([v, inp]) => f(v)(inp)), + Either.chain(([v, inp]) => f(v)(inp)), ) -export const optional = (p: Parser): Parser> => +export const optional = (p: Parser): Parser> => flow( recoverInput(p), - fold( + Either.fold( flow( - mapFst(_ => none), - right, + mapFst(_ => Option.none), + Either.right, ), - flow(mapFst(some), right), + flow(mapFst(Option.some), Either.right), ), ) diff --git a/src/types.ts b/src/types.ts index ea9f9bf..473f5e1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,38 +1,33 @@ -import {Option} from "fp-ts/lib/Option" -import { constructors, Union } from "./utils" +import { Option } from 'fp-ts/Option' +import { constructors, Union } from './utils' type _ = never export type Literal = Union<{ - String: string, - Number: number, - Boolean: boolean, + String: string + Number: number + Boolean: boolean }> export const Literal = constructors() export type Expr = Union<{ - Start: _, - End: _, - Optional: { expr: Expr }, - OneOrMore: { expr: Expr }, - ZeroOrMore: { expr: Expr }, - AnyItem: _, - Or: { exprs: Expr[] }, - AnyString: _, - AnyNumber: _, - AnyBool: _, - Truthy: _, - Falsey: _, - Group: { exprs: Expr[] }, - PropertyMatch: { name: string, expr: Expr }, - Literal: Literal, - Sequence: { exprs: Expr[] }, + Start: _ + End: _ + Optional: { expr: Expr } + OneOrMore: { expr: Expr } + ZeroOrMore: { expr: Expr } + AnyItem: _ + Or: { exprs: Expr[] } + AnyString: _ + AnyNumber: _ + AnyBool: _ + Truthy: _ + Falsey: _ + Group: { exprs: Expr[] } + PropertyMatch: { name: string; expr: Expr } + Literal: Literal + Sequence: { exprs: Expr[] } }> export const Expr = constructors() -export type ListExpr = [ - Option, - Expr, - Option, -] - +export type ListExpr = [Option, Expr, Option] diff --git a/src/utils.ts b/src/utils.ts index 66c4c53..281263b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -16,7 +16,7 @@ type Tag = { tag: N; value: V } export type Union = { [N in keyof T]: Tag }[keyof T] export const constructors = >(): { - [N in T['tag']]: TagValue extends null|never + [N in T['tag']]: TagValue extends null | never ? (value?: null | never) => T : (value: TagValue) => T } => diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts index 6fb5921..dfa5e40 100644 --- a/tests/basic.spec.ts +++ b/tests/basic.spec.ts @@ -130,7 +130,6 @@ 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' }, diff --git a/tests/parser.spec.ts b/tests/parser.spec.ts index 6c773d6..8a53faf 100644 --- a/tests/parser.spec.ts +++ b/tests/parser.spec.ts @@ -4,14 +4,10 @@ import { whitespace, whitespaces0, delimited, - sepBy1, - symbol, } from '../src/parser/utils' import { parser } from '../src/parser' import { none, some } from 'fp-ts/Option' import { Expr, Literal } from '../src/types' -import { jlog } from '../src/utils' -import { parse } from 'fp-ts/lib/Json' const wrap = (e: Expr) => right([[none, e, none], '']) const grouped = (l: Expr[]) => wrap(Expr.Group({ exprs: l })) @@ -88,7 +84,7 @@ describe('Parser', () => { exprs: [ Expr.AnyString(), Expr.Group({ exprs: [Expr.AnyBool(), Expr.Truthy()] }), - ] + ], }), Expr.AnyNumber(), ]), -- cgit v1.3.1