aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/eval/index.ts19
-rw-r--r--src/parser/index.ts40
-rw-r--r--src/parser/utils.ts17
-rw-r--r--src/types.ts4
4 files changed, 43 insertions, 37 deletions
diff --git a/src/eval/index.ts b/src/eval/index.ts
index 0579579..4c47adf 100644
--- a/src/eval/index.ts
+++ b/src/eval/index.ts
@@ -103,13 +103,20 @@ const checkExpr = <T>(
)
},
- _: _ => [],
+ // Or: ({ left, right }) => {
+ // return pipe(
+ // [],
+ // skip(1),
+ // )
+ // },
+
+ _: _ => { throw new Error(`TODO: ${expr.tag} not implemented for match`) },
}),
)
}
export const matchAll = <T>(
- [startO, exprs, endO]: ListExpr,
+ [startO, expr, endO]: ListExpr,
list: T[],
): MatchGroupResult => {
const check = (index: number, ls: T[], expr: Expr): MatchGroupIndexed[] => {
@@ -125,14 +132,12 @@ export const matchAll = <T>(
return checkExpr(expr, item, ls, index, next)
}
- const expr = Expr.Group({ exprs })
-
return {
groups: check(0, list, expr),
}
}
-export const find = <T>([startO, exprs, endO]: ListExpr, list: T[]): any => {
+export const find = <T>([startO, expr, endO]: ListExpr, list: T[]): any => {
const check =
(expr: Expr) =>
<T>(x: T, i: number, ls: T[]): boolean => {
@@ -161,7 +166,5 @@ export const find = <T>([startO, exprs, endO]: ListExpr, list: T[]): any => {
)
}
- const cs = exprs.map(check)
-
- return list.filter((x, i, ls) => cs.every(c => c(x, i, ls)))
+ return list.filter((x, i, ls) => check(expr)(x, i, ls))
}
diff --git a/src/parser/index.ts b/src/parser/index.ts
index e815334..1f9da13 100644
--- a/src/parser/index.ts
+++ b/src/parser/index.ts
@@ -1,5 +1,5 @@
import { flow, pipe } from 'fp-ts/function'
-import { chain, left, orElse, right } from 'fp-ts/lib/Either'
+import { chain, map as mapE, left, orElse, right } from 'fp-ts/lib/Either'
import {
delimited,
digits,
@@ -15,6 +15,7 @@ import {
ParserResult,
prefixed,
satifyChar,
+ sepBy1,
suffixed,
symbol,
tuple3,
@@ -22,7 +23,7 @@ import {
} from './utils'
import { Expr, ListExpr, Literal } from '../types'
import {getOrElse, map} from 'fp-ts/lib/Option'
-import {snd} from 'fp-ts/lib/Tuple'
+import {mapFst, snd} from 'fp-ts/lib/Tuple'
const start = mapTo(symbol('^'), _ => Expr.Start())
const end = mapTo(symbol('$'), _ => Expr.End())
@@ -47,17 +48,6 @@ const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
),
)
-const wrapAlt: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(
- ([expr, input]) =>
- pipe(
- input,
- mapTo(prefixed(symbol('|'), many1(expressionP)), rest =>
- Expr.Or({ left: expr, right: rest }),
- ),
- orElse(_ => right([expr, input])),
- ),
-)
-
const propRegex = /^[A-Za-z0-9_-]$/
export const propertyName: Parser<string> = pipe(
@@ -76,7 +66,7 @@ const objectProperty = (input: string) =>
pair(propertyName, many0(expressionP)),
symbol(']'),
),
- ([name, exprs]) => Expr.PropertyMatch({ name, expr: Expr.Group({ exprs }) }),
+ ([name, exprs]) => Expr.PropertyMatch({ name, expr: exprsToGroup(exprs) }),
),
)
@@ -111,13 +101,17 @@ const literalP: Parser<Literal> = delimited(
whitespaces0,
)
-const expressionP: Parser<Expr> = (input: string) =>
+const expressionP: Parser<Expr> = (input: string) => pipe(
+ input,
+ sepBy1(symbol('|'), groupP),
+ mapE(mapFst(exprs => exprs.length === 1 ? exprs[0] : Expr.Or({ exprs }))),
+)
+
+const atomP: Parser<Expr> = (input: string) =>
pipe(
input,
or([
- mapTo(delimited(symbol('('), many1(expressionP), symbol(')')), exprs =>
- Expr.Group({ exprs }),
- ),
+ mapTo(delimited(symbol('('), many1(expressionP), symbol(')')), exprsToGroup),
objectProperty,
nextItem,
anyItem,
@@ -129,21 +123,21 @@ const expressionP: Parser<Expr> = (input: string) =>
mapTo(literalP, Expr.Literal),
]),
wrapQuantifiers,
- wrapAlt,
+ //wrapAlt,
)
+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(
optional(start),
- many1(expressionP),
+ expressionP,
optional(end),
)
/*
-
{3,6} => 3 to 6 instances
(> 5) => number greater than
(< 5) => number less than
-[name x] => apply x on property `name`
/x/ => match regular expression (string values in list)
-
*/
diff --git a/src/parser/utils.ts b/src/parser/utils.ts
index 908405e..cee1de7 100644
--- a/src/parser/utils.ts
+++ b/src/parser/utils.ts
@@ -1,4 +1,4 @@
-import { constant, flow, pipe } from 'fp-ts/function'
+import { flow, pipe } from 'fp-ts/function'
import {
Either,
left,
@@ -9,9 +9,10 @@ import {
fold,
orElseW,
} from 'fp-ts/Either'
-import { none, some, Option } from 'fp-ts/Option'
+import { none, some, Option, getOrElse } from 'fp-ts/Option'
import { fst, mapFst, mapSnd, snd } from 'fp-ts/Tuple'
import { eq } from '../utils'
+import { prepend } from 'fp-ts/lib/Array'
export type char = string
@@ -25,11 +26,19 @@ export const constP =
(inp: string) =>
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)))),
+ ),
+ )
+
export const many0 = <T>(parser: Parser<T>): Parser<Array<T>> =>
flow(
parser,
chain(([a, nextInput]) =>
- pipe(nextInput, many0(parser), map(mapFst(ls => [a, ...ls]))),
+ pipe(nextInput, many0(parser), map(mapFst(prepend(a)))),
),
orElse(
flow(
@@ -134,7 +143,7 @@ export const andThen =
export const optional = <T>(p: Parser<T>): Parser<Option<T>> =>
flow(
- p,
+ recoverInput(p),
fold(
flow(
mapFst(_ => none),
diff --git a/src/types.ts b/src/types.ts
index b09bde5..97ff81d 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -18,7 +18,7 @@ export type Expr = Union<{
ZeroOrMore: { expr: Expr },
NextItem: _,
AnyItem: _,
- Or: { left: Expr, right: Expr[] },
+ Or: { exprs: Expr[] },
AnyString: _,
AnyNumber: _,
AnyBool: _,
@@ -32,7 +32,7 @@ export const Expr = constructors<Expr>()
export type ListExpr = [
Option<Expr>,
- Expr[],
+ Expr,
Option<Expr>,
]