UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

98 lines 3.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RootId = void 0; exports.prepareParsedData = prepareParsedData; exports.convertPreparedParsedData = convertPreparedParsedData; const retriever_1 = require("../../../../retriever"); const assert_1 = require("../../../../../util/assert"); const type_1 = require("../../model/type"); exports.RootId = 0; /** * Takes the raw {@link RShell} output and extracts the csv information contained */ function prepareParsedData(data) { let json; try { json = JSON.parse(`[${data.trim()}]`); } catch (e) { throw new Error(`Failed to parse data [${data}]: ${e?.message}`); } (0, assert_1.guard)(Array.isArray(json), () => `Expected ${data} to be an array but was not`); const ret = new Map(json.map(([line1, col1, line2, col2, id, parent, token, terminal, text]) => { return [id, { line1, col1, line2, col2, id, parent, token: (0, retriever_1.removeRQuotes)(token), terminal, text }]; })); const roots = []; // iterate a second time to set parent-child relations (since they may be out of order in the csv) for (const entry of ret.values()) { if (entry.parent != exports.RootId) { /** it turns out that comments may return a negative id pair to their parent */ const parent = ret.get(Math.abs(entry.parent)); if (parent) { parent.children ??= []; parent.children.push(entry); } } else { roots.push(entry); } } return roots; } /** * Takes the CSV-Entries and maps them to the old json format for compatibility. */ function convertPreparedParsedData(roots) { const partialEntry = { token: type_1.RawRType.ExpressionList, text: '', id: exports.RootId, parent: exports.RootId }; // if we don't have children, this is simple if (roots.length <= 0) { return { ...partialEntry, line1: 1, col1: 1, line2: 1, col2: 1, children: [] }; } // Locate start, end of a source file (order children in advance). const rootEntries = [...roots].sort(orderOf); const start = rootEntries[0]; const end = rootEntries[rootEntries.length - 1]; // Construct CsvEntry for the root, handling empty input. const csvParent = { ...partialEntry, line1: start?.line1 ?? 1, col1: start?.col1 ?? 1, line2: end?.line2 ?? 1, col2: end?.col2 ?? 1, children: rootEntries, terminal: false }; // Return actual value. return convertEntry(csvParent); } function convertEntry(csvEntry) { return { ...csvEntry, // check and recursively iterate children children: csvEntry.children?.sort(orderOf).map(convertEntry) ?? [] }; } /** * we sort children the same way xmlparsedata does (by line, by column, by inverse end line, by inverse end column, by terminal state, by combined "start" tiebreaker value) * (https://github.com/r-lib/xmlparsedata/blob/v1.0.5/R/package.R#L120) */ function orderOf(c1, c2) { return c1.line1 - c2.line1 || c1.col1 - c2.col1 || c2.line2 - c1.line2 || c2.col2 - c1.col2 || Number(c1.terminal) - Number(c2.terminal) || sortTiebreak(c1) - sortTiebreak(c2); } function sortTiebreak({ line1, col1, col2 }) { // see https://github.com/r-lib/xmlparsedata/blob/v1.0.5/R/package.R#L86 return line1 * (Math.max(col1, col2) + 1) + col1; } //# sourceMappingURL=format.js.map