diff --git a/src/main/java/parser/ast/ASTBalancer.java b/src/main/java/parser/ast/ASTBalancer.java index dd0de7d..44bf132 100644 --- a/src/main/java/parser/ast/ASTBalancer.java +++ b/src/main/java/parser/ast/ASTBalancer.java @@ -1,13 +1,47 @@ package parser.ast; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import static util.Logger.log; public final class ASTBalancer { + private static final Map priority; + + // 0 - Unary: -, +, ! + // 1 - Multiplicative: *, /, % + // 2 - Additive: +, - + // 3 - Comparative: <, <=, >, >= + // 4 - Equality: ==, != + // 5 - Logical AND: && + // 6 - Logical OR: || + static { + priority = new HashMap<>(); + + priority.put("NOT", 0); + + priority.put("MUL", 1); + priority.put("DIV", 1); + priority.put("MOD", 1); + + priority.put("ADD", 2); + priority.put("SUB", 2); + + priority.put("LESS", 3); + priority.put("LESS_EQUAL", 3); + priority.put("GREATER", 3); + priority.put("GREATER_EQUAL", 3); + + priority.put("EQUAL", 4); + priority.put("NOT_EQUAL", 4); + + priority.put("AND", 5); + + priority.put("OR", 6); + } + private ASTBalancer() {} public static void balance(AST tree) { @@ -84,7 +118,7 @@ public final class ASTBalancer { private static ASTNode getExpr(ASTNode root) { for (ASTNode child : root.getChildren()) { - if (child.getName().equals("EXPR")) { + if ("EXPR".equals(child.getName())) { return child; } } @@ -96,48 +130,47 @@ public final class ASTBalancer { return root.getChildren().size() == 1; } - // 0 - Unary: -, +, ! - // 1 - Multiplicative: *, /, % - // 2 - Additive: +, - - // 3 - Comparative: <, <=, >, >= - // 4 - Equality: ==, != - // 5 - Logical AND: && - // 6 - Logical OR: || public static void operatorPrecedence(AST tree) { log("Right-rotating expressions for operator-precedence"); - operatorPrecedence(tree.getRoot()); + + boolean changed; + + do { + changed = operatorPrecedence(tree.getRoot()); + } while (changed); } - public static void operatorPrecedence(ASTNode root) { + public static boolean operatorPrecedence(ASTNode root) { + boolean changed = false; + for (ASTNode child : root.getChildren()) { - operatorPrecedence(child); + changed = changed || operatorPrecedence(child); + + if (preceding(root, child)) { + simpleRightRotate(root); + changed = true; + } } - if (preceding(root)) { - simpleRightRotate(root); - } + return changed; } - private static boolean preceding(ASTNode root) { - ASTNode op = getExpr(root); - - if (op == null || !root.getName().equals("EXPR") || root.getValue().isEmpty()) { + private static boolean preceding(ASTNode parent, ASTNode child) { + if (!"EXPR".equals(parent.getName()) || parent.getValue().isEmpty() + || !"EXPR".equals(child.getName()) || child.getValue().isEmpty()) { return false; } - Collection arithHigh = Arrays.asList("MUL", "DIV", "MOD"); - Collection arithLow = Arrays.asList("ADD", "SUB"); - Collection logHigh = Arrays.asList("AND"); - Collection logLow = Arrays.asList("OR"); - - return (arithHigh.contains(root.getValue()) && arithLow.contains(op.getValue())) - || (logHigh.contains(root.getValue()) && logLow.contains(op.getValue())); + // Less equals higher + return priority.get(parent.getValue()) < priority.get(child.getValue()); } private static void simpleRightRotate(ASTNode root) { ASTNode left = root.getChildren().get(0); ASTNode right = root.getChildren().get(1); + log("Right-Rotating " + root.getName() + ": " + root.getValue()); + ASTNode insertRight = new ASTNode(root.getName()); insertRight.setValue(root.getValue()); insertRight.setChildren(left.getChildren().get(1), right);