start implementing expression balancer

This commit is contained in:
ChUrl
2020-12-12 16:04:49 +01:00
parent 8bdcd0f7d7
commit 16315e288a
2 changed files with 194 additions and 0 deletions

View 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) {
}
}

View 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);
}
}