Skip to content

Commit

Permalink
implemented literal-only alternatives optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
elucash committed Nov 27, 2017
1 parent 7549dc0 commit 01bf3fc
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 12 deletions.
42 changes: 33 additions & 9 deletions src/io/immutables/grammar/Productions.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public final Traversal traverse() {

/**
* Pull-style traversal over productions.
* Mechanic is to be revised
*/
public static final class Traversal {
public enum At {
Expand Down Expand Up @@ -142,9 +143,9 @@ public At next() {
return current = At.EOP;
}

long l1 = elements[position];
int nextSibling = position + decodeLength(l1);
boolean isTerm = decodeKind(l1) >= 0;
long l0 = elements[position];
int nextSibling = position + decodeLength(l0);
boolean isTerm = decodeKind(l0) >= 0;

int nextPosition = position + POSITION_INCREMENT;
// If we're ending on the next position,
Expand Down Expand Up @@ -175,6 +176,24 @@ public At next() {
return current = At.PRODUCTION_BEGIN;
}

public void skip() {
checkBegin();
checkEnd();
if (current != At.TERM) {
int length = decodeLength(elements[position]);
// if it is a position increment
if (length != POSITION_INCREMENT) {
// Checking if we have have to enque PRODUCTION_ENDs for any
// stacked productions which end on the same next position
while (stackPointer >= 0 && stack[stackPointer] == position + length) {
prodEndCount++;
stackPointer--;
}
}
position += length - POSITION_INCREMENT;
}
}

public short kind() {
checkBegin();
checkEnd();
Expand Down Expand Up @@ -309,18 +328,23 @@ protected final boolean term(short part, int term) {
int i = terms.index();
int t = terms.advance();
if (t == term) {
markTermBegin();
if (part != NO_PART) {
markTerm(part, t);
}
match(part, t);
return true;
}
mismatch(terms.index(), term, t);
mismatch(term, t);
terms.reset(i);
return false;
}

private void mismatch(int index, int termExpected, int termActual) {
protected final void match(short part, int term) {
markTermBegin();
if (part != NO_PART) {
markTerm(part, term);
}
}

protected final void mismatch(int termExpected, int termActual) {
int index = terms.index();
// farthest or first (when equal) mismatch wins
if (index > mismatchAt) {
mismatchAt = index;
Expand Down
26 changes: 24 additions & 2 deletions src/io/immutables/grammar/processor/Generator.generator
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ public final class [className]<T extends [grmp].TreeProduction<[treesClass]>> ex
[if p.subtypes]
return [for s in p.subtypes][if not for.first]
|| [/if][asVar s](part)[/for];
[else if p.literalAlternatives]
[literalAlternativesBody p]
[else]
int i = terms.index(), p = position;
[for a in p.alternatives]
Expand Down Expand Up @@ -335,6 +337,26 @@ public final class [className]<T extends [grmp].TreeProduction<[treesClass]>> ex
}
[/template]

[template literalAlternativesBody Prod prod]
int i = terms.index(), p = position;
[if not prod.ephemeral]
production(part, KIND_[asConstant prod.id]);
[/if]
int t = terms.advance();
switch (t) {
[for l in prod.literalAlternatives]
case TERM_[asTokenConstant l]:
[/for]
match([if prod.hasTagged]part != 0 ? [for tg in prod.parts][if for.first]PART_[asConstant tg.tag][/if][/for] : [/if]NO_PART, t);
return end(part, p);
default:
[-- Just use first in alternatives do describe mismatch --]
mismatch([for l in prod.literalAlternatives][if for.first]TERM_[asTokenConstant l][/if][/for], t);
terms.reset(i); position = p;
return false;
}
[/template]

[template alternativeBody Prod prod Alt alt String altVar]
[for part in alt.parts if not part.mode.consume][if for.first]
int j;
Expand Down Expand Up @@ -366,7 +388,7 @@ while ([inlineMatch p for.index]);[-- multiple optional --]

[template inlineMatch Part p Integer partIndex][output.trim]
[if p.literal]
term([if p.tagged]part != 0 ? PART_[asConstant p.tag] : NO_PART[else]NO_PART[/if], TERM_[asTokenConstant p.literal])
term([if p.tagged]part != 0 ? PART_[asConstant p.tag] : [/if]NO_PART, TERM_[asTokenConstant p.literal])
[else if p.reference]
[if p.reference.ephemeral]
[asVar p.reference.id](part != 0 ? ANY_PART : NO_PART)
Expand Down Expand Up @@ -416,7 +438,7 @@ private static [treesClass].[type] [var](Traversal in) {
[/if]
break;
[/for]
default: throw io.immutables.Unreachable.exhaustive();
default: throw io.immutables.Unreachable.contractual();
}
}[/if]

Expand Down
2 changes: 1 addition & 1 deletion src/io/immutables/grammar/processor/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Templates.Invokable with(String pack, String name, TermDispatch dispatch, Vect<P
id -> asConstant.apply(dispatch.termsById().get(id).name().value());

final Function<Grammars.ProductionPart, PartCase> asPartCase = PartCase::new;

class PartCase {
final Cardinality cardinality;
final boolean consume;
Expand Down
20 changes: 20 additions & 0 deletions src/io/immutables/grammar/processor/Production.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.function.Predicate;
import javax.annotation.Nullable;
import org.immutables.value.Value.Check;
import org.immutables.value.Value.Derived;
import org.immutables.value.Value.Enclosing;
import org.immutables.value.Value.Immutable;
import org.immutables.value.Value.Lazy;
Expand Down Expand Up @@ -94,6 +95,25 @@ Vect<Alternative> alwaysSucceedingAlternatives() {
return alternatives().filter(Production::isAlwaysSucceding);
}

/**
* If this list is not empty, then production is a pure single-literal alternative list.
*/
@Derived
Vect<Literal> literalAlternatives() {
if (alternatives().size() > 1
&& alternatives().all(a -> !a.singular()
&& a.parts().size() == 1
&& a.parts().get(0).mode().consume()
&& a.parts().get(0) instanceof LiteralPart)
&& parts().all(p -> p.cardinality().isExactlyOne())) {
return alternatives()
.flatMap(Alternative::parts)
.only(LiteralPart.class)
.map(LiteralPart::literal);
}
return Vect.of();
}

static class Builder extends ImmutableProduction.Builder {}

@Immutable
Expand Down

0 comments on commit 01bf3fc

Please sign in to comment.