aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--default.nix12
-rw-r--r--src/index.ts26
-rw-r--r--src/parser.ts78
-rw-r--r--src/utils.ts4
4 files changed, 68 insertions, 52 deletions
diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000..7b1a6c7
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,12 @@
+{ pkgs ? import <nixpkgs> { } }:
+with pkgs;
+mkShell rec {
+ buildInputs = [
+ nodejs-16_x
+ yarn
+ efm-langserver
+ nodePackages.vls
+ nodePackages.prettier
+ nodePackages.typescript-language-server
+ ];
+}
diff --git a/src/index.ts b/src/index.ts
index 582f9be..95a5411 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,16 @@
import { constant, flow, identity, pipe } from 'fp-ts/function'
-import { andThen, delimited, mapTo, optional, pair, symbol } from './parser'
+import {
+ andThen,
+ delimited,
+ digit,
+ integer,
+ many1,
+ mapTo,
+ optional,
+ or,
+ pair,
+ symbol,
+} from './parser'
export const start = mapTo(symbol('^'), constant({ tag: 'Start' } as Expr))
export const end = mapTo(symbol('$'), constant({ tag: 'End' } as Expr))
@@ -27,15 +38,12 @@ type Expr =
| { tag: 'Truthy' }
| { tag: 'Falsey' }
-export const expressionP = symbol('fuck')
+export const expressionP = or([
+ symbol('fuck'),
+ mapTo(many1(digit), (j) => j.join('')),
+])
-export const parser = pair(
- pair(
- optional(start),
- expressionP,
- ),
- optional(end),
-)
+export const parser = pair(pair(optional(start), expressionP), optional(end))
/*
diff --git a/src/parser.ts b/src/parser.ts
index 5ccba43..9baab8e 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -1,6 +1,8 @@
import { flow, pipe } from 'fp-ts/function'
import { Either, left, right, map, chain, orElse, fold } from 'fp-ts/Either'
-import { none, some, Option } from 'fp-ts/lib/Option'
+import { none, some, Option } from 'fp-ts/Option'
+import { mapFst, snd } from 'fp-ts/Tuple'
+import { eq } from './utils'
export type char = string
@@ -17,13 +19,14 @@ export const many0 = <T>(parser: Parser<T>): Parser<Array<T>> =>
flow(
parser,
chain(([a, nextInput]) =>
- pipe(
- nextInput,
- many0(parser),
- map(([ls, inp]): ParserResult<T[]> => [[a, ...ls], inp])
- )
+ pipe(nextInput, many0(parser), map(mapFst((ls) => [a, ...ls])))
),
- orElse(([_, inp]) => right([[] as T[], inp]))
+ orElse(
+ flow(
+ mapFst((_) => [] as T[]),
+ right
+ )
+ )
)
export const many1 = <T>(parser: Parser<T>): Parser<Array<T>> =>
@@ -37,21 +40,12 @@ export const many1 = <T>(parser: Parser<T>): Parser<Array<T>> =>
)
export const prefixed = <T>(a: Parser<any>, b: Parser<T>): Parser<T> =>
- flow(
- a,
- chain(([_, inp]) => b(inp))
- )
+ flow(a, chain(flow(snd, b)))
export const suffixed = <T>(a: Parser<T>, b: Parser<any>): Parser<T> =>
flow(
a,
- chain(([out, inp]) =>
- pipe(
- inp,
- b,
- chain(([_, inp2]) => right([out, inp2]))
- )
- )
+ chain(([out, inp]) => pipe(inp, b, map(mapFst((_) => out))))
)
export const delimited = <T>(
@@ -72,22 +66,22 @@ export const digit = satifyChar((c) => /^[0-9]$/g.test(c))
export const integer: Parser<number> = flow(
many1(digit),
- map(([ds, input]) => [parseInt(ds.join(''), 10), input])
+ map(mapFst((ds) => parseInt(ds.join(''), 10)))
)
export const or = <T>(parsers: Parser<T>[]): Parser<T> => {
- const ppp = ([p, ...ps]: Parser<T>[]) =>
+ const run = ([p, ...ps]: Parser<T>[]) =>
flow(
p,
orElse(([_, inp]) => or(ps)(inp))
)
return parsers.length > 0
- ? ppp(parsers)
+ ? run(parsers)
: (inp: string) => left(['unable to match', inp])
}
-export const matchChar = (ch: char): Parser<char> => satifyChar((c) => c === ch)
+export const matchChar = (ch: char): Parser<char> => satifyChar(eq(ch))
export const space = matchChar(' ')
export const newline = matchChar('\n')
@@ -102,11 +96,7 @@ export const matchString = (s: string): Parser<string> =>
: flow(
matchChar(s.charAt(0)),
chain(([c, inp]) =>
- pipe(
- inp,
- matchString(s.slice(1)),
- map(([s, inp]) => [c + s, inp])
- )
+ pipe(inp, matchString(s.slice(1)), map(mapFst((s) => c + s)))
)
)
@@ -114,28 +104,30 @@ 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(([v, inp]) => [f(v), inp])
- )
+ flow(p, 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)),
- )
+export const andThen =
+ <I, R>(f: (p: I) => Parser<R>) =>
+ (p: Parser<I>): Parser<R> =>
+ flow(
+ p,
+ chain(([v, inp]) => f(v)(inp))
+ )
export const optional = <T>(p: Parser<T>): Parser<Option<T>> =>
flow(
p,
fold(
- ([_, inp]) => right([none, inp]),
- ([v, inp]) => right([some(v), inp])
+ flow(
+ mapFst((_) => none),
+ right
+ ),
+ flow(mapFst(some), right)
)
)
-export const pair = <A, B>(a: Parser<A>, b: Parser<B>): Parser<[A, B]> => pipe(
- a,
- andThen(ra => mapTo(b, rb => [ra, rb]))
-)
-
+export const pair = <A, B>(a: Parser<A>, b: Parser<B>): Parser<[A, B]> =>
+ pipe(
+ a,
+ andThen((ra) => mapTo(b, (rb) => [ra, rb]))
+ )
diff --git a/src/utils.ts b/src/utils.ts
new file mode 100644
index 0000000..e7392bf
--- /dev/null
+++ b/src/utils.ts
@@ -0,0 +1,4 @@
+export const eq =
+ <T>(a: T) =>
+ (b: T): boolean =>
+ a === b