Skip to content

Commit 1939f50

Browse files
committed
feat: EliminateEmptyAlternatives transformer
1 parent fd0d96e commit 1939f50

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
2+
package org.variantsync.diffdetective.variation.diff.transform;
3+
4+
import org.prop4j.Node;
5+
import org.variantsync.diffdetective.variation.Label;
6+
import org.variantsync.diffdetective.variation.tree.VariationTree;
7+
import org.variantsync.diffdetective.variation.tree.VariationTreeNode;
8+
9+
import java.util.List;
10+
11+
import static org.variantsync.diffdetective.util.fide.FormulaUtils.*;
12+
13+
/**
14+
* This transformer simplifies annotations such that empty alternatives do not appear in choices.
15+
* This means, that nestings without any siblings such as
16+
*
17+
* <pre>
18+
* #if A
19+
* #elif B
20+
* #elif C
21+
* #else
22+
* foo
23+
* #endif
24+
* </pre>
25+
*
26+
* will be simplified to
27+
*
28+
* <pre>
29+
* #if !A && !B && !C
30+
* foo
31+
* #endif
32+
* </pre>
33+
*
34+
* Annotations without any children also get eliminated.
35+
*
36+
* @author Paul Bittner
37+
*/
38+
public class EliminateEmptyAlternatives<L extends Label> implements VariationTreeTransformer<L> {
39+
private void elim(VariationTreeNode<L> subtree) {
40+
// We simplify only annotations.
41+
if (!subtree.isAnnotation()) return;
42+
43+
final List<VariationTreeNode<L>> children = subtree.getChildren();
44+
45+
// When there are no children, 'subtree' is an empty annotation that can be eliminated.
46+
if (children.isEmpty()) {
47+
subtree.drop();
48+
}
49+
// When there is exactly one child and that child is an 'else' or 'elif' we can simplify that nesting.
50+
else if (children.size() == 1) {
51+
final VariationTreeNode<L> child = children.getFirst();
52+
53+
if ((subtree.isIf() || subtree.isElif()) && (child.isElif() || child.isElse())) {
54+
// determine new feaure mapping
55+
Node newFormula = negate(subtree.getFormula());
56+
if (child.isElif()) {
57+
newFormula = and(newFormula, child.getFormula());
58+
}
59+
subtree.setFormula(newFormula);
60+
61+
// simplify tree
62+
child.drop();
63+
subtree.stealChildrenOf(child);
64+
}
65+
}
66+
}
67+
68+
@Override
69+
public void transform(VariationTree<L> tree) {
70+
tree.forAllPostorder(this::elim);
71+
}
72+
}

0 commit comments

Comments
 (0)