optimized alternative collapsing

only collapse alternative if the result is smaller than the uncollapsed
version
This commit is contained in:
overflowerror 2022-02-06 22:15:05 +01:00
parent 4a9667ec4e
commit 8970ef67d4
3 changed files with 53 additions and 3 deletions

View file

@ -802,7 +802,25 @@ public class HoistingProcessorTest extends AbstractXtextTests {
assertFalse(guard.isTrivial()); assertFalse(guard.isTrivial());
assertTrue(guard.hasTerminal()); assertTrue(guard.hasTerminal());
assertEquals("(" + keyword("a", 2) + " || " + keyword("b", 1) + " || ((p0) && (p2))) && (" + keyword("b", 2) + " || " + keyword("b", 1) + " || ((p0) && (p3))) && (" + keyword("a", 1) + " || (p1))", guard.render()); // collapsed version is actually not optimal
//assertEquals("(" + keyword("a", 2) + " || " + keyword("b", 1) + " || ((p0) && (p2))) && (" + keyword("b", 2) + " || " + keyword("b", 1) + " || ((p0) && (p3))) && (" + keyword("a", 1) + " || (p1))", guard.render());
assertEquals(
"(" +
keyword("b", 1) + " || " +
"(" +
"(p0) && (" +
keyword("a", 2) + " || " +
"(p2)" +
") && (" +
keyword("b", 2) + " || " +
"(p3)" +
")" +
")" +
") && (" +
keyword("a", 1) + " || " +
"(p1)" +
")",
guard.render());
} }
// currently not able to find optimal solution // currently not able to find optimal solution
@ -833,7 +851,27 @@ public class HoistingProcessorTest extends AbstractXtextTests {
//assertEquals("(" + keyword("a", 1) + " || (" + keyword("c", 3) + " && " + eof(3) + ") || ((p0) && (p2))) && (" + keyword("c", 1) + " || ((p0) && (p3))) && (" + keyword("d", 3) + " || (p1))", guard.render()); //assertEquals("(" + keyword("a", 1) + " || (" + keyword("c", 3) + " && " + eof(3) + ") || ((p0) && (p2))) && (" + keyword("c", 1) + " || ((p0) && (p3))) && (" + keyword("d", 3) + " || (p1))", guard.render());
// still valid but non-optimal // still valid but non-optimal
assertEquals("(" + keyword("a", 1) + " || (" + keyword("a", 3)+ " && " + keyword("b", 3) + " && " + keyword("c", 3) + " && " + eof(3) + ") || ((p0) && (p2))) && (" + keyword("b", 1) + " || (" + keyword("a", 3)+ " && " + keyword("b", 3) + " && " + keyword("c", 3) + " && " + eof(3) + ") || ((p0) && (p3))) && (" + keyword("d", 3) + " || (p1))", guard.render()); assertEquals(
"(" +
"(" +
keyword("a", 3) + " && " +
keyword("b", 3) + " && " +
keyword("c", 3) + " && " +
eof(3) +
") || (" +
"(p0) && (" +
keyword("a", 1) + " || " +
"(p2)" +
") && (" +
keyword("b", 1) + " || " +
"(p3)" +
")" +
")" +
") && (" +
keyword("d", 3) + " || " +
"(p1)" +
")",
guard.render());
} }
@Test @Test

View file

@ -31,9 +31,19 @@ public class AlternativesGuard implements HoistingGuard {
} }
public AlternativesGuard(List<PathGuard> paths) { public AlternativesGuard(List<PathGuard> paths) {
// collapsing nested alternatives might reduce output size
// -> try both and use smaller one
this.paths = paths;
int lengthWithoutCollapse = render().length();
this.paths = PathGuard.collapse(paths); this.paths = PathGuard.collapse(paths);
int lengthWithCollapse = render().length();
if (lengthWithoutCollapse < lengthWithCollapse)
this.paths = paths;
} }
// package private so PathGuard can access this method // package private so PathGuard can access this method
List<PathGuard> getPaths() { List<PathGuard> getPaths() {
return paths; return paths;

View file

@ -28,8 +28,10 @@ public class TokenSequenceGuard implements TokenGuard {
public TokenSequenceGuard(Collection<? extends TokenGuard> sequence) { public TokenSequenceGuard(Collection<? extends TokenGuard> sequence) {
Set<Integer> checkedPositions = new HashSet<>(); Set<Integer> checkedPositions = new HashSet<>();
// remove all guards from sequences who's positions are already in the sequence
this.sequence = sequence.stream() this.sequence = sequence.stream()
.flatMap(g -> { .flatMap(g -> {
// special case: reduce TokenSequenceGuards
if (g instanceof TokenSequenceGuard) { if (g instanceof TokenSequenceGuard) {
return ((TokenSequenceGuard) g).sequence.stream() return ((TokenSequenceGuard) g).sequence.stream()
.filter(s -> !s.getPositions().stream() .filter(s -> !s.getPositions().stream()
@ -65,7 +67,7 @@ public class TokenSequenceGuard implements TokenGuard {
@Override @Override
public String render() { public String render() {
if (sequence.size() == 1) { if (sequence.size() == 1) {
return sequence.stream().findAny().get().render(); return sequence.stream().findAny().get().render();
} else { } else {
return render(ContextConnective.DISJUNCTION); return render(ContextConnective.DISJUNCTION);
} }