UNPKG

fruitsconfits

Version:

FruitsConfits - A well typed and sugared parser combinator framework for TypeScript/JavaScript.

174 lines 6.74 kB
// Copyright (c) 2019 Shellyl_N and Authors // license: ISC // https://github.com/shellyln import { zeroWidth, zeroWidthError, beginning, end, quantify, first, or, transform, lookAhead, lookBehind, applyProductionRules, makeProgram } from './parser'; export function objSequence(helper, comparator) { return (needle => { return (input => { const len = Math.max(0, input.end - input.start); let matched = true; if (len >= needle.length) { for (let i = 0; i < needle.length; i++) { if (!comparator(input.src[input.start + i], needle[i])) { matched = false; break; } } } else { matched = false; } return (matched ? { succeeded: true, next: { src: input.src, start: input.start + needle.length, end: input.end, context: input.context, templateArgs: input.templateArgs, templateArgsPos: input.templateArgsPos, }, tokens: [helper(needle)], } : { succeeded: false, error: false, src: input.src, pos: input.start, // eslint-disable-next-line @typescript-eslint/restrict-template-expressions message: `operator "objSequence(${needle})"`, }); }); }); } export function objClass(helper, comparator) { // NOTE: <T> version `needles` type is `T`. return ((...needles) => { return (input => { const len = Math.max(0, input.end - input.start); let index = -1; const succeeded = len > 0 ? needles.some((needle, idx) => { if (comparator(input.src[input.start], needle)) { index = idx; return true; } }) : false; return (succeeded ? { succeeded: true, next: { src: input.src, start: input.start + 1, end: input.end, context: input.context, templateArgs: input.templateArgs, templateArgsPos: input.templateArgsPos, }, tokens: [helper(needles[index])], } : { succeeded: false, error: false, src: input.src, pos: input.start, message: `operator "objClass(${needles.join(',')})"`, }); }); }); } export function objClassNot(helper, comparator) { // NOTE: <T> version `needles` type is `T`. return ((...needles) => { return (input => { const len = Math.max(0, input.end - input.start); if (len > 0) { for (const needle of needles) { let matched = true; if (!comparator(input.src[input.start], needle)) { matched = false; break; } if (matched) { return ({ succeeded: false, error: false, src: input.src, pos: input.start, message: `operator "objClassNot(${needles.join(',')})"`, }); } } } return ({ succeeded: true, next: { src: input.src, start: input.start + 1, end: input.end, context: input.context, templateArgs: input.templateArgs, templateArgsPos: input.templateArgsPos, }, tokens: [helper(input.src[input.start])], }); }); }); } export function objClassByNeedleFn(helper, comparator) { // NOTE: needles[i] should be one character. surrogate pair and/or ligature are accepted. // NOTE: <T> version `needles` type is `T`. return (needle => { return (input => { const len = Math.max(0, input.end - input.start); const matched = len > 0 ? needle(input.src[input.start]) : false; return (matched ? { succeeded: true, next: { src: input.src, start: input.start + 1, end: input.end, context: input.context, templateArgs: input.templateArgs, templateArgsPos: input.templateArgsPos, }, tokens: [helper(input.src[input.start])], } : { succeeded: false, error: false, src: input.src, pos: input.start, message: `operator "objClassByNeedleFn"`, }); }); }); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function getObjectParsers(params) { const clsFn = objClassByNeedleFn(params.rawToToken, params.comparator); const isAny = clsFn(src => true); // TODO: reduce unneccessary call for adding types. return ({ seq: objSequence(params.rawToToken, params.comparator), cls: objClass(params.rawToToken, params.comparator), notCls: objClassNot(params.rawToToken, params.comparator), clsFn, classes: { any: isAny, }, cat: transform(params.concatTokens), once: quantify(1, 1), repeat: quantify(), qty: (min, max) => quantify(min, max), zeroWidth: (helper) => zeroWidth(helper), err: (message) => zeroWidthError(message), beginning: (helper) => beginning(helper), end: (helper) => end(helper), first: (...parsers) => first(...parsers), or: (...parsers) => or(...parsers), combine: transform(), erase: transform(tokens => []), trans: (fn) => transform(fn), ahead: (...parsers) => lookAhead(...parsers), behind: (n, helper) => lookBehind(n, helper), rules: (args) => applyProductionRules(args), makeProgram, }); } //# sourceMappingURL=object-parser.js.map