AST Visualizer
After completing my tokenizer and parser with a few fixes, I wanted to move straight onto building the actual domain and range logic and setting up all the constraints, but instead, I had another idea. Whenever I saw the output of my parser, it just seemed a bit meh. The output was just a nested tuple and it was not looking like what I had built was a tree. So, as a side quest, I built an SVG AST visualizer that takes the tuple and build its tree and it is SVG and not matplotlib so that if I ever decide to turn this program into a website, I can simply plug in this code and get the output straight in a web page.
How it works:
For the people curious as to how it works, I am sorry if my explanation does not make sense because even I do not understand it very well (I am pretty bad at recursion).
basically, the main function that lets me plot these nodes in a 2D space is assign_positions. If we do not focus on recursion yet, the basic idea of this function is that there are 2 types of node: leaf nodes and internal nodes. Leaf nodes are the nodes which do not have any children and terminate the branch i.e. are terminal. whereas, internal nodes have children and branch out further to extend the tree i.e. are non-terminal. The basic hypothesis was that if there are two leaf nodes, and I assign them an x-position of 0 and 1, their parent node should be at a position which is the mid point (or average) of its children. Which means, the parent node of two leaf nodes (or internal nodes) at x-position 0 and 1 would lie at x-position 0.5 (avg of 0 and 1). now for the y-position, I have used depth as the name where the idea was simply that with every new node, the depth should increase by 1.
Now we come to recursion and how I generalized this position idea to any possible tuple. The basic things that the assign_positions function takes are:
node-> Current node
depth-> Current depth/ y-position
id_count-> The ID assigned to the node
leaf_count-> Basically the x-position of the leaves
tree-> Current tree dictionary
There are 2 cases, the node can either be a leaf or an internal node. If the node is a leaf node, then we simple make the tree: tree[str_id] = {'label': node, 'x': str_x, 'depth': depth}. we increase leaf_count by 1 (because if the x-position assigned to this node was 0 then the next leaf node should have it as 1) and we increase id_count by 1. This case returns the x-position assigned to this node-> str_x, the id assigned to this node-> str_id, the current id_count, the current leaf_count and the current tree. These specific constraints are returned because If a parent had done a recursive call and the node was a leaf node then the parent would require:
- the child’s x position to average left and right positions to set its own position.
- the child’s id to keep track of it in its own dictionary.
- the current id_count and leaf_count so that an assigned number is not reassigned to another node by mistake in a recursive call.
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.