first commit
This commit is contained in:
103
node_modules/peberminta/lib/char.cjs
generated
vendored
Normal file
103
node_modules/peberminta/lib/char.cjs
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
var core = require('./core.cjs');
|
||||
var util = require('./util.cjs');
|
||||
|
||||
function char(char) {
|
||||
return core.token((c) => (c === char) ? c : undefined);
|
||||
}
|
||||
function oneOf(chars) {
|
||||
return core.token((c) => (chars.includes(c)) ? c : undefined);
|
||||
}
|
||||
function noneOf(chars) {
|
||||
return core.token((c) => (chars.includes(c)) ? undefined : c);
|
||||
}
|
||||
function charTest(regex) {
|
||||
return core.token((c) => regex.test(c) ? c : undefined);
|
||||
}
|
||||
function str(str) {
|
||||
const len = str.length;
|
||||
return (data, i) => {
|
||||
const tokensNumber = core.remainingTokensNumber(data, i);
|
||||
let substr = '';
|
||||
let j = 0;
|
||||
while (j < tokensNumber && substr.length < len) {
|
||||
substr += data.tokens[i + j];
|
||||
j++;
|
||||
}
|
||||
return (substr === str)
|
||||
? {
|
||||
matched: true,
|
||||
position: i + j,
|
||||
value: str
|
||||
}
|
||||
: { matched: false };
|
||||
};
|
||||
}
|
||||
function concat(...ps) {
|
||||
return core.map(core.flatten(...ps), (vs) => vs.join(''));
|
||||
}
|
||||
function parserPosition(data, i, contextTokens = 11) {
|
||||
const len = data.tokens.length;
|
||||
const lowIndex = util.clamp(0, i - contextTokens, len - contextTokens);
|
||||
const highIndex = util.clamp(contextTokens, i + 1 + contextTokens, len);
|
||||
const tokensSlice = data.tokens.slice(lowIndex, highIndex);
|
||||
if (tokensSlice.some((t) => t.length !== 1)) {
|
||||
return core.parserPosition(data, i, (t) => t);
|
||||
}
|
||||
let line = '';
|
||||
let offset = 0;
|
||||
let markerLen = 1;
|
||||
if (i < 0) {
|
||||
line += ' ';
|
||||
}
|
||||
if (0 < lowIndex) {
|
||||
line += '...';
|
||||
}
|
||||
for (let j = 0; j < tokensSlice.length; j++) {
|
||||
const token = util.escapeWhitespace(tokensSlice[j]);
|
||||
if (lowIndex + j === i) {
|
||||
offset = line.length;
|
||||
markerLen = token.length;
|
||||
}
|
||||
line += token;
|
||||
}
|
||||
if (highIndex < len) {
|
||||
line += '...';
|
||||
}
|
||||
if (len <= i) {
|
||||
offset = line.length;
|
||||
}
|
||||
return `${''.padEnd(offset)}${i}\n${line}\n${''.padEnd(offset)}${'^'.repeat(markerLen)}`;
|
||||
}
|
||||
function parse(parser, str, options) {
|
||||
const data = { tokens: [...str], options: options };
|
||||
const result = parser(data, 0);
|
||||
if (!result.matched) {
|
||||
throw new Error('No match');
|
||||
}
|
||||
if (result.position < data.tokens.length) {
|
||||
throw new Error(`Partial match. Parsing stopped at:\n${parserPosition(data, result.position)}`);
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
function tryParse(parser, str, options) {
|
||||
return core.tryParse(parser, [...str], options);
|
||||
}
|
||||
function match(matcher, str, options) {
|
||||
return core.match(matcher, [...str], options);
|
||||
}
|
||||
|
||||
exports.anyOf = oneOf;
|
||||
exports.char = char;
|
||||
exports.charTest = charTest;
|
||||
exports.concat = concat;
|
||||
exports.match = match;
|
||||
exports.noneOf = noneOf;
|
||||
exports.oneOf = oneOf;
|
||||
exports.parse = parse;
|
||||
exports.parserPosition = parserPosition;
|
||||
exports.str = str;
|
||||
exports.tryParse = tryParse;
|
154
node_modules/peberminta/lib/char.d.ts
generated
vendored
Normal file
154
node_modules/peberminta/lib/char.d.ts
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* This is an additional module specifically for string parsers.
|
||||
*
|
||||
* It contains parsers with token type bound to be `string`
|
||||
* and expected to work with individual characters.
|
||||
*
|
||||
* It should work even if you have a custom way to split
|
||||
* a string into symbols such as graphemes.
|
||||
*
|
||||
* Node:
|
||||
* ```ts
|
||||
* import * as pc from 'peberminta/char';
|
||||
* ```
|
||||
*
|
||||
* Deno:
|
||||
* ```ts
|
||||
* import * as p from 'https://deno.land/x/peberminta@.../char.ts';
|
||||
* ```
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
import { Parser, Matcher, Data } from './core';
|
||||
/**
|
||||
* Make a parser that looks for the exact match for a given character
|
||||
* and returns a match with that character.
|
||||
*
|
||||
* Tokens expected to be individual characters/graphemes.
|
||||
*
|
||||
* @param char - A character to look for.
|
||||
*/
|
||||
export declare function char<TOptions>(char: string): Parser<string, TOptions, string>;
|
||||
/**
|
||||
* Make a parser that matches and returns a character
|
||||
* if it is present in a given character samples string/array.
|
||||
*
|
||||
* Tokens expected to be individual characters/graphemes.
|
||||
*
|
||||
* @param chars - An array (or a string) of all acceptable characters.
|
||||
*/
|
||||
export declare function oneOf<TOptions>(chars: string | string[]): Parser<string, TOptions, string>;
|
||||
export { oneOf as anyOf };
|
||||
/**
|
||||
* Make a parser that matches and returns a character
|
||||
* if it is absent in a given character samples string/array.
|
||||
*
|
||||
* Tokens expected to be individual characters/graphemes.
|
||||
*
|
||||
* @param chars - An array (or a string) of all characters that are not acceptable.
|
||||
*/
|
||||
export declare function noneOf<TOptions>(chars: string | string[]): Parser<string, TOptions, string>;
|
||||
/**
|
||||
* Make a parser that matches input character against given regular expression.
|
||||
*
|
||||
* Use this to match characters belonging to a certain range
|
||||
* or having a certain [unicode property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes).
|
||||
*
|
||||
* Use `satisfy` from core module instead if you need a predicate.
|
||||
*
|
||||
* Tokens expected to be individual characters/graphemes.
|
||||
*
|
||||
* @param regex - Tester regular expression.
|
||||
*/
|
||||
export declare function charTest<TOptions>(regex: RegExp): Parser<string, TOptions, string>;
|
||||
/**
|
||||
* Make a parser that looks for the exact match for a given string,
|
||||
* returns a match with that string and consumes an according number of tokens.
|
||||
*
|
||||
* Empty string matches without consuming input.
|
||||
*
|
||||
* Tokens expected to be individual characters/graphemes.
|
||||
*
|
||||
* @param str - A string to look for.
|
||||
*/
|
||||
export declare function str<TOptions>(str: string): Parser<string, TOptions, string>;
|
||||
/**
|
||||
* Make a parser that concatenates characters/strings
|
||||
* from all provided parsers into a single string.
|
||||
*
|
||||
* Nonmatch is returned if any of parsers didn't match.
|
||||
*
|
||||
* @param ps - Parsers sequence.
|
||||
* Each parser can return a string or an array of strings.
|
||||
*/
|
||||
export declare function concat<TOptions>(...ps: Parser<string, TOptions, string | string[]>[]): Parser<string, TOptions, string>;
|
||||
/**
|
||||
* Utility function to render a given parser position
|
||||
* for error reporting and debug purposes.
|
||||
*
|
||||
* This is a version specific for char parsers.
|
||||
*
|
||||
* Note: it will fall back to core version (one token per line)
|
||||
* in case any multicharacter tokens are present.
|
||||
*
|
||||
* @param data - Data object (tokens and options).
|
||||
* @param i - Parser position in the tokens array.
|
||||
* @param contextTokens - How many tokens (characters) around the current one to render.
|
||||
* @returns A multiline string.
|
||||
*
|
||||
* @category Utility functions
|
||||
*/
|
||||
export declare function parserPosition(data: Data<string, unknown>, i: number, contextTokens?: number): string;
|
||||
/**
|
||||
* Utility function that provides a bit cleaner interface for running a parser.
|
||||
*
|
||||
* This one throws an error in case parser didn't match
|
||||
* OR the match is incomplete (some part of input string left unparsed).
|
||||
*
|
||||
* Input string is broken down to characters as `[...str]`
|
||||
* unless you provide a pre-split array.
|
||||
*
|
||||
* @param parser - A parser to run.
|
||||
* @param str - Input string or an array of graphemes.
|
||||
* @param options - Parser options.
|
||||
* @returns A matched value.
|
||||
*
|
||||
* @category Utility functions
|
||||
*/
|
||||
export declare function parse<TOptions, TValue>(parser: Parser<string, TOptions, TValue>, str: string | string[], options: TOptions): TValue;
|
||||
/**
|
||||
* Utility function that provides a bit cleaner interface
|
||||
* for running a parser over a string.
|
||||
* Returns `undefined` in case parser did not match.
|
||||
*
|
||||
* Input string is broken down to characters as `[...str]`
|
||||
* unless you provide a pre-split array.
|
||||
*
|
||||
* Note: this doesn't capture errors thrown during parsing.
|
||||
* Nonmatch is considered a part or normal flow.
|
||||
* Errors mean unrecoverable state and it's up to client code to decide
|
||||
* where to throw errors and how to get back to safe state.
|
||||
*
|
||||
* @param parser - A parser to run.
|
||||
* @param str - Input string or an array of graphemes.
|
||||
* @param options - Parser options.
|
||||
* @returns A matched value or `undefined` in case of nonmatch.
|
||||
*
|
||||
* @category Utility functions
|
||||
*/
|
||||
export declare function tryParse<TOptions, TValue>(parser: Parser<string, TOptions, TValue>, str: string | string[], options: TOptions): TValue | undefined;
|
||||
/**
|
||||
* Utility function that provides a bit cleaner interface
|
||||
* for running a {@link Matcher} over a string.
|
||||
*
|
||||
* Input string is broken down to characters as `[...str]`
|
||||
* unless you provide a pre-split array.
|
||||
*
|
||||
* @param matcher - A matcher to run.
|
||||
* @param str - Input string or an array of graphemes.
|
||||
* @param options - Parser options.
|
||||
* @returns A matched value.
|
||||
*
|
||||
* @category Utility functions
|
||||
*/
|
||||
export declare function match<TOptions, TValue>(matcher: Matcher<string, TOptions, TValue>, str: string | string[], options: TOptions): TValue;
|
89
node_modules/peberminta/lib/char.mjs
generated
vendored
Normal file
89
node_modules/peberminta/lib/char.mjs
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import { token, remainingTokensNumber, map, flatten, parserPosition as parserPosition$1, tryParse as tryParse$1, match as match$1 } from './core.mjs';
|
||||
import { clamp, escapeWhitespace } from './util.mjs';
|
||||
|
||||
function char(char) {
|
||||
return token((c) => (c === char) ? c : undefined);
|
||||
}
|
||||
function oneOf(chars) {
|
||||
return token((c) => (chars.includes(c)) ? c : undefined);
|
||||
}
|
||||
function noneOf(chars) {
|
||||
return token((c) => (chars.includes(c)) ? undefined : c);
|
||||
}
|
||||
function charTest(regex) {
|
||||
return token((c) => regex.test(c) ? c : undefined);
|
||||
}
|
||||
function str(str) {
|
||||
const len = str.length;
|
||||
return (data, i) => {
|
||||
const tokensNumber = remainingTokensNumber(data, i);
|
||||
let substr = '';
|
||||
let j = 0;
|
||||
while (j < tokensNumber && substr.length < len) {
|
||||
substr += data.tokens[i + j];
|
||||
j++;
|
||||
}
|
||||
return (substr === str)
|
||||
? {
|
||||
matched: true,
|
||||
position: i + j,
|
||||
value: str
|
||||
}
|
||||
: { matched: false };
|
||||
};
|
||||
}
|
||||
function concat(...ps) {
|
||||
return map(flatten(...ps), (vs) => vs.join(''));
|
||||
}
|
||||
function parserPosition(data, i, contextTokens = 11) {
|
||||
const len = data.tokens.length;
|
||||
const lowIndex = clamp(0, i - contextTokens, len - contextTokens);
|
||||
const highIndex = clamp(contextTokens, i + 1 + contextTokens, len);
|
||||
const tokensSlice = data.tokens.slice(lowIndex, highIndex);
|
||||
if (tokensSlice.some((t) => t.length !== 1)) {
|
||||
return parserPosition$1(data, i, (t) => t);
|
||||
}
|
||||
let line = '';
|
||||
let offset = 0;
|
||||
let markerLen = 1;
|
||||
if (i < 0) {
|
||||
line += ' ';
|
||||
}
|
||||
if (0 < lowIndex) {
|
||||
line += '...';
|
||||
}
|
||||
for (let j = 0; j < tokensSlice.length; j++) {
|
||||
const token = escapeWhitespace(tokensSlice[j]);
|
||||
if (lowIndex + j === i) {
|
||||
offset = line.length;
|
||||
markerLen = token.length;
|
||||
}
|
||||
line += token;
|
||||
}
|
||||
if (highIndex < len) {
|
||||
line += '...';
|
||||
}
|
||||
if (len <= i) {
|
||||
offset = line.length;
|
||||
}
|
||||
return `${''.padEnd(offset)}${i}\n${line}\n${''.padEnd(offset)}${'^'.repeat(markerLen)}`;
|
||||
}
|
||||
function parse(parser, str, options) {
|
||||
const data = { tokens: [...str], options: options };
|
||||
const result = parser(data, 0);
|
||||
if (!result.matched) {
|
||||
throw new Error('No match');
|
||||
}
|
||||
if (result.position < data.tokens.length) {
|
||||
throw new Error(`Partial match. Parsing stopped at:\n${parserPosition(data, result.position)}`);
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
function tryParse(parser, str, options) {
|
||||
return tryParse$1(parser, [...str], options);
|
||||
}
|
||||
function match(matcher, str, options) {
|
||||
return match$1(matcher, [...str], options);
|
||||
}
|
||||
|
||||
export { oneOf as anyOf, char, charTest, concat, match, noneOf, oneOf, parse, parserPosition, str, tryParse };
|
447
node_modules/peberminta/lib/core.cjs
generated
vendored
Normal file
447
node_modules/peberminta/lib/core.cjs
generated
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
var util = require('./util.cjs');
|
||||
|
||||
function emit(value) {
|
||||
return (data, i) => ({
|
||||
matched: true,
|
||||
position: i,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
function make(
|
||||
f) {
|
||||
return (data, i) => ({
|
||||
matched: true,
|
||||
position: i,
|
||||
value: f(data, i)
|
||||
});
|
||||
}
|
||||
function action(
|
||||
f) {
|
||||
return (data, i) => {
|
||||
f(data, i);
|
||||
return {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: null
|
||||
};
|
||||
};
|
||||
}
|
||||
function fail(
|
||||
data, i) {
|
||||
return { matched: false };
|
||||
}
|
||||
function error(message) {
|
||||
return (data, i) => {
|
||||
throw new Error((message instanceof Function) ? message(data, i) : message);
|
||||
};
|
||||
}
|
||||
function token(
|
||||
onToken,
|
||||
onEnd) {
|
||||
return (data, i) => {
|
||||
let position = i;
|
||||
let value = undefined;
|
||||
if (i < data.tokens.length) {
|
||||
value = onToken(data.tokens[i], data, i);
|
||||
if (value !== undefined) {
|
||||
position++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
onEnd?.(data, i);
|
||||
}
|
||||
return (value === undefined)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: position,
|
||||
value: value
|
||||
};
|
||||
};
|
||||
}
|
||||
function any(data, i) {
|
||||
return (i < data.tokens.length)
|
||||
? {
|
||||
matched: true,
|
||||
position: i + 1,
|
||||
value: data.tokens[i]
|
||||
}
|
||||
: { matched: false };
|
||||
}
|
||||
function satisfy(
|
||||
test) {
|
||||
return (data, i) => (i < data.tokens.length && test(data.tokens[i], data, i))
|
||||
? {
|
||||
matched: true,
|
||||
position: i + 1,
|
||||
value: data.tokens[i]
|
||||
}
|
||||
: { matched: false };
|
||||
}
|
||||
function mapInner(r, f) {
|
||||
return (r.matched) ? ({
|
||||
matched: true,
|
||||
position: r.position,
|
||||
value: f(r.value, r.position)
|
||||
}) : r;
|
||||
}
|
||||
function mapOuter(r, f) {
|
||||
return (r.matched) ? f(r) : r;
|
||||
}
|
||||
function map(p, mapper) {
|
||||
return (data, i) => mapInner(p(data, i), (v, j) => mapper(v, data, i, j));
|
||||
}
|
||||
function map1(p,
|
||||
mapper) {
|
||||
return (data, i) => mapOuter(p(data, i), (m) => mapper(m, data, i));
|
||||
}
|
||||
function peek(p, f) {
|
||||
return (data, i) => {
|
||||
const r = p(data, i);
|
||||
f(r, data, i);
|
||||
return r;
|
||||
};
|
||||
}
|
||||
function option(p, def) {
|
||||
return (data, i) => {
|
||||
const r = p(data, i);
|
||||
return (r.matched)
|
||||
? r
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: def
|
||||
};
|
||||
};
|
||||
}
|
||||
function not(p) {
|
||||
return (data, i) => {
|
||||
const r = p(data, i);
|
||||
return (r.matched)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: true
|
||||
};
|
||||
};
|
||||
}
|
||||
function choice(...ps) {
|
||||
return (data, i) => {
|
||||
for (const p of ps) {
|
||||
const result = p(data, i);
|
||||
if (result.matched) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return { matched: false };
|
||||
};
|
||||
}
|
||||
function otherwise(pa, pb) {
|
||||
return (data, i) => {
|
||||
const r1 = pa(data, i);
|
||||
return (r1.matched)
|
||||
? r1
|
||||
: pb(data, i);
|
||||
};
|
||||
}
|
||||
function longest(...ps) {
|
||||
return (data, i) => {
|
||||
let match = undefined;
|
||||
for (const p of ps) {
|
||||
const result = p(data, i);
|
||||
if (result.matched && (!match || match.position < result.position)) {
|
||||
match = result;
|
||||
}
|
||||
}
|
||||
return match || { matched: false };
|
||||
};
|
||||
}
|
||||
function takeWhile(p,
|
||||
test) {
|
||||
return (data, i) => {
|
||||
const values = [];
|
||||
let success = true;
|
||||
do {
|
||||
const r = p(data, i);
|
||||
if (r.matched && test(r.value, values.length + 1, data, i, r.position)) {
|
||||
values.push(r.value);
|
||||
i = r.position;
|
||||
}
|
||||
else {
|
||||
success = false;
|
||||
}
|
||||
} while (success);
|
||||
return {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: values
|
||||
};
|
||||
};
|
||||
}
|
||||
function takeUntil(p,
|
||||
test) {
|
||||
return takeWhile(p, (value, n, data, i, j) => !test(value, n, data, i, j));
|
||||
}
|
||||
function takeWhileP(pValue, pTest) {
|
||||
return takeWhile(pValue, (value, n, data, i) => pTest(data, i).matched);
|
||||
}
|
||||
function takeUntilP(pValue, pTest) {
|
||||
return takeWhile(pValue, (value, n, data, i) => !pTest(data, i).matched);
|
||||
}
|
||||
function many(p) {
|
||||
return takeWhile(p, () => true);
|
||||
}
|
||||
function many1(p) {
|
||||
return ab(p, many(p), (head, tail) => [head, ...tail]);
|
||||
}
|
||||
function ab(pa, pb, join) {
|
||||
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) => join(ma.value, vb, data, i, j)));
|
||||
}
|
||||
function left(pa, pb) {
|
||||
return ab(pa, pb, (va) => va);
|
||||
}
|
||||
function right(pa, pb) {
|
||||
return ab(pa, pb, (va, vb) => vb);
|
||||
}
|
||||
function abc(pa, pb, pc, join) {
|
||||
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) => join(ma.value, mb.value, vc, data, i, j))));
|
||||
}
|
||||
function middle(pa, pb, pc) {
|
||||
return abc(pa, pb, pc, (ra, rb) => rb);
|
||||
}
|
||||
function all(...ps) {
|
||||
return (data, i) => {
|
||||
const result = [];
|
||||
let position = i;
|
||||
for (const p of ps) {
|
||||
const r1 = p(data, position);
|
||||
if (r1.matched) {
|
||||
result.push(r1.value);
|
||||
position = r1.position;
|
||||
}
|
||||
else {
|
||||
return { matched: false };
|
||||
}
|
||||
}
|
||||
return {
|
||||
matched: true,
|
||||
position: position,
|
||||
value: result
|
||||
};
|
||||
};
|
||||
}
|
||||
function skip(...ps) {
|
||||
return map(all(...ps), () => null);
|
||||
}
|
||||
function flatten(...ps) {
|
||||
return flatten1(all(...ps));
|
||||
}
|
||||
function flatten1(p) {
|
||||
return map(p, (vs) => vs.flatMap((v) => v));
|
||||
}
|
||||
function sepBy1(pValue, pSep) {
|
||||
return ab(pValue, many(right(pSep, pValue)), (head, tail) => [head, ...tail]);
|
||||
}
|
||||
function sepBy(pValue, pSep) {
|
||||
return otherwise(sepBy1(pValue, pSep), emit([]));
|
||||
}
|
||||
function chainReduce(acc,
|
||||
f) {
|
||||
return (data, i) => {
|
||||
let loop = true;
|
||||
let acc1 = acc;
|
||||
let pos = i;
|
||||
do {
|
||||
const r = f(acc1, data, pos)(data, pos);
|
||||
if (r.matched) {
|
||||
acc1 = r.value;
|
||||
pos = r.position;
|
||||
}
|
||||
else {
|
||||
loop = false;
|
||||
}
|
||||
} while (loop);
|
||||
return {
|
||||
matched: true,
|
||||
position: pos,
|
||||
value: acc1
|
||||
};
|
||||
};
|
||||
}
|
||||
function reduceLeft(acc, p,
|
||||
reducer) {
|
||||
return chainReduce(acc, (acc) => map(p, (v, data, i, j) => reducer(acc, v, data, i, j)));
|
||||
}
|
||||
function reduceRight(p, acc,
|
||||
reducer) {
|
||||
return map(many(p), (vs, data, i, j) => vs.reduceRight((acc, v) => reducer(v, acc, data, i, j), acc));
|
||||
}
|
||||
function leftAssoc1(pLeft, pOper) {
|
||||
return chain(pLeft, (v0) => reduceLeft(v0, pOper, (acc, f) => f(acc)));
|
||||
}
|
||||
function rightAssoc1(pOper, pRight) {
|
||||
return ab(reduceRight(pOper, (y) => y, (f, acc) => (y) => f(acc(y))), pRight, (f, v) => f(v));
|
||||
}
|
||||
function leftAssoc2(pLeft, pOper, pRight) {
|
||||
return chain(pLeft, (v0) => reduceLeft(v0, ab(pOper, pRight, (f, y) => [f, y]), (acc, [f, y]) => f(acc, y)));
|
||||
}
|
||||
function rightAssoc2(pLeft, pOper, pRight) {
|
||||
return ab(reduceRight(ab(pLeft, pOper, (x, f) => [x, f]), (y) => y, ([x, f], acc) => (y) => f(x, acc(y))), pRight, (f, v) => f(v));
|
||||
}
|
||||
function condition(cond, pTrue, pFalse) {
|
||||
return (data, i) => (cond(data, i))
|
||||
? pTrue(data, i)
|
||||
: pFalse(data, i);
|
||||
}
|
||||
function decide(p) {
|
||||
return (data, i) => mapOuter(p(data, i), (m1) => m1.value(data, m1.position));
|
||||
}
|
||||
function chain(p,
|
||||
f) {
|
||||
return (data, i) => mapOuter(p(data, i), (m1) => f(m1.value, data, i, m1.position)(data, m1.position));
|
||||
}
|
||||
function ahead(p) {
|
||||
return (data, i) => mapOuter(p(data, i), (m1) => ({
|
||||
matched: true,
|
||||
position: i,
|
||||
value: m1.value
|
||||
}));
|
||||
}
|
||||
function recursive(f) {
|
||||
return function (data, i) {
|
||||
return f()(data, i);
|
||||
};
|
||||
}
|
||||
function start(data, i) {
|
||||
return (i !== 0)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: true
|
||||
};
|
||||
}
|
||||
function end(data, i) {
|
||||
return (i < data.tokens.length)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: true
|
||||
};
|
||||
}
|
||||
function remainingTokensNumber(data, i) {
|
||||
return data.tokens.length - i;
|
||||
}
|
||||
function parserPosition(data, i, formatToken, contextTokens = 3) {
|
||||
const len = data.tokens.length;
|
||||
const lowIndex = util.clamp(0, i - contextTokens, len - contextTokens);
|
||||
const highIndex = util.clamp(contextTokens, i + 1 + contextTokens, len);
|
||||
const tokensSlice = data.tokens.slice(lowIndex, highIndex);
|
||||
const lines = [];
|
||||
const indexWidth = String(highIndex - 1).length + 1;
|
||||
if (i < 0) {
|
||||
lines.push(`${String(i).padStart(indexWidth)} >>`);
|
||||
}
|
||||
if (0 < lowIndex) {
|
||||
lines.push('...'.padStart(indexWidth + 6));
|
||||
}
|
||||
for (let j = 0; j < tokensSlice.length; j++) {
|
||||
const index = lowIndex + j;
|
||||
lines.push(`${String(index).padStart(indexWidth)} ${(index === i ? '>' : ' ')} ${util.escapeWhitespace(formatToken(tokensSlice[j]))}`);
|
||||
}
|
||||
if (highIndex < len) {
|
||||
lines.push('...'.padStart(indexWidth + 6));
|
||||
}
|
||||
if (len <= i) {
|
||||
lines.push(`${String(i).padStart(indexWidth)} >>`);
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
function parse(parser, tokens, options, formatToken = JSON.stringify) {
|
||||
const data = { tokens: tokens, options: options };
|
||||
const result = parser(data, 0);
|
||||
if (!result.matched) {
|
||||
throw new Error('No match');
|
||||
}
|
||||
if (result.position < data.tokens.length) {
|
||||
throw new Error(`Partial match. Parsing stopped at:\n${parserPosition(data, result.position, formatToken)}`);
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
function tryParse(parser, tokens, options) {
|
||||
const result = parser({ tokens: tokens, options: options }, 0);
|
||||
return (result.matched)
|
||||
? result.value
|
||||
: undefined;
|
||||
}
|
||||
function match(matcher, tokens, options) {
|
||||
const result = matcher({ tokens: tokens, options: options }, 0);
|
||||
return result.value;
|
||||
}
|
||||
|
||||
exports.ab = ab;
|
||||
exports.abc = abc;
|
||||
exports.action = action;
|
||||
exports.ahead = ahead;
|
||||
exports.all = all;
|
||||
exports.and = all;
|
||||
exports.any = any;
|
||||
exports.chain = chain;
|
||||
exports.chainReduce = chainReduce;
|
||||
exports.choice = choice;
|
||||
exports.condition = condition;
|
||||
exports.decide = decide;
|
||||
exports.discard = skip;
|
||||
exports.eitherOr = otherwise;
|
||||
exports.emit = emit;
|
||||
exports.end = end;
|
||||
exports.eof = end;
|
||||
exports.error = error;
|
||||
exports.fail = fail;
|
||||
exports.flatten = flatten;
|
||||
exports.flatten1 = flatten1;
|
||||
exports.left = left;
|
||||
exports.leftAssoc1 = leftAssoc1;
|
||||
exports.leftAssoc2 = leftAssoc2;
|
||||
exports.longest = longest;
|
||||
exports.lookAhead = ahead;
|
||||
exports.make = make;
|
||||
exports.many = many;
|
||||
exports.many1 = many1;
|
||||
exports.map = map;
|
||||
exports.map1 = map1;
|
||||
exports.match = match;
|
||||
exports.middle = middle;
|
||||
exports.not = not;
|
||||
exports.of = emit;
|
||||
exports.option = option;
|
||||
exports.or = choice;
|
||||
exports.otherwise = otherwise;
|
||||
exports.parse = parse;
|
||||
exports.parserPosition = parserPosition;
|
||||
exports.peek = peek;
|
||||
exports.recursive = recursive;
|
||||
exports.reduceLeft = reduceLeft;
|
||||
exports.reduceRight = reduceRight;
|
||||
exports.remainingTokensNumber = remainingTokensNumber;
|
||||
exports.right = right;
|
||||
exports.rightAssoc1 = rightAssoc1;
|
||||
exports.rightAssoc2 = rightAssoc2;
|
||||
exports.satisfy = satisfy;
|
||||
exports.sepBy = sepBy;
|
||||
exports.sepBy1 = sepBy1;
|
||||
exports.skip = skip;
|
||||
exports.some = many1;
|
||||
exports.start = start;
|
||||
exports.takeUntil = takeUntil;
|
||||
exports.takeUntilP = takeUntilP;
|
||||
exports.takeWhile = takeWhile;
|
||||
exports.takeWhileP = takeWhileP;
|
||||
exports.token = token;
|
||||
exports.tryParse = tryParse;
|
1051
node_modules/peberminta/lib/core.d.ts
generated
vendored
Normal file
1051
node_modules/peberminta/lib/core.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
384
node_modules/peberminta/lib/core.mjs
generated
vendored
Normal file
384
node_modules/peberminta/lib/core.mjs
generated
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
import { clamp, escapeWhitespace } from './util.mjs';
|
||||
|
||||
function emit(value) {
|
||||
return (data, i) => ({
|
||||
matched: true,
|
||||
position: i,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
function make(
|
||||
f) {
|
||||
return (data, i) => ({
|
||||
matched: true,
|
||||
position: i,
|
||||
value: f(data, i)
|
||||
});
|
||||
}
|
||||
function action(
|
||||
f) {
|
||||
return (data, i) => {
|
||||
f(data, i);
|
||||
return {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: null
|
||||
};
|
||||
};
|
||||
}
|
||||
function fail(
|
||||
data, i) {
|
||||
return { matched: false };
|
||||
}
|
||||
function error(message) {
|
||||
return (data, i) => {
|
||||
throw new Error((message instanceof Function) ? message(data, i) : message);
|
||||
};
|
||||
}
|
||||
function token(
|
||||
onToken,
|
||||
onEnd) {
|
||||
return (data, i) => {
|
||||
let position = i;
|
||||
let value = undefined;
|
||||
if (i < data.tokens.length) {
|
||||
value = onToken(data.tokens[i], data, i);
|
||||
if (value !== undefined) {
|
||||
position++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
onEnd?.(data, i);
|
||||
}
|
||||
return (value === undefined)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: position,
|
||||
value: value
|
||||
};
|
||||
};
|
||||
}
|
||||
function any(data, i) {
|
||||
return (i < data.tokens.length)
|
||||
? {
|
||||
matched: true,
|
||||
position: i + 1,
|
||||
value: data.tokens[i]
|
||||
}
|
||||
: { matched: false };
|
||||
}
|
||||
function satisfy(
|
||||
test) {
|
||||
return (data, i) => (i < data.tokens.length && test(data.tokens[i], data, i))
|
||||
? {
|
||||
matched: true,
|
||||
position: i + 1,
|
||||
value: data.tokens[i]
|
||||
}
|
||||
: { matched: false };
|
||||
}
|
||||
function mapInner(r, f) {
|
||||
return (r.matched) ? ({
|
||||
matched: true,
|
||||
position: r.position,
|
||||
value: f(r.value, r.position)
|
||||
}) : r;
|
||||
}
|
||||
function mapOuter(r, f) {
|
||||
return (r.matched) ? f(r) : r;
|
||||
}
|
||||
function map(p, mapper) {
|
||||
return (data, i) => mapInner(p(data, i), (v, j) => mapper(v, data, i, j));
|
||||
}
|
||||
function map1(p,
|
||||
mapper) {
|
||||
return (data, i) => mapOuter(p(data, i), (m) => mapper(m, data, i));
|
||||
}
|
||||
function peek(p, f) {
|
||||
return (data, i) => {
|
||||
const r = p(data, i);
|
||||
f(r, data, i);
|
||||
return r;
|
||||
};
|
||||
}
|
||||
function option(p, def) {
|
||||
return (data, i) => {
|
||||
const r = p(data, i);
|
||||
return (r.matched)
|
||||
? r
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: def
|
||||
};
|
||||
};
|
||||
}
|
||||
function not(p) {
|
||||
return (data, i) => {
|
||||
const r = p(data, i);
|
||||
return (r.matched)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: true
|
||||
};
|
||||
};
|
||||
}
|
||||
function choice(...ps) {
|
||||
return (data, i) => {
|
||||
for (const p of ps) {
|
||||
const result = p(data, i);
|
||||
if (result.matched) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return { matched: false };
|
||||
};
|
||||
}
|
||||
function otherwise(pa, pb) {
|
||||
return (data, i) => {
|
||||
const r1 = pa(data, i);
|
||||
return (r1.matched)
|
||||
? r1
|
||||
: pb(data, i);
|
||||
};
|
||||
}
|
||||
function longest(...ps) {
|
||||
return (data, i) => {
|
||||
let match = undefined;
|
||||
for (const p of ps) {
|
||||
const result = p(data, i);
|
||||
if (result.matched && (!match || match.position < result.position)) {
|
||||
match = result;
|
||||
}
|
||||
}
|
||||
return match || { matched: false };
|
||||
};
|
||||
}
|
||||
function takeWhile(p,
|
||||
test) {
|
||||
return (data, i) => {
|
||||
const values = [];
|
||||
let success = true;
|
||||
do {
|
||||
const r = p(data, i);
|
||||
if (r.matched && test(r.value, values.length + 1, data, i, r.position)) {
|
||||
values.push(r.value);
|
||||
i = r.position;
|
||||
}
|
||||
else {
|
||||
success = false;
|
||||
}
|
||||
} while (success);
|
||||
return {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: values
|
||||
};
|
||||
};
|
||||
}
|
||||
function takeUntil(p,
|
||||
test) {
|
||||
return takeWhile(p, (value, n, data, i, j) => !test(value, n, data, i, j));
|
||||
}
|
||||
function takeWhileP(pValue, pTest) {
|
||||
return takeWhile(pValue, (value, n, data, i) => pTest(data, i).matched);
|
||||
}
|
||||
function takeUntilP(pValue, pTest) {
|
||||
return takeWhile(pValue, (value, n, data, i) => !pTest(data, i).matched);
|
||||
}
|
||||
function many(p) {
|
||||
return takeWhile(p, () => true);
|
||||
}
|
||||
function many1(p) {
|
||||
return ab(p, many(p), (head, tail) => [head, ...tail]);
|
||||
}
|
||||
function ab(pa, pb, join) {
|
||||
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) => join(ma.value, vb, data, i, j)));
|
||||
}
|
||||
function left(pa, pb) {
|
||||
return ab(pa, pb, (va) => va);
|
||||
}
|
||||
function right(pa, pb) {
|
||||
return ab(pa, pb, (va, vb) => vb);
|
||||
}
|
||||
function abc(pa, pb, pc, join) {
|
||||
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) => join(ma.value, mb.value, vc, data, i, j))));
|
||||
}
|
||||
function middle(pa, pb, pc) {
|
||||
return abc(pa, pb, pc, (ra, rb) => rb);
|
||||
}
|
||||
function all(...ps) {
|
||||
return (data, i) => {
|
||||
const result = [];
|
||||
let position = i;
|
||||
for (const p of ps) {
|
||||
const r1 = p(data, position);
|
||||
if (r1.matched) {
|
||||
result.push(r1.value);
|
||||
position = r1.position;
|
||||
}
|
||||
else {
|
||||
return { matched: false };
|
||||
}
|
||||
}
|
||||
return {
|
||||
matched: true,
|
||||
position: position,
|
||||
value: result
|
||||
};
|
||||
};
|
||||
}
|
||||
function skip(...ps) {
|
||||
return map(all(...ps), () => null);
|
||||
}
|
||||
function flatten(...ps) {
|
||||
return flatten1(all(...ps));
|
||||
}
|
||||
function flatten1(p) {
|
||||
return map(p, (vs) => vs.flatMap((v) => v));
|
||||
}
|
||||
function sepBy1(pValue, pSep) {
|
||||
return ab(pValue, many(right(pSep, pValue)), (head, tail) => [head, ...tail]);
|
||||
}
|
||||
function sepBy(pValue, pSep) {
|
||||
return otherwise(sepBy1(pValue, pSep), emit([]));
|
||||
}
|
||||
function chainReduce(acc,
|
||||
f) {
|
||||
return (data, i) => {
|
||||
let loop = true;
|
||||
let acc1 = acc;
|
||||
let pos = i;
|
||||
do {
|
||||
const r = f(acc1, data, pos)(data, pos);
|
||||
if (r.matched) {
|
||||
acc1 = r.value;
|
||||
pos = r.position;
|
||||
}
|
||||
else {
|
||||
loop = false;
|
||||
}
|
||||
} while (loop);
|
||||
return {
|
||||
matched: true,
|
||||
position: pos,
|
||||
value: acc1
|
||||
};
|
||||
};
|
||||
}
|
||||
function reduceLeft(acc, p,
|
||||
reducer) {
|
||||
return chainReduce(acc, (acc) => map(p, (v, data, i, j) => reducer(acc, v, data, i, j)));
|
||||
}
|
||||
function reduceRight(p, acc,
|
||||
reducer) {
|
||||
return map(many(p), (vs, data, i, j) => vs.reduceRight((acc, v) => reducer(v, acc, data, i, j), acc));
|
||||
}
|
||||
function leftAssoc1(pLeft, pOper) {
|
||||
return chain(pLeft, (v0) => reduceLeft(v0, pOper, (acc, f) => f(acc)));
|
||||
}
|
||||
function rightAssoc1(pOper, pRight) {
|
||||
return ab(reduceRight(pOper, (y) => y, (f, acc) => (y) => f(acc(y))), pRight, (f, v) => f(v));
|
||||
}
|
||||
function leftAssoc2(pLeft, pOper, pRight) {
|
||||
return chain(pLeft, (v0) => reduceLeft(v0, ab(pOper, pRight, (f, y) => [f, y]), (acc, [f, y]) => f(acc, y)));
|
||||
}
|
||||
function rightAssoc2(pLeft, pOper, pRight) {
|
||||
return ab(reduceRight(ab(pLeft, pOper, (x, f) => [x, f]), (y) => y, ([x, f], acc) => (y) => f(x, acc(y))), pRight, (f, v) => f(v));
|
||||
}
|
||||
function condition(cond, pTrue, pFalse) {
|
||||
return (data, i) => (cond(data, i))
|
||||
? pTrue(data, i)
|
||||
: pFalse(data, i);
|
||||
}
|
||||
function decide(p) {
|
||||
return (data, i) => mapOuter(p(data, i), (m1) => m1.value(data, m1.position));
|
||||
}
|
||||
function chain(p,
|
||||
f) {
|
||||
return (data, i) => mapOuter(p(data, i), (m1) => f(m1.value, data, i, m1.position)(data, m1.position));
|
||||
}
|
||||
function ahead(p) {
|
||||
return (data, i) => mapOuter(p(data, i), (m1) => ({
|
||||
matched: true,
|
||||
position: i,
|
||||
value: m1.value
|
||||
}));
|
||||
}
|
||||
function recursive(f) {
|
||||
return function (data, i) {
|
||||
return f()(data, i);
|
||||
};
|
||||
}
|
||||
function start(data, i) {
|
||||
return (i !== 0)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: true
|
||||
};
|
||||
}
|
||||
function end(data, i) {
|
||||
return (i < data.tokens.length)
|
||||
? { matched: false }
|
||||
: {
|
||||
matched: true,
|
||||
position: i,
|
||||
value: true
|
||||
};
|
||||
}
|
||||
function remainingTokensNumber(data, i) {
|
||||
return data.tokens.length - i;
|
||||
}
|
||||
function parserPosition(data, i, formatToken, contextTokens = 3) {
|
||||
const len = data.tokens.length;
|
||||
const lowIndex = clamp(0, i - contextTokens, len - contextTokens);
|
||||
const highIndex = clamp(contextTokens, i + 1 + contextTokens, len);
|
||||
const tokensSlice = data.tokens.slice(lowIndex, highIndex);
|
||||
const lines = [];
|
||||
const indexWidth = String(highIndex - 1).length + 1;
|
||||
if (i < 0) {
|
||||
lines.push(`${String(i).padStart(indexWidth)} >>`);
|
||||
}
|
||||
if (0 < lowIndex) {
|
||||
lines.push('...'.padStart(indexWidth + 6));
|
||||
}
|
||||
for (let j = 0; j < tokensSlice.length; j++) {
|
||||
const index = lowIndex + j;
|
||||
lines.push(`${String(index).padStart(indexWidth)} ${(index === i ? '>' : ' ')} ${escapeWhitespace(formatToken(tokensSlice[j]))}`);
|
||||
}
|
||||
if (highIndex < len) {
|
||||
lines.push('...'.padStart(indexWidth + 6));
|
||||
}
|
||||
if (len <= i) {
|
||||
lines.push(`${String(i).padStart(indexWidth)} >>`);
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
function parse(parser, tokens, options, formatToken = JSON.stringify) {
|
||||
const data = { tokens: tokens, options: options };
|
||||
const result = parser(data, 0);
|
||||
if (!result.matched) {
|
||||
throw new Error('No match');
|
||||
}
|
||||
if (result.position < data.tokens.length) {
|
||||
throw new Error(`Partial match. Parsing stopped at:\n${parserPosition(data, result.position, formatToken)}`);
|
||||
}
|
||||
return result.value;
|
||||
}
|
||||
function tryParse(parser, tokens, options) {
|
||||
const result = parser({ tokens: tokens, options: options }, 0);
|
||||
return (result.matched)
|
||||
? result.value
|
||||
: undefined;
|
||||
}
|
||||
function match(matcher, tokens, options) {
|
||||
const result = matcher({ tokens: tokens, options: options }, 0);
|
||||
return result.value;
|
||||
}
|
||||
|
||||
export { ab, abc, action, ahead, all, all as and, any, chain, chainReduce, choice, condition, decide, skip as discard, otherwise as eitherOr, emit, end, end as eof, error, fail, flatten, flatten1, left, leftAssoc1, leftAssoc2, longest, ahead as lookAhead, make, many, many1, map, map1, match, middle, not, emit as of, option, choice as or, otherwise, parse, parserPosition, peek, recursive, reduceLeft, reduceRight, remainingTokensNumber, right, rightAssoc1, rightAssoc2, satisfy, sepBy, sepBy1, skip, many1 as some, start, takeUntil, takeUntilP, takeWhile, takeWhileP, token, tryParse };
|
13
node_modules/peberminta/lib/util.cjs
generated
vendored
Normal file
13
node_modules/peberminta/lib/util.cjs
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
function clamp(left, x, right) {
|
||||
return Math.max(left, Math.min(x, right));
|
||||
}
|
||||
function escapeWhitespace(str) {
|
||||
return str.replace(/(\t)|(\r)|(\n)/g, (m, t, r) => t ? '\\t' : r ? '\\r' : '\\n');
|
||||
}
|
||||
|
||||
exports.clamp = clamp;
|
||||
exports.escapeWhitespace = escapeWhitespace;
|
8
node_modules/peberminta/lib/util.mjs
generated
vendored
Normal file
8
node_modules/peberminta/lib/util.mjs
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
function clamp(left, x, right) {
|
||||
return Math.max(left, Math.min(x, right));
|
||||
}
|
||||
function escapeWhitespace(str) {
|
||||
return str.replace(/(\t)|(\r)|(\n)/g, (m, t, r) => t ? '\\t' : r ? '\\r' : '\\n');
|
||||
}
|
||||
|
||||
export { clamp, escapeWhitespace };
|
Reference in New Issue
Block a user