@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
80 lines • 3.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizedAstToMermaid = normalizedAstToMermaid;
exports.normalizedAstToMermaidUrl = normalizedAstToMermaidUrl;
const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
const flowr_file_1 = require("../../project/context/flowr-file");
const info_1 = require("./info");
const model_1 = require("../../r-bridge/lang-4.x/ast/model/model");
const mermaid_1 = require("./mermaid");
function identifyMermaidDirection(prefix) {
const directionMatch = prefix.match(/flowchart (TD|LR|RL|BT)/);
if (directionMatch) {
return directionMatch[1];
}
return 'TD';
}
/**
* Serialize the normalized AST to mermaid format
*/
function normalizedAstToMermaid(ast, { prefix = 'flowchart TD\n', markStyle = info_1.MermaidDefaultMarkStyle, includeOnlyIds, mark } = {}) {
let output = prefix;
function showNode(n) {
if (includeOnlyIds && !includeOnlyIds.has(n.info.id)) {
return;
}
const name = `${n.type} (${n.info.id})\\n${n.lexeme ?? ' '}`;
output += ` n${n.info.id}(["${mermaid_1.Mermaid.escape(name)}"])\n`;
if (mark?.has(n.info.id)) {
output += ` style n${n.info.id} ${markStyle.vertex}\n`;
}
if (n.info.parent !== undefined && (!includeOnlyIds || includeOnlyIds.has(n.info.parent))) {
const context = n.info;
const roleSuffix = context.role === "el-c" /* RoleInParent.ExpressionListChild */ || context.role === "call-arg" /* RoleInParent.FunctionCallArgument */ || context.role === "param" /* RoleInParent.FunctionDefinitionParameter */ ? `-${context.index}` : '';
output += ` n${n.info.parent} -->|"${context.role}${roleSuffix}"| n${n.info.id}\n`;
}
if (n.type === type_1.RType.ExpressionList && n.grouping !== undefined) {
output += ` n${n.info.id} -.-|"group-open"| n${n.grouping[0].info.id}\n`;
output += ` n${n.info.id} -.-|"group-close"| n${n.grouping[1].info.id}\n`;
}
}
function showAst(ast) {
model_1.RNode.visitAst(ast, n => {
showNode(n);
if (n.type === 'RAccess' && (n.operator !== '[' && n.operator !== '[[')) {
for (const k of n.access) {
if (k !== r_function_call_1.EmptyArgument) {
showNode(k);
}
}
}
return false;
});
}
if (ast.type === type_1.RType.Project) {
for (const f of ast.files) {
// add a subgraph for each file
if (ast.files.length !== 1 || (f.filePath && f.filePath !== flowr_file_1.FlowrFile.INLINE_PATH)) {
const direction = identifyMermaidDirection(prefix);
output += ` subgraph "File: ${mermaid_1.Mermaid.escape(f.filePath ?? flowr_file_1.FlowrFile.INLINE_PATH)}" direction ${direction}\n`;
showAst(f.root);
output += ' end\n';
}
else {
showAst(f.root);
}
}
}
else {
showAst(ast);
}
return output;
}
/**
* Use mermaid to visualize the normalized AST.
*/
function normalizedAstToMermaidUrl(ast, info) {
return mermaid_1.Mermaid.codeToUrl(normalizedAstToMermaid(ast, info ?? {}));
}
//# sourceMappingURL=ast.js.map