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());
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
@ -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());
// 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

View file

@ -31,9 +31,19 @@ public class AlternativesGuard implements HoistingGuard {
}
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);
int lengthWithCollapse = render().length();
if (lengthWithoutCollapse < lengthWithCollapse)
this.paths = paths;
}
// package private so PathGuard can access this method
List<PathGuard> getPaths() {
return paths;

View file

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