const selfClosingTags = require("./util/selfClosingTags"); module.exports = class Compiler { constructor(tree, context) { this.tree = tree; this.context = context; this.pos = 0; this.result = ""; } compile() { this.tree.forEach(node => { switch (node.constructor.name) { case "Application": this.result += this.application(node); break; case "Identifier": this.result += this.lookup(node); break; case "String": this.result += node.value; break; } }); return this.result; } application(node) { let result = `<${node.functionName.name}`; node.args .filter(arg => arg.constructor.name === "Attribute") .forEach(arg => { result += ` ${arg.name}`; let compiler = new Compiler([arg.value], this.context); let attrValue = compiler.compile(); if (attrValue) { result += `="${attrValue}"`; } }); result += ">"; node.args .filter(arg => arg.constructor.name !== "Attribute") .forEach(arg => { let compiler = new Compiler([arg], this.context); result += compiler.compile(); }); if (!selfClosingTags.includes(node.functionName.name)) { result += ``; } return result; } lookup(identifier) { let result = this.context[identifier.name]; if (!result) { throw `Undefined variable '${identifier.name}'`; } return result; } };