UNPKG

@abaplint/transpiler

Version:
111 lines 3.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Rearranger = void 0; const core_1 = require("@abaplint/core"); // this rearranges the AST to take precedence into account class Rearranger { run(type, node) { if (!node) { return undefined; } if (type === "INTF") { // no arithmethic expressions in global interfaces return node; } const flattened = this.flatten(node); const rebuilt = this.rebuild(flattened); return rebuilt; } ///////////////// rebuild(node) { if (node instanceof core_1.Nodes.TokenNode) { return node; } const children = node.getChildren(); children.forEach(this.rebuild.bind(this)); if (node instanceof core_1.Nodes.ExpressionNode) { this.precedence(node); } return node; } // this takes a single flattened node, and splits into binary nodes according to precedence and left to right processing precedence(node) { const children = node.getChildren(); const arith = node.findDirectExpressions(core_1.Expressions.ArithOperator); // after flattening it might have multiple operators under the samenode if (arith.length <= 1) { return; } let splitAt; // multiplication/division and left to right for (let i = arith.length - 1; i >= 0; i--) { const a = arith[i]; const concat = a.concatTokens().toUpperCase(); if (concat === "*" || concat === "/" || concat === "**" || concat === "MOD" || concat === "DIV") { continue; } splitAt = a; break; } // fallback if (splitAt === undefined) { splitAt = arith[arith.length - 1]; } const index = children.indexOf(splitAt); let left = []; { const lhs = children.slice(0, index); if (lhs.length > 1) { const temp = new core_1.Nodes.ExpressionNode(node.get()); temp.setChildren(lhs); this.precedence(temp); left.push(temp); } else { left = lhs; } } let right = []; { const rhs = children.slice(index + 1); if (rhs.length > 1) { const temp = new core_1.Nodes.ExpressionNode(node.get()); temp.setChildren(rhs); this.precedence(temp); right.push(temp); } else { right = rhs; } } node.setChildren(left.concat([splitAt]).concat(right)); } // this flattens the arithmethic expressions so all related is under the same node flatten(node) { if (node instanceof core_1.Nodes.TokenNode) { return node; } const children = node.getChildren(); children.forEach(this.flatten.bind(this)); const last = children[children.length - 1]; const secondLast = children[children.length - 2]; if (last === undefined || secondLast === undefined || !(last instanceof core_1.Nodes.ExpressionNode) || !(last.get() instanceof core_1.Expressions.Source) || !(secondLast instanceof core_1.Nodes.ExpressionNode) || !(secondLast.get() instanceof core_1.Expressions.ArithOperator)) { return node; } const withoutLast = node.getChildren().slice(0, children.length - 1); const flat = withoutLast.concat(last.getChildren()); node.setChildren(flat); return node; } } exports.Rearranger = Rearranger; //# sourceMappingURL=rearranger.js.map