diff options
Diffstat (limited to '')
| -rw-r--r-- | src/parser/index.ts | 43 | ||||
| -rw-r--r-- | src/types.ts | 36 | ||||
| -rw-r--r-- | src/utils.ts | 15 | ||||
| -rw-r--r-- | tests/basic.spec.ts | 25 |
4 files changed, 64 insertions, 55 deletions
diff --git a/src/parser/index.ts b/src/parser/index.ts index f522214..9e284f6 100644 --- a/src/parser/index.ts +++ b/src/parser/index.ts @@ -1,4 +1,4 @@ -import { constant, pipe } from 'fp-ts/function' +import { pipe } from 'fp-ts/function' import { chain, orElse, right } from 'fp-ts/lib/Either' import { delimited, @@ -13,36 +13,24 @@ import { } from './utils' import { Expr } from '../types' -export const start = mapTo(symbol('^'), constant({ tag: 'Start' } as Expr)) -export const end = mapTo(symbol('$'), constant({ tag: 'End' } as Expr)) -export const anyItem = mapTo(symbol('.'), constant({ tag: 'AnyItem' } as Expr)) -export const nextItem = mapTo( - symbol(','), - constant({ tag: 'NextItem' } as Expr) -) -export const anyString = mapTo( - symbol('\\s'), - constant({ tag: 'AnyString' } as Expr) -) -export const anyNumber = mapTo( - symbol('\\n'), - constant({ tag: 'AnyNumber' } as Expr) -) -export const anyBool = mapTo( - symbol('\\b'), - constant({ tag: 'AnyBool' } as Expr) -) -export const truthy = mapTo(symbol('\\T'), constant({ tag: 'Truthy' } as Expr)) -export const falsey = mapTo(symbol('\\F'), constant({ tag: 'Falsey' } as Expr)) +export const start = mapTo(symbol('^'), () => Expr.Start(null)) +export const end = mapTo(symbol('$'), () => Expr.End(null)) +export const anyItem = mapTo(symbol('.'), () => Expr.AnyItem(null)) +export const nextItem = mapTo(symbol(','), () => Expr.NextItem(null)) +export const anyString = mapTo(symbol('\\s'), () => Expr.AnyString(null)) +export const anyNumber = mapTo(symbol('\\n'), () => Expr.AnyNumber(null)) +export const anyBool = mapTo(symbol('\\b'), () => Expr.AnyBool(null)) +export const truthy = mapTo(symbol('\\T'), () => Expr.Truthy(null)) +export const falsey = mapTo(symbol('\\F'), () => Expr.Falsey(null)) export const wrapQuantifiers: (e: ParserResult<Expr>) => ParserResult<Expr> = chain(([expr, input]) => pipe( input, or([ - mapTo(symbol('*'), (_) => ({ tag: 'ZeroOrMore', expr } as Expr)), - mapTo(symbol('+'), (_) => ({ tag: 'OneOrMore', expr } as Expr)), - mapTo(symbol('?'), (_) => ({ tag: 'Optional', expr } as Expr)), + mapTo(symbol('*'), () => Expr.ZeroOrMore({ expr })), + mapTo(symbol('+'), () => Expr.OneOrMore({ expr })), + mapTo(symbol('?'), () => Expr.Optional({ expr })), ]), orElse(() => right([expr, input])) ) @@ -52,9 +40,8 @@ export const expressionP: Parser<Expr> = (input: string) => pipe( input, or([ - mapTo( - delimited(symbol('('), many1(expressionP), symbol(')')), - (exprs) => ({ tag: 'Group', exprs } as Expr) + mapTo(delimited(symbol('('), many1(expressionP), symbol(')')), (exprs) => + Expr.Group({ exprs }) ), nextItem, anyItem, diff --git a/src/types.ts b/src/types.ts index 21e9517..7863981 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,17 +1,23 @@ +import { constructors, Union } from "./utils" -export type Expr = - | { tag: 'Start' } - | { tag: 'End' } - | { tag: 'Optional'; expr: Expr } - | { tag: 'OneOrMore'; expr: Expr } - | { tag: 'ZeroOrMore'; expr: Expr } - | { tag: 'NextItem' } - | { tag: 'AnyItem' } - | { tag: 'Or' } - | { tag: 'AnyString' } - | { tag: 'AnyNumber' } - | { tag: 'AnyBool' } - | { tag: 'Truthy' } - | { tag: 'Falsey' } - | { tag: 'Group'; exprs: Expr[] } +type ExprT = { + Start: any, + End: any, + Optional: { expr: Expr }, + OneOrMore: { expr: Expr }, + ZeroOrMore: { expr: Expr }, + NextItem: any, + AnyItem: any, + Or: any, + AnyString: any, + AnyNumber: any, + AnyBool: any, + Truthy: any, + Falsey: any, + Group: { exprs: Expr[] }, +} + +export type Expr = Union<ExprT> + +export const Expr = constructors<ExprT>() diff --git a/src/utils.ts b/src/utils.ts index 9c4c97b..6591050 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,3 +7,18 @@ export const match = <R, K extends string>(pattern: { [key in K | '_']: () => R }) => (k: K): R => (pattern[k] || pattern._)() + +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 Record<string, any>>(): { + [N in keyof T]: (value: T[N]) => Union<T> // Tag<N, T[N]> +} => + new Proxy( + {}, + { + get(_, k) { + return (value: any) => ({ tag: k, value }) + }, + } + ) as any diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts index 59ce573..d443ce1 100644 --- a/tests/basic.spec.ts +++ b/tests/basic.spec.ts @@ -7,6 +7,7 @@ import { } from '../src/parser/utils' import { parser } from '../src/parser' import { some } from 'fp-ts/Option' +import { Expr } from '../src/types' describe('Foobar', () => { it('should do shit', () => { @@ -28,15 +29,15 @@ describe('Foobar', () => { expect(parser(/^ .\s(\n)\b \T $/.source)).toEqual( right([ [ - some({ tag: 'Start' }), + some(Expr.Start(null)), [ - { tag: 'AnyItem' }, - { tag: 'AnyString' }, - { tag: 'Group', exprs: [{ tag: 'AnyNumber' }] }, - { tag: 'AnyBool' }, - { tag: 'Truthy' }, + Expr.AnyItem(null), + Expr.AnyString(null), + Expr.Group({ exprs: [Expr.AnyNumber(null)] }), + Expr.AnyBool(null), + Expr.Truthy(null), ], - some({ tag: 'End' }), + some(Expr.End(null)), ], '', ]) @@ -45,13 +46,13 @@ describe('Foobar', () => { expect(parser(/^ \s* \T? \n+ $/.source)).toEqual( right([ [ - some({ tag: 'Start' }), + some(Expr.Start(null)), [ - { tag: 'ZeroOrMore', expr: { tag: 'AnyString' } }, - { tag: 'Optional', expr: { tag: 'Truthy' } }, - { tag: 'OneOrMore', expr: { tag: 'AnyNumber' } }, + Expr.ZeroOrMore({ expr: Expr.AnyString(null) }), + Expr.Optional({ expr: Expr.Truthy(null) }), + Expr.OneOrMore({ expr: Expr.AnyNumber(null) }), ], - some({ tag: 'End' }), + some(Expr.End(null)), ], '', ]) |
