Skip to content

Instantly share code, notes, and snippets.

@KKostya
Last active August 29, 2015 14:11
Show Gist options
  • Save KKostya/d028292cd32a0385a29d to your computer and use it in GitHub Desktop.
Save KKostya/d028292cd32a0385a29d to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node circle { fill: #fff; stroke: steelblue; stroke-width: 1.5px; }
.link { fill: none; stroke: #ccc; stroke-width: 1.5px; }
</style>
<body>
<input id="toparse" type='text' style="width:500px" value="42 * (111+10) / (7+4)"/>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var width = 960, height = 500;
var tree = d3.layout.tree()
.size([height, width - 160]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(40,0)");
function drawTree(str){
var ast = parse(str);
var nodes = tree.nodes(ast),
links = tree.links(nodes);
var link = svg.selectAll("path.link").data(links);
link.exit().remove();
link.enter().append("path").attr("class", "link")
link.attr("d", diagonal);
var node = svg.selectAll("g.node").data(nodes);
node.exit().remove();
var nenter = node.enter().append("g").attr("class", "node");
nenter.append("circle").attr("r", 4.5);
nenter.append("text").attr("dy", 3);
node.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
node.select("text")
.attr("dx", function(d) { return d.children ? 0 : 8; })
.attr("dy", function(d) { return d.children ? -12: 0; })
.attr("text-anchor", function(d) { return d.children ? "middle" : "start"; })
.text(function(d) { return d.name; });
}
d3.select("#toparse").on("keyup", function(){drawTree(this.value);});
pre = d3.map();
pre["+"] = 1;
pre["-"] = 1;
pre["*"] = 2;
pre["/"] = 2;
function parse(str){
var opstack = [];
var astack = [];
var lexnode = null;
astack.opop = function() { return this.length >0 ? this.pop() : {name:"???"}; }
astack.opush = function() {
var rhs = astack.opop();
var lhs = astack.opop();
this.push({name:opstack.pop(), children:[lhs,rhs]})
}
str.split("").forEach(function(ch){
if(/[0-9]/.test(ch)) {
if(lexnode != null) lexnode.name += ch;
else {
lexnode = { name:ch };
astack.push(lexnode);
}
} else lexnode = null;
if(pre[ch]) {
while(pre[ch] <= pre[opstack[opstack.length-1]]) astack.opush();
opstack.push(ch);
}
if(ch == ")") {
while(opstack[opstack.length-1] != "(") astack.opush();
opstack.pop();
}
if(ch == "(") opstack.push(ch);
});
while(opstack.length > 0) astack.opush();
return astack[0];
}
drawTree(document.getElementById("toparse").value);
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment