UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

147 lines 5.5 kB
"use strict"; 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