I am writing a program that simulates the 6 compiler phases using java. Currently, stuck in the printing of the parse tree in the 2nd phase, syntax Analyzer. I already know what my problem is after some debugging. The parent and children nodes are correct but is visually displayed in wrong depths.
Input: z=y*y+x*3
When it gets to the * symbol which has children, it displays its children first before displaying the its sibling node which is also another *, because of the recursion.
public static void displayParseTree(ParseTreeNode node, int depth) {
if (node != null) {
StringBuilder indent = new StringBuilder();
for (int i = 0; i < depth; i++) {
indent.append(" ");
}
//if node has children print / -> child1 \ -> child2
System.out.print(indent.toString() + node.token.getValue());
// Check if the node has any children.
if (!node.children.isEmpty()) {
System.out.println("");
System.out.print("/ ");
System.out.println(" \\");
// Print the left child node.
displayParseTree(node.children.get(0), depth + 1);
// Print the right child node.
displayParseTree(node.children.get(1), depth + 1);
System.out.println("");
}
}
}
Incase img doesn't open, this is the my current ouput:
Please enter the source code:
z=y*y+x*3
Source Form: z=y*y+x*3
Math Form: z=yxy+xx3
Lexical Analyzer: id1=id2*id2+id3*3
Syntax analysis completed. The input is valid.
=
/ \
id1 +
/ \
*
/ \
id2 id2
*
/ \
id3 3
I want my output to look more like this:
=
/ \
id1 +
/ \
* *
/ \ / \
id2 id2 id3 3
EDIT: I somewhat hardcoded it(not proud of it), but I'll leave it at that till I find a better way
public static void displayParseTree(ParseTreeNode node, int depth) {
if (node != null) {
StringBuilder indent = new StringBuilder();
for (int i = 0; i < depth; i++) {
indent.append(" ");
}
//if node has children print / -> child1 \ -> child2
if (node.token.getValue().equals("=")){
System.out.println(" " + indent.toString() + node.token.getValue());
}
// Check if the node has any children.
if (!node.children.isEmpty()) {
if (node.children.get(0).token.getValue().equals("*") && node.children.get(1).token.getValue().equals("*")) {
System.out.print("/ ");
System.out.println(" \\");
for (int i = 0; i < 2; i++) {
System.out.print(node.children.get(i).token.getValue() + " ");
}
System.out.println("");
System.out.print("/ ");
System.out.print(" \\ ");
System.out.print(" / ");
System.out.println(" \\");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++)
System.out.print(node.children.get(i).children.get(j).token.getValue() + " ");
}
System.out.println("");
}
else {
// Print the left child node.
System.out.print("/ ");
System.out.println(" \\");
for (int i = 0; i < 2; i++) {
System.out.print(node.children.get(i).token.getValue() + " ");
}
System.out.println("");
displayParseTree(node.children.get(0), depth + 1);
// Print the right child node.
displayParseTree(node.children.get(1), depth + 1);
}
}
}
}
Current Output:
=
/ \
id1 +
/ \
* *
/ \ / \
id2 id2 id3 3
I figured it out. Though I think there could've been a better solution, but this is what I managed to come up with. Since, only the multiply and divide operators can come at the same depth so I just made a condition specifically for them. First check that both ops are * or /, if yes print the / \ branches and then print the ops, then print branches for all their children which is 4 so / \ / \ then using a nested loop print both of their children on the same line, else do everything normally. That's it. After that it was just a matter of adjusting the spaces to get the output I was looking for.
public static void displayParseTree(ParseTreeNode node, int depth) {
if (node != null) {
StringBuilder indent = new StringBuilder();
for (int i = 0; i < depth; i++) {
indent.append(" ");
}
//if node has children print / -> child1 \ -> child2
if (node.token.getValue().equals("=")){
System.out.println(" " + indent.toString() + node.token.getValue());
}
// Check if the node has any children.
if (!node.children.isEmpty()) {
if (node.children.get(0).token.getValue().equals("*") && node.children.get(1).token.getValue().equals("*") ||
node.children.get(0).token.getValue().equals("/") && node.children.get(1).token.getValue().equals("/")) {
System.out.print(" / ");
System.out.println(" \\");
for (int i = 0; i < 2; i++) {
System.out.print(" "+ node.children.get(i).token.getValue() + " ");
}
System.out.println("");
System.out.print(" / ");
System.out.print(" \\ ");
System.out.print(" / ");
System.out.println(" \\");
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++)
System.out.print(" "+ node.children.get(i).children.get(j).token.getValue() + " ");
}
System.out.println("");
}
else {
// Print the left child node.
System.out.print(" / ");
System.out.println(" \\");
for (int i = 0; i < 2; i++) {
System.out.print(" " + node.children.get(i).token.getValue() + " ");
}
System.out.println("");
displayParseTree(node.children.get(0), depth + 1);
// Print the right child node.
displayParseTree(node.children.get(1), depth + 1);
}
}
}
}
Please enter the source code:
z=y*y+x*3
Source Form: z=y*y+x*3
Math Form: z=yxy+xx3
Lexical Analyzer: id1=id2*id2+id3*3
Syntax analysis completed. The input is valid.
=
/ \
id1 +
/ \
* *
/ \ / \
id2 id2 id3 3