@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
147 lines • 5.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCommand = void 0;
const format_1 = require("../../../r-bridge/lang-4.x/ast/parser/json/format");
const normalize_meta_1 = require("../../../r-bridge/lang-4.x/ast/parser/main/normalize-meta");
const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
const retriever_1 = require("../../../r-bridge/retriever");
function toDepthMap(entry) {
const visit = [{ depth: 0, node: entry }];
const result = [];
while (visit.length > 0) {
const current = visit.pop();
if (current === undefined) {
continue;
}
const children = current.node.children;
result.push({ ...current, leaf: children.length === 0 });
children.reverse();
const nextDepth = current.depth + 1;
for (const c of children) {
visit.push({ depth: nextDepth, node: c });
}
}
return result;
}
function treeSitterToJsonEntry(node) {
return {
token: node.type,
children: [],
text: node.text,
id: node.id,
parent: node.parent?.id ?? -1,
terminal: node.isNamed,
line1: node.startPosition.row + 1,
col1: node.startPosition.column + 1,
line2: node.endPosition.row + 1,
col2: node.endPosition.column + 1
};
}
function treeSitterToDepthList(node) {
const visit = [{ depth: 0, node }];
const result = [];
while (visit.length > 0) {
const current = visit.pop();
if (current === undefined) {
continue;
}
const children = current.node.children;
result.push({ depth: current.depth, node: treeSitterToJsonEntry(current.node), leaf: children.length === 0 });
children.reverse();
const nextDepth = current.depth + 1;
for (const c of children) {
visit.push({ depth: nextDepth, node: c });
}
}
return result;
}
function lastElementInNesting(i, list, depth) {
for (let j = i + 1; j < list.length; j++) {
if (list[j].depth < depth) {
return true;
}
if (list[j].depth === depth) {
return false;
}
}
// only more deeply nested come after
return true;
}
function initialIndentation(i, depth, deadDepths, nextDepth, list, f) {
let result = `${i === 0 ? '' : '\n'}${f.getFormatString({ style: 2 /* FontStyles.Faint */ })}`;
// we know there never is something on the same level as the expression list
for (let d = 1; d < depth; d++) {
result += deadDepths.has(d) ? ' ' : '│ ';
}
if (nextDepth < depth) {
result += '╰ ';
}
else if (i > 0) {
// check if we are maybe the last one with this depth until someone with a lower depth comes around
const isLast = lastElementInNesting(i, list, depth);
result += isLast ? '╰ ' : '├ ';
if (isLast) {
deadDepths.add(depth);
}
}
return result;
}
function retrieveLocationString(locationRaw) {
const extracted = (0, normalize_meta_1.extractLocation)(locationRaw);
if (extracted[0] === extracted[2] && extracted[1] === extracted[3]) {
return ` (${extracted[0]}:${extracted[1]})`;
}
else if (extracted[0] === extracted[2]) {
return ` (${extracted[0]}:${extracted[1]}─${extracted[3]})`;
}
else {
return ` (${extracted[0]}:${extracted[1]}─${extracted[2]}:${extracted[3]})`;
}
}
function depthListToTextTree(list, f) {
let result = '';
const deadDepths = new Set();
let i = 0;
for (const { depth, node, leaf } of list) {
if (depth > 10) {
result += '...';
break;
}
const nextDepth = i + 1 < list.length ? list[i + 1].depth : 0;
deadDepths.delete(depth);
result += initialIndentation(i, depth, deadDepths, nextDepth, list, f);
result += f.reset();
const content = node.text;
const location = retrieveLocationString(node);
const type = (0, normalize_meta_1.getTokenType)(node);
if (leaf) {
const suffix = `${f.format(content ? JSON.stringify(content) : '', { style: 1 /* FontStyles.Bold */ })}${f.format(location, { style: 3 /* FontStyles.Italic */ })}`;
result += `${type} ${suffix}`;
}
else {
result += f.format(type, { style: 1 /* FontStyles.Bold */ });
}
i++;
}
return result;
}
exports.parseCommand = {
description: `Prints ASCII Art of the parsed, unmodified AST, start with '${retriever_1.fileProtocol}' to indicate a file`,
usageExample: ':parse',
aliases: ['p'],
script: false,
fn: async (output, parser, remainingLine) => {
const result = await (0, default_pipelines_1.createParsePipeline)(parser, {
request: (0, retriever_1.requestFromInput)((0, retriever_1.removeRQuotes)(remainingLine.trim()))
}).allRemainingSteps();
if (parser.name === 'r-shell') {
const object = (0, format_1.convertPreparedParsedData)((0, format_1.prepareParsedData)(result.parse.parsed));
output.stdout(depthListToTextTree(toDepthMap(object), output.formatter));
}
else {
// print the tree-sitter ast
output.stdout(depthListToTextTree(treeSitterToDepthList(result.parse.parsed.rootNode), output.formatter));
}
}
};
//# sourceMappingURL=repl-parse.js.map