In this recitation we will describe how to generate DOT visualizations of ASTs and show a possible organization for symbol tables.
DOT is a declarative language for specifying diagrams. These diagrams consists of a series of nodes connected to one another with edges. Each node and edge is specified in a statement; statements are seperated from one another with semi-colons.
It's probably easiest to learn DOT by example, so consider the following simple diagram:
Here is its specification in DOT:
1 digraph { 2 0 [label="Apple"]; 3 1 [label="Orange"]; 4 2 [label="Banana"]; 5 6 0 -> 1; 7 0 -> 2; 8 2 -> 1; 9 }
Note that each node (specified on lines 2 through 4) has an identifier (1,
2, or 3) and a label (apple, orange, banana). Lines 6 through 8 specify how
the nodes connect; the arrow ->
specifies the direction of the
edge.
For visualizing symbol tables you'll want the nodes to be records that contain fields. The following diagram shows an example of this:
digraph { graph [rankdir="LR"]; node [shape=record]; 0 [label=" <f1> Field A | <f2> Field 2 | <f3> Field 3"]; 1 [label=" <f1> Orange | <f2> Apple | <f3> Banana"]; 2 [label=" <f1> Red | <f2> Orange | <f3> Yellow "]; 0:<f2> -> 1:<f1>; 1:<f1> -> 2:<f2>; 1:<f2> -> 2:<f1>; 1:<f3> -> 2:<f3>; }
Note that we seperate fields in a record with pipes |, and label fields with an
angle bracketed identifier (for example <f1>
).
You can read more about DOT on its documentation page.
digraph SymTable { graph [rankdir="LR"]; node [shape=record]; 0 [label=" <f0> Scope | <f1> mDict\[A\] | <f2> mDict\[B\] "]; 0:<f1> -> 1:<f0>; 1 [label=" <f0> ClassSTE | <f1> mName = A| <f2> mMain = false| <f3> mSuperClass = null| <f4> mScope "]; 1:<f4> -> 2:<f0>; 2 [label=" <f0> Scope "]; 0:<f2> -> 3:<f0>; 3 [label=" <f0> ClassSTE | <f1> mName = B| <f2> mMain = false| <f3> mSuperClass = null| <f4> mScope "]; 3:<f4> -> 4:<f0>; 4 [label=" <f0> Scope | <f1> mDict\[foo\] "]; 4:<f1> -> 5:<f0>; 5 [label=" <f0> MethodSTE | <f1> mName = foo| <f2> mSignature = (INT, class_float;, COLOR, TONE, class_A;, class_B;) returns class_null;| <f3> mScope "]; 5:<f3> -> 6:<f0>; 6 [label=" <f0> Scope | <f1> mDict\[this\] | <f2> mDict\[i\] | <f3> mDict\[f\] | <f4> mDict\[c\] | <f5> mDict\[t\] | <f6> mDict\[a\] | <f7> mDict\[b\] "]; 6:<f1> -> 7:<f0>; 7 [label=" <f0> VarSTE | <f1> mName = this| <f2> mType = class_B;| <f3> mBase = INVALID| <f4> mOffset = 0"]; 6:<f2> -> 8:<f0>; 8 [label=" <f0> VarSTE | <f1> mName = i| <f2> mType = INT| <f3> mBase = INVALID| <f4> mOffset = 0"]; 6:<f3> -> 9:<f0>; 9 [label=" <f0> VarSTE | <f1> mName = f| <f2> mType = class_float;| <f3> mBase = INVALID| <f4> mOffset = 0"]; 6:<f4> -> 10:<f0>; 10 [label=" <f0> VarSTE | <f1> mName = c| <f2> mType = COLOR| <f3> mBase = INVALID| <f4> mOffset = 0"]; 6:<f5> -> 11:<f0>; 11 [label=" <f0> VarSTE | <f1> mName = t| <f2> mType = TONE| <f3> mBase = INVALID| <f4> mOffset = 0"]; 6:<f6> -> 12:<f0>; 12 [label=" <f0> VarSTE | <f1> mName = a| <f2> mType = class_A;| <f3> mBase = INVALID| <f4> mOffset = 0"]; 6:<f7> -> 13:<f0>; 13 [label=" <f0> VarSTE | <f1> mName = b| <f2> mType = class_B;| <f3> mBase = INVALID| <f4> mOffset = 0"]; }
dot -Tpng input.dot > output.png