start implementing expression balancer
This commit is contained in:
88
src/main/java/parser/ast/ExpressionBalancer.java
Normal file
88
src/main/java/parser/ast/ExpressionBalancer.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package parser.ast;
|
||||||
|
|
||||||
|
public final class ExpressionBalancer {
|
||||||
|
|
||||||
|
private ExpressionBalancer() {}
|
||||||
|
|
||||||
|
// Spiegelt den Baum, da meine Müll-Grammatik die EXPRs rückwärts parst
|
||||||
|
public static void flip(AST tree) {
|
||||||
|
flip(tree.getRoot());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void flip(Node root) {
|
||||||
|
for (Node child : root.getChildren()) {
|
||||||
|
flip(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.getChildren().size() == 2) {
|
||||||
|
Node left = root.getChildren().get(0);
|
||||||
|
Node right = root.getChildren().get(1);
|
||||||
|
|
||||||
|
root.setChildren(right, left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Führt Linksrotationen durch
|
||||||
|
// Es werden EXPR-Nodes (2 Childs, 1 davon EXPR, Kein Wert) solange wie möglich linksrotiert
|
||||||
|
public static void leftPrecedence(AST tree) {
|
||||||
|
boolean change;
|
||||||
|
|
||||||
|
do {
|
||||||
|
change = leftPrecedence(tree.getRoot());
|
||||||
|
} while (change);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean leftPrecedence(Node root) {
|
||||||
|
for (Node child : root.getChildren()) {
|
||||||
|
leftPrecedence(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node expr = getExpr(root);
|
||||||
|
|
||||||
|
if (expr == null || root.getChildren().size() != 2 || !root.getValue().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leftRotate(root);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void leftRotate(Node root) {
|
||||||
|
Node left = root.getChildren().get(0);
|
||||||
|
Node right = root.getChildren().get(1);
|
||||||
|
|
||||||
|
// Verhindert Wurzel mit nur einem EXPR-Child
|
||||||
|
if (endOfExpr(right)) {
|
||||||
|
root.setName(right.getName());
|
||||||
|
root.setValue(right.getValue());
|
||||||
|
root.setChildren(left, right.getChildren().get(0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node insertLeft = new Node(root.getName());
|
||||||
|
insertLeft.setValue(right.getValue());
|
||||||
|
insertLeft.setChildren(left, right.getChildren().get(0));
|
||||||
|
|
||||||
|
root.setName(right.getName());
|
||||||
|
root.setChildren(insertLeft, right.getChildren().get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Node getExpr(Node root) {
|
||||||
|
for (Node child : root.getChildren()) {
|
||||||
|
if (child.getName().equals("EXPR")) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean endOfExpr(Node root) {
|
||||||
|
return root.getChildren().size() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void operatorPrecedence(AST tree) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/test/java/parser/ast/ExpressionBalancerTest.java
Normal file
106
src/test/java/parser/ast/ExpressionBalancerTest.java
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package parser.ast;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class ExpressionBalancerTest {
|
||||||
|
|
||||||
|
//EXPR
|
||||||
|
//├── EXPR: SUB
|
||||||
|
//| └── INTEGER_LIT: 2
|
||||||
|
//└── INTEGER_LIT: 1
|
||||||
|
private static AST tree1() {
|
||||||
|
AST tree = new AST(new Node("EXPR"));
|
||||||
|
|
||||||
|
Node right = new Node("INTEGER_LIT");
|
||||||
|
right.setValue("1");
|
||||||
|
|
||||||
|
Node left = new Node("EXPR");
|
||||||
|
left.setValue("SUB");
|
||||||
|
|
||||||
|
Node lleft = new Node("INTEGER_LIT");
|
||||||
|
lleft.setValue("2");
|
||||||
|
left.setChildren(lleft);
|
||||||
|
|
||||||
|
tree.getRoot().setChildren(left, right);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AST tree2() {
|
||||||
|
AST tree = new AST(new Node("EXPR"));
|
||||||
|
|
||||||
|
Node right = new Node("INTEGER_LIT");
|
||||||
|
right.setValue("1");
|
||||||
|
|
||||||
|
Node left = new Node("EXPR");
|
||||||
|
left.setValue("SUB");
|
||||||
|
|
||||||
|
Node lleft = new Node("EXPR");
|
||||||
|
lleft.setValue("SUB");
|
||||||
|
|
||||||
|
Node lright = new Node("INTEGER_LIT");
|
||||||
|
lright.setValue("2");
|
||||||
|
|
||||||
|
Node llleft = new Node("INTEGER_LIT");
|
||||||
|
llleft.setValue("3");
|
||||||
|
|
||||||
|
lleft.setChildren(llleft);
|
||||||
|
left.setChildren(lleft, lright);
|
||||||
|
|
||||||
|
tree.getRoot().setChildren(left, right);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTree1Flip() {
|
||||||
|
AST tree = tree1();
|
||||||
|
System.out.println("Before:\n" + tree);
|
||||||
|
|
||||||
|
ExpressionBalancer.flip(tree);
|
||||||
|
System.out.println("After:\n" + tree);
|
||||||
|
|
||||||
|
assertThat(tree.getRoot().getChildren().get(0).getName()).isEqualTo("INTEGER_LIT");
|
||||||
|
assertThat(tree.getRoot().getChildren().get(1).getName()).isEqualTo("EXPR");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTree2Flip() {
|
||||||
|
AST tree = tree2();
|
||||||
|
System.out.println("Before:\n" + tree);
|
||||||
|
|
||||||
|
ExpressionBalancer.flip(tree);
|
||||||
|
System.out.println("After:\n" + tree);
|
||||||
|
|
||||||
|
assertThat(tree.getRoot().getChildren().get(0).getName()).isEqualTo("INTEGER_LIT");
|
||||||
|
assertThat(tree.getRoot().getChildren().get(1).getName()).isEqualTo("EXPR");
|
||||||
|
assertThat(tree.getRoot().getChildren().get(1).getChildren().get(0).getName()).isEqualTo("INTEGER_LIT");
|
||||||
|
assertThat(tree.getRoot().getChildren().get(1).getChildren().get(1).getName()).isEqualTo("EXPR");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTree1Rotate() {
|
||||||
|
AST tree = tree1();
|
||||||
|
ExpressionBalancer.flip(tree);
|
||||||
|
System.out.println("Before:\n" + tree);
|
||||||
|
|
||||||
|
ExpressionBalancer.leftPrecedence(tree);
|
||||||
|
System.out.println("After:\n" + tree);
|
||||||
|
|
||||||
|
assertThat(tree.size()).isEqualTo(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTree2Rotate() {
|
||||||
|
AST tree = tree2();
|
||||||
|
ExpressionBalancer.flip(tree);
|
||||||
|
System.out.println("Before:\n" + tree);
|
||||||
|
|
||||||
|
ExpressionBalancer.leftPrecedence(tree);
|
||||||
|
System.out.println("After:\n" + tree);
|
||||||
|
|
||||||
|
assertThat(tree.size()).isEqualTo(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user