'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;