Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const Parsimmon = require('parsimmon');
- const {fail, lazy} = Parsimmon;
- const SIN_MAX = 10;
- const indLog = (...args) => console.log(logIndent, ...args);
- const logDebug = false;
- const logAnnotations = false;
- const fullValues = true;
- const okDetails = true;
- const logFails = true;
- let sinCounter = 0;
- let logIndent = '';
- let stack = [];
- const captureStack = (type, tag, i) => {
- stack = [...stack, [type, tag, i]];
- };
- const reportStack = (stack, input) => {
- return stack
- .map(([type, tag, i]) =>
- logIndent + ' ' + tag + ' : '.yellow +
- reportPos(input, i) + ' ' +
- shortCodeRef(input, i)
- )
- .join('\n');
- };
- const reportPos = (inp, i) => {
- const lines = inp.slice(0, i).split(/([\n\r][\n\r]?)/g);
- const pos = i - lines.slice(0, -1).join('').length;
- return `${Math.round(lines.length/2)}:${pos}`;
- };
- const shortCodeRef = (input, i) => JSON.stringify(input.slice(i, i + 30) + '...');
- Parsimmon.prototype.breakOnRepeat = function (tag) {
- let visited = {};
- let n = 0;
- return Parsimmon((input, i) => {
- const visitLabel = tag + '-' + n++;
- indLog(visitLabel.yellow, shortCodeRef(input, i));
- captureStack('break', visitLabel, i);
- if (visited[i]) {
- sinCounter++;
- indLog((`${tag} already visited position ${i} (${shortCodeRef(input, i)}). Visit label was ` + `${visited[i][0]}`.yellow).bgRed);
- if (sinCounter >= SIN_MAX) {
- console.log('\n\n\n');
- indLog('stack was: ');
- console.log(reportStack(visited[i][1], input));
- indLog('stack now:');
- console.log(reportStack(stack, input));
- console.log('\n\n\n');
- throw new Error(`you are bloody sinner`);
- }
- }
- visited[i] = [visitLabel, stack];
- const result = this._(input, i);
- stack = stack.slice(0, -1);
- return result;
- });
- };
- const stripMiddle = (s, n=50) => s.length < (n + 3) ? s : s.slice(0, n/2) + '...' + s.slice(-n/2);
- Parsimmon.prototype.log = function (tag, highlightTag = false) {
- if (highlightTag) {
- tag = '['.bgBlue + tag + ']'.bgBlue
- }
- require('colors');
- return Parsimmon((input, i) => {
- const oldLogIndent = logIndent;
- indLog(tag, shortCodeRef(input, i));
- logIndent += ' ';
- captureStack('log', tag, i);
- const result = this._(input, i);
- stack = stack.slice(0, -1);
- if (result.status) {
- const before = '...' + JSON.stringify(input.slice(i - 5, i)).slice(1, -1);
- const match = '['.yellow + stripMiddle(JSON.stringify(input.slice(i, result.index)).slice(1, -1)).green + ']'.yellow;
- const after = JSON.stringify(input.slice(result.index, result.index + 5)).slice(1, -1) + '...';
- const valueReport = fullValues ? JSON.stringify(result.value) : stripMiddle(JSON.stringify(result.value));
- const okDetailsReport = okDetails ? before + match + after + ' => ' + valueReport : valueReport;
- indLog(`ok(${tag})`.green, okDetailsReport);
- } else {
- logFails && indLog(`fail(${tag}) ${shortCodeRef(input, i)}`.red);
- }
- logIndent = oldLogIndent;
- return result;
- });
- };
- const seqAnnotate = (tag, ...parsers) => Parsimmon.seq(...parsers).annotate(tag);
- Parsimmon.prototype.debug = function (tag, hightlightTag) {
- if (logDebug) {
- return this.log(tag, hightlightTag);
- }
- return this;
- };
- const value = (v) => Parsimmon((input, i) => Parsimmon.makeSuccess(i, v));
- const offset = Parsimmon((input, i) => Parsimmon.makeSuccess(i, i));
- Parsimmon.prototype.annotate = function (type, highlightTag = false) {
- const parser = Parsimmon.seqObj(
- ['type', value(type)],
- ['start', offset],
- ['value', this],
- ['end', offset]
- );
- if (logAnnotations) {
- return parser.log(type, highlightTag);
- }
- return parser;
- };
- Parsimmon.prototype.spaced = function () {
- return spaced(this);
- };
- const logger = tag => x => {
- console.log(tag, JSON.stringify(x));
- return x;
- };
- const stats = {};
- const count = tag => x => {
- stats[tag] = (stats[tag] || 0) + 1;
- return x;
- };
- module.exports = {
- logger,
- spaced,
- count,
- stats,
- seqAnnotate
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement