diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/index.ts | 19 | ||||
| -rw-r--r-- | src/parser/index.ts | 40 | ||||
| -rw-r--r-- | src/parser/utils.ts | 17 | ||||
| -rw-r--r-- | src/types.ts | 4 |
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>, ] |
