From 6639605b395ceb1355c95e06ff0e1470adc54101 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 7 Jan 2022 18:13:40 +0530 Subject: refactor: simplifies quantifier logic + moves stuff around --- src/parser.ts | 162 ---------------------------------------------------------- 1 file changed, 162 deletions(-) delete mode 100644 src/parser.ts (limited to 'src/parser.ts') diff --git a/src/parser.ts b/src/parser.ts deleted file mode 100644 index a7d6528..0000000 --- a/src/parser.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { constant, flow, pipe } from 'fp-ts/function' -import { - Either, - left, - right, - map, - chain, - orElse, - fold, - orElseW, -} from 'fp-ts/Either' -import { none, some, Option } from 'fp-ts/Option' -import { mapFst, mapSnd, snd } from 'fp-ts/Tuple' -import { eq } from './utils' - -export type char = string - -export type ParserState = [T, string] -export type ParserError = [string, string] -export type ParserResult = Either> -export type Parser = (input: string) => ParserResult - -export const constP = - (v: T): Parser => - (inp: string) => - right([v, inp]) - -export const many0 = (parser: Parser): Parser> => - flow( - parser, - chain(([a, nextInput]) => - pipe(nextInput, many0(parser), map(mapFst((ls) => [a, ...ls]))) - ), - orElse( - flow( - mapFst((_) => [] as T[]), - right - ) - ) - ) - -export const many1 = (parser: Parser): Parser> => - flow( - many0(parser), - chain(([res, inp]) => - res.length > 0 - ? right([res, inp]) - : left([`many1 failed to parse at ${inp}`, inp]) - ) - ) - -const recoverInput = - (p: Parser): Parser => - (input: string) => - pipe( - input, - p, - orElseW( - flow( - mapSnd((_) => input), - left - ) - ) - ) - -export const prefixed = (a: Parser, b: Parser): Parser => - recoverInput(flow(a, chain(flow(snd, b)))) - -export const suffixed = (a: Parser, b: Parser): Parser => - recoverInput( - flow( - a, - chain(([out, inp]) => pipe(inp, b, map(mapFst((_) => out)))) - ) - ) - -export const delimited = ( - p: Parser, - a: Parser, - s: Parser -): Parser => suffixed(prefixed(p, a), s) - -export const satifyChar = - (f: (c: char) => boolean): Parser => - (input: string) => { - const c = input.charAt(0) - if (f(c)) return right([c, input.slice(1)]) - return left([`Expected to satisfy ${f}, got "${c}"`, input]) - } - -export const digit = satifyChar((c) => /^[0-9]$/g.test(c)) - -export const integer: Parser = flow( - many1(digit), - map(mapFst((ds) => parseInt(ds.join(''), 10))) -) - -export const or = (parsers: Parser[]): Parser => { - const run = ([p, ...ps]: Parser[]) => - flow( - p, - orElse(([_, inp]) => or(ps)(inp)) - ) - - return parsers.length > 0 - ? run(parsers) - : (inp: string) => left(['unable to match', inp]) -} - -export const matchChar = (ch: char): Parser => satifyChar(eq(ch)) - -export const space = matchChar(' ') -export const newline = matchChar('\n') -export const tab = matchChar('\t') - -export const whitespace = or([space, newline, tab]) -export const whitespaces0 = many0(whitespace) - -export const matchString = - (s: string): Parser => - (input: string) => - input.slice(0, s.length) === s - ? right([s, input.slice(s.length)]) - : left([`Expected ${s} but got ${input.slice(0, 1)}`, input]) - -export const symbol = (s: string): Parser => - delimited(whitespaces0, matchString(s), whitespaces0) - -export const mapTo = (p: Parser, f: (p: I) => R): Parser => - flow(p, map(mapFst(f))) - -export const andThen = - (f: (p: I) => Parser) => - (p: Parser): Parser => - flow( - p, - chain(([v, inp]) => f(v)(inp)) - ) - -export const optional = (p: Parser): Parser> => - flow( - p, - fold( - flow( - mapFst((_) => none), - right - ), - flow(mapFst(some), right) - ) - ) - -export const pair = (a: Parser, b: Parser): Parser<[A, B]> => - pipe( - a, - andThen((ra) => mapTo(b, (rb) => [ra, rb])) - ) - -export const tuple3 = ( - a: Parser, - b: Parser, - c: Parser -): Parser<[A, B, C]> => mapTo(pair(pair(a, b), c), ([[a, b], c]) => [a, b, c]) -- cgit v1.3.1