aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/parser/index.ts43
-rw-r--r--src/types.ts36
-rw-r--r--src/utils.ts15
3 files changed, 51 insertions, 43 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