aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2022-01-14 19:10:49 +0530
committerAkshay Nair <phenax5@gmail.com>2022-01-14 19:23:59 +0530
commitb5893d68ce4eacbc3ae431ca48f821657236c7aa (patch)
tree3bf215c9ff226fbe1363069fcc63ca22ea5417c7
parentde5d3de99afae3cb7f1dc56fe8781394f8614a50 (diff)
downloadelxr-b5893d68ce4eacbc3ae431ca48f821657236c7aa.tar.gz
elxr-b5893d68ce4eacbc3ae431ca48f821657236c7aa.zip
refactor: refactors imports + formatting
-rw-r--r--TODO.md4
-rw-r--r--package.json2
-rw-r--r--src/eval/index.ts28
-rw-r--r--src/index.ts10
-rw-r--r--src/parser/index.ts29
-rw-r--r--src/parser/utils.ts73
-rw-r--r--src/types.ts49
-rw-r--r--src/utils.ts2
-rw-r--r--tests/basic.spec.ts1
-rw-r--r--tests/parser.spec.ts6
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<T = any> {
value: T
@@ -73,20 +65,20 @@ const checkExpr = <T>(
(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 = <T>(
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<Expr>) => ParserResult<Expr> = chain(
- ([expr, input]) =>
+const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> =
+ Either.chain(([expr, input]) =>
pipe(
input,
or([
@@ -43,9 +42,9 @@ const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> = 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<number> = 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<Literal> = 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> = [T, string]
export type ParserError = [string, string]
-export type ParserResult<T> = Either<ParserError, ParserState<T>>
+export type ParserResult<T> = Either.Either<ParserError, ParserState<T>>
export type Parser<T> = (input: string) => ParserResult<T>
export const constP =
<T>(v: T): Parser<T> =>
(inp: string) =>
- right([v, inp])
+ Either.right([v, inp])
export const sepBy1 = <T>(sep: Parser<any>, parser: Parser<T>): Parser<T[]> =>
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 = <T>(parser: Parser<T>): Parser<Array<T>> =>
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 = <T>(parser: Parser<T>): Parser<Array<T>> =>
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<char> =>
(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<string> = flow(
many1(digit),
- map(mapFst(ds => ds.join(''))),
+ Either.map(mapFst(ds => ds.join(''))),
)
export const or = <T>(parsers: Parser<T>[]): Parser<T> => {
const run = ([p, ...ps]: Parser<T>[]) =>
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<char> => satifyChar(eq(ch))
@@ -119,8 +114,8 @@ export const matchString =
(s: string): Parser<string> =>
(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<string> => or(xs.map(matchString))
@@ -131,25 +126,25 @@ export const symbol = (s: string): Parser<string> =>
delimited(whitespaces0, matchString(s), whitespaces0)
export const mapTo = <I, R>(p: Parser<I>, f: (p: I) => R): Parser<R> =>
- flow(p, map(mapFst(f)))
+ flow(p, Either.map(mapFst(f)))
export const andThen =
<I, R>(f: (p: I) => Parser<R>) =>
(p: Parser<I>): Parser<R> =>
flow(
p,
- chain(([v, inp]) => f(v)(inp)),
+ Either.chain(([v, inp]) => f(v)(inp)),
)
-export const optional = <T>(p: Parser<T>): Parser<Option<T>> =>
+export const optional = <T>(p: Parser<T>): Parser<Option.Option<T>> =>
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<Literal>()
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<Expr>()
-export type ListExpr = [
- Option<Expr>,
- Expr,
- Option<Expr>,
-]
-
+export type ListExpr = [Option<Expr>, Expr, Option<Expr>]
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<N, V> = { tag: N; value: V }
export type Union<T> = { [N in keyof T]: Tag<N, T[N]> }[keyof T]
export const constructors = <T extends Tag<string, any>>(): {
- [N in T['tag']]: TagValue<T, N> extends null|never
+ [N in T['tag']]: TagValue<T, N> extends null | never
? (value?: null | never) => T
: (value: TagValue<T, N>) => 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(),
]),