pegjs-backtrace
Version:
A debug backtrace module for PEG.js.
138 lines (112 loc) • 3.48 kB
JavaScript
"use strict";
var TextUtil = require("./text-util");
var defaultOptions = {
useColor: true
};
var _applyDefault = function(opt, def) {
var ret = {};
for (var key in def) {
ret[key] = opt && opt[key] !== undefined ? opt[key] : def[key];
}
return ret;
};
var TextGraph = function(opt) {
this.options = _applyDefault(opt, defaultOptions);
};
TextGraph.prototype.setTextStyle = function(str, style, start, end) {
if (this.options.useColor) {
return TextUtil.setTextStyle(str, style, start, end);
} else {
return str;
}
};
TextGraph.prototype.drawState = function(nodes, column, contents, isLastState) {
var buf = [];
contents = contents || [];
if (0 < contents.length) {
buf.push(this.drawStateLine(nodes, column, isLastState) + contents.shift());
while (0 < contents.length) {
buf.push(
this.drawStateLine(nodes, undefined, isLastState) + contents.shift()
);
}
} else {
buf.push(this.drawStateLine(nodes, column, isLastState));
}
return buf;
};
TextGraph.prototype.drawStateLine = function(nodes, column, isLastState) {
var line = "",
i,
quote = isLastState ? " " : "| ";
for (i = 0; i < nodes.length; i++) {
if (column === i) {
if (nodes[i].type == "rule.fail") {
line += this.setTextStyle("x ", { color: "red" });
} else if (nodes[i].type == "rule.match") {
line += this.setTextStyle("o ", { color: "green" });
} else {
line += this.setTextStyle("? ", { color: "yellow" });
}
} else {
line += this.setTextStyle(quote, nodes[i].style);
}
}
return line;
};
TextGraph.prototype.drawMergeEdge = function(fromIndex, toIndex, nodes) {
var lines = ["", ""],
i;
for (i = 0; i < nodes.length; i++) {
if (i <= toIndex) {
lines[0] += this.setTextStyle("| ", nodes[i].style);
} else if (i < fromIndex - 1) {
lines[0] +=
this.setTextStyle("|", nodes[i].style) +
this.setTextStyle("_", nodes[fromIndex].style);
} else if (i == fromIndex - 1) {
lines[0] +=
this.setTextStyle("|", nodes[i].style) +
this.setTextStyle("/", nodes[fromIndex].style);
} else if (fromIndex < i || (i == fromIndex && toIndex + 1 == fromIndex)) {
lines[0] += this.setTextStyle("| ", nodes[i].style);
} else {
lines[0] += " ";
}
}
for (i = 0; i < nodes.length; i++) {
if (i < toIndex) {
lines[1] += this.setTextStyle("| ", nodes[i].style);
} else if (i == toIndex) {
lines[1] +=
this.setTextStyle("|", nodes[i].style) +
this.setTextStyle("/", nodes[fromIndex].style);
} else if (i < fromIndex) {
lines[1] += this.setTextStyle("| ", nodes[i].style);
} else if (i < nodes.length - 1) {
lines[1] += this.setTextStyle(" /", nodes[i + 1].style);
} else {
lines[1] += " ";
}
}
return lines;
};
TextGraph.prototype.drawMergeEdges = function(fromIndexes, toIndex, nodes) {
nodes = nodes.slice(0);
fromIndexes = fromIndexes.slice(0);
fromIndexes.sort(function(a, b) {
return a - b;
});
var lines = [],
i;
while (0 < fromIndexes.length) {
var fromIndex = fromIndexes.shift();
lines = lines.concat(this.drawMergeEdge(fromIndex, toIndex, nodes));
nodes.splice(fromIndex, 1);
for (var i = 0; i < fromIndexes.length; i++) {
if (fromIndex < fromIndexes[i]) fromIndexes[i]--;
}
}
return lines;
};
module.exports = TextGraph;