How to print a proper parse tree in console using Java?

105 Views Asked by At

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("");
            }
        }
    }

Output

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
1

There are 1 best solutions below

1
On BEST ANSWER

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