fix operator-precedence
This commit is contained in:
@ -1,13 +1,47 @@
|
|||||||
package parser.ast;
|
package parser.ast;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static util.Logger.log;
|
import static util.Logger.log;
|
||||||
|
|
||||||
public final class ASTBalancer {
|
public final class ASTBalancer {
|
||||||
|
|
||||||
|
private static final Map<String, Integer> 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() {}
|
private ASTBalancer() {}
|
||||||
|
|
||||||
public static void balance(AST tree) {
|
public static void balance(AST tree) {
|
||||||
@ -84,7 +118,7 @@ public final class ASTBalancer {
|
|||||||
|
|
||||||
private static ASTNode getExpr(ASTNode root) {
|
private static ASTNode getExpr(ASTNode root) {
|
||||||
for (ASTNode child : root.getChildren()) {
|
for (ASTNode child : root.getChildren()) {
|
||||||
if (child.getName().equals("EXPR")) {
|
if ("EXPR".equals(child.getName())) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,48 +130,47 @@ public final class ASTBalancer {
|
|||||||
return root.getChildren().size() == 1;
|
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) {
|
public static void operatorPrecedence(AST tree) {
|
||||||
log("Right-rotating expressions for operator-precedence");
|
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()) {
|
for (ASTNode child : root.getChildren()) {
|
||||||
operatorPrecedence(child);
|
changed = changed || operatorPrecedence(child);
|
||||||
|
|
||||||
|
if (preceding(root, child)) {
|
||||||
|
simpleRightRotate(root);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preceding(root)) {
|
return changed;
|
||||||
simpleRightRotate(root);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean preceding(ASTNode root) {
|
private static boolean preceding(ASTNode parent, ASTNode child) {
|
||||||
ASTNode op = getExpr(root);
|
if (!"EXPR".equals(parent.getName()) || parent.getValue().isEmpty()
|
||||||
|
|| !"EXPR".equals(child.getName()) || child.getValue().isEmpty()) {
|
||||||
if (op == null || !root.getName().equals("EXPR") || root.getValue().isEmpty()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<String> arithHigh = Arrays.asList("MUL", "DIV", "MOD");
|
// Less equals higher
|
||||||
Collection<String> arithLow = Arrays.asList("ADD", "SUB");
|
return priority.get(parent.getValue()) < priority.get(child.getValue());
|
||||||
Collection<String> logHigh = Arrays.asList("AND");
|
|
||||||
Collection<String> logLow = Arrays.asList("OR");
|
|
||||||
|
|
||||||
return (arithHigh.contains(root.getValue()) && arithLow.contains(op.getValue()))
|
|
||||||
|| (logHigh.contains(root.getValue()) && logLow.contains(op.getValue()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void simpleRightRotate(ASTNode root) {
|
private static void simpleRightRotate(ASTNode root) {
|
||||||
ASTNode left = root.getChildren().get(0);
|
ASTNode left = root.getChildren().get(0);
|
||||||
ASTNode right = root.getChildren().get(1);
|
ASTNode right = root.getChildren().get(1);
|
||||||
|
|
||||||
|
log("Right-Rotating " + root.getName() + ": " + root.getValue());
|
||||||
|
|
||||||
ASTNode insertRight = new ASTNode(root.getName());
|
ASTNode insertRight = new ASTNode(root.getName());
|
||||||
insertRight.setValue(root.getValue());
|
insertRight.setValue(root.getValue());
|
||||||
insertRight.setChildren(left.getChildren().get(1), right);
|
insertRight.setChildren(left.getChildren().get(1), right);
|
||||||
|
|||||||
Reference in New Issue
Block a user