kmap-term-tree
Version:
Renders a tree from a mathematical term
96 lines • 3.25 kB
JavaScript
export class TermNode {
constructor(token, leftChildNode, rightChildNode) {
this.toString = () => { return this.token.value; };
this.token = token;
this.leftChildNode = leftChildNode;
this.rightChildNode = rightChildNode;
}
breadthFirst(callback) {
var queue = [this];
var depth = [0];
var n;
var d;
while (queue.length > 0) {
n = queue.shift();
d = depth.shift();
if (n === undefined || d === undefined)
throw new Error("nonsense");
callback(n, d);
if (n.rightChildNode) {
queue.push(n.rightChildNode);
depth.push(d + 1);
}
if (n.leftChildNode) {
queue.push(n.leftChildNode);
depth.push(d + 1);
}
}
}
}
class Stack {
constructor() {
this.array = [];
}
push(o) { this.array.push(o); }
;
pop() { return this.array.pop(); }
;
peek() { return this.array.slice(-1)[0]; }
;
isEmpty() { return this.array.length === 0; }
;
clear() { this.array = []; }
}
export class Parser {
constructor() {
this.opStack = new Stack();
this.outStack = new Stack();
}
outOperator(operatorToken) {
const rightChildNode = this.outStack.pop();
const leftChildNode = this.outStack.pop();
this.outStack.push(new TermNode(operatorToken, leftChildNode, rightChildNode));
}
outFunction(operatorToken) {
const leftChildNode = this.outStack.pop();
this.outStack.push(new TermNode(operatorToken, leftChildNode));
}
// https://de.wikipedia.org/wiki/Shunting-yard-Algorithmus
parse(tokens) {
this.opStack.clear();
this.outStack.clear();
tokens.forEach((t) => {
if (t.type === "Literal" || t.type === "Variable") {
this.outStack.push(new TermNode(t));
}
else if (t.type === "Function") {
this.opStack.push(t);
}
else if (t.type === "Comma") {
}
else if (t.type === "Operator") {
while (!this.opStack.isEmpty()
&& this.opStack.peek().type === "Operator"
&& t.associativity() === "left"
&& t.precedence() <= this.opStack.peek().precedence()) {
this.outOperator(this.opStack.pop());
}
this.opStack.push(t);
}
else if (t.type === "Left Parenthesis") {
this.opStack.push(t);
}
else if (t.type === "Right Parenthesis") {
while (!this.opStack.isEmpty() && this.opStack.peek().type !== "Left Parenthesis")
this.outOperator(this.opStack.pop());
this.opStack.pop();
if (!this.opStack.isEmpty() && this.opStack.peek().type === "Function")
this.outFunction(this.opStack.pop());
}
});
while (!this.opStack.isEmpty())
this.outOperator(this.opStack.pop());
return this.outStack.pop();
}
}
//# sourceMappingURL=parser.js.map