Skip to content

Commit

Permalink
Add new scope shorthands for convenience with matchine tests.
Browse files Browse the repository at this point in the history
Also included test for refs with limit 0, which return an empty list
immediately in the new getAllScopedValues. If limit is 0, not need to go
find the correct scope and we can return immediately.
  • Loading branch information
mvanaken committed Feb 10, 2024
1 parent 471a94f commit cb8db0c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
5 changes: 2 additions & 3 deletions core/src/main/java/io/parsingdata/metal/Shorthand.java
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,9 @@ private Shorthand() {}

/** @see Bytes */ public static ValueExpression bytes(final ValueExpression operand) { return new Bytes(operand); }

/** @deprecated Use {@link #scope(NameRef, SingleValueExpression)} instead. You probably need to switch {@code last} with {@code scope}, e.g. {@code scope(last(x), y)} to {@code last(scope(x, y))}. */
@Deprecated
public static ValueExpression scope(final SingleValueExpression scopedValueExpression, final SingleValueExpression scopeSize) { throw new UnsupportedOperationException("A deprecated shorthand for scope is used. Use one of the other alternatives instead."); }
/** @see Ref */ public static NameRef scope(final NameRef operand) { return scope(operand, con(0)); }
/** @see Ref */ public static NameRef scope(final NameRef operand, final SingleValueExpression scopeSize) { return operand.withScope(scopeSize); }
/** @see Ref */ public static DefinitionRef scope(final DefinitionRef operand) { return scope(operand, con(0)); }
/** @see Ref */ public static DefinitionRef scope(final DefinitionRef operand, final SingleValueExpression scopeSize) { return operand.withScope(scopeSize); }

/** @see And */ public static BinaryLogicalExpression and(final Expression left, final Expression right) { return new And(left, right); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static io.parsingdata.metal.Shorthand.eq;
import static io.parsingdata.metal.Shorthand.first;
import static io.parsingdata.metal.Shorthand.fold;
import static io.parsingdata.metal.Shorthand.join;
import static io.parsingdata.metal.Shorthand.last;
import static io.parsingdata.metal.Shorthand.not;
import static io.parsingdata.metal.Shorthand.offset;
Expand Down Expand Up @@ -70,7 +71,7 @@ private static <T> Token limitedSum(final Ref<T> ref) {
return
seq(rep(def("a", con(1), not(eq(con(0))))),
def("zero", con(1), eq(con(0))),
def("sum", con(1), eq(fold(ref, Shorthand::add))));
def("sum", con(1), eq(fold(join(con(0), ref), Shorthand::add))));
}

@Override
Expand Down Expand Up @@ -107,22 +108,26 @@ public Collection<Object[]> data() {
{ "[1, 2, 3, 1] a, a, a, first(ref(a.definition))", refMatch(eq(first(ref(refAny)))), stream(1, 2, 3, 1), enc(), true },
{ "[1, 2, 3, 6] a, a, a, first(fold(ref(a.definition), add))", refMatch(eq(first(fold(ref(refAny), Shorthand::add)))), stream(1, 2, 3, 6), enc(), true },
{ "[1, 2, 3, 2] a, a, a, last(ref(a.definition))", refMatch(eq(last(ref(refAny)))), stream(1, 2, 3, 2), enc(), false },
{ "[1, 2, 3, 0, 0] a, a, a, 0, sum(ref(a, 0))", limitedSum(ref("a", con(0))), stream(1, 2, 3, 0, 0), enc(), true },
{ "[1, 2, 3, 0, 3] a, a, a, 0, sum(ref(a, 1))", limitedSum(ref("a", con(1))), stream(1, 2, 3, 0, 3), enc(), true },
{ "[1, 2, 3, 0, 5] a, a, a, 0, sum(ref(a, 2))", limitedSum(ref("a", con(2))), stream(1, 2, 3, 0, 5), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(a, 3))", limitedSum(ref("a", con(3))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 7] a, a, a, 0, sum(ref(a, 4))", limitedSum(ref("a", con(4))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(a, 4))", limitedSum(ref("a", con(4))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 0] a, a, a, 0, sum(ref(0, a))", limitedSum(ref(con(0), "a")), stream(1, 2, 3, 0, 0), enc(), true },
{ "[1, 2, 3, 0, 3] a, a, a, 0, sum(ref(1, a))", limitedSum(ref(con(1), "a")), stream(1, 2, 3, 0, 3), enc(), true },
{ "[1, 2, 3, 0, 5] a, a, a, 0, sum(ref(2, a))", limitedSum(ref(con(2), "a")), stream(1, 2, 3, 0, 5), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(3, a))", limitedSum(ref(con(3), "a")), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 7] a, a, a, 0, sum(ref(4, a))", limitedSum(ref(con(4), "a")), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(4, a))", limitedSum(ref(con(4), "a")), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 0] a, a, a, 0, sum(ref(0, a.definition))", limitedSum(ref(con(0), any("a"))), stream(1, 2, 3, 0, 0), enc(), true },
{ "[1, 2, 3, 0, 3] a, a, a, 0, sum(ref(1, a.definition))", limitedSum(ref(con(1), any("a"))), stream(1, 2, 3, 0, 3), enc(), true },
{ "[1, 2, 3, 0, 5] a, a, a, 0, sum(ref(2, a.definition))", limitedSum(ref(con(2), any("a"))), stream(1, 2, 3, 0, 5), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(3, a.definition))", limitedSum(ref(con(3), any("a"))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 7] a, a, a, 0, sum(ref(4, a.definition))", limitedSum(ref(con(4), any("a"))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(4, a.definition))", limitedSum(ref(con(4), any("a"))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 0] a, a, a, 0, sum(ref(a.definition, 0))", limitedSum(ref(any("a"), con(0))), stream(1, 2, 3, 0, 0), enc(), true },
{ "[1, 2, 3, 0, 3] a, a, a, 0, sum(ref(a.definition, 1))", limitedSum(ref(any("a"), con(1))), stream(1, 2, 3, 0, 3), enc(), true },
{ "[1, 2, 3, 0, 5] a, a, a, 0, sum(ref(a.definition, 2))", limitedSum(ref(any("a"), con(2))), stream(1, 2, 3, 0, 5), enc(), true },
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(a.definition, 3))", limitedSum(ref(any("a"), con(3))), stream(1, 2, 3, 0, 6), enc(), true },
{ "[1, 2, 3, 0, 7] a, a, a, 0, sum(ref(a.definition, 4))", limitedSum(ref(any("a"), con(4))), stream(1, 2, 3, 0, 6), enc(), true }
{ "[1, 2, 3, 0, 6] a, a, a, 0, sum(ref(a.definition, 4))", limitedSum(ref(any("a"), con(4))), stream(1, 2, 3, 0, 6), enc(), true }
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,13 @@ public void negativeScopeSize() {
}

@Test
public void scopeSizes() {
public void scopeSizesByName() {
final Token scopesToken =
seq(any("value"), // 0
repn(seq(any("value"), // 1
seq(any("value"), // 2
// deepestValue=2, default scope=0, so refers to the deepest scope, which includes only the "value" in this seq
def("deepestValue", con(1), eq(first(scope(ref("value"))))),
// deepestValue=2, scope=0, so refers to the deepest scope, which includes only the "value" in this seq
def("deepestValue", con(1), eq(first(scope(ref("value"), con(0))))),
// middleValue=1, scope=1, so includes the current seq and the one above it.
Expand All @@ -85,7 +87,35 @@ public void scopeSizes() {
), con(1)
)
);
final Optional<ParseState> result = scopesToken.parse(env(stream(0, 1, 2, 2, 1, 1, 0, 0), enc()));
final Optional<ParseState> result = scopesToken.parse(env(stream(0, 1, 2, 2, 2, 1, 1, 0, 0), enc()));
assertTrue(result.isPresent());
}


@Test
public void scopeSizesByDefinition() {
final Token value = any("value");
final Token scopesToken =
seq(value, // 0
repn(seq(value, // 1
seq(value, // 2
// deepestValue=2, default scope=0, so refers to the deepest scope, which includes only the "value" in this seq
def("deepestValue", con(1), eq(first(scope(ref(value))))),
// deepestValue=2, scope=0, so refers to the deepest scope, which includes only the "value" in this seq
def("deepestValue", con(1), eq(first(scope(ref(value), con(0))))),
// middleValue=1, scope=1, so includes the current seq and the one above it.
def("middleValue", con(1), eq(first(scope(ref(value), con(1))))),
// stillMiddleValue=1, scope=2, but since repn is also a scope delimiter, it does not include the top-level seq
def("stillMiddleValue", con(1), eq(first(scope(ref(value), con(2))))),
// topValue=0, scope=3, includes all scope delimiting tokens, to effectively global
def("topValue", con(1), eq(first(scope(ref(value), con(3))))),
// hugeScope=0, scope=100, everything from 3 up is global scope since there are 4 scope delimiting tokens (0-3)
def("hugeScope", con(1), eq(first(scope(ref(value), con(100)))))
)
), con(1)
)
);
final Optional<ParseState> result = scopesToken.parse(env(stream(0, 1, 2, 2, 2, 1, 1, 0, 0), enc()));
assertTrue(result.isPresent());
}

Expand Down

0 comments on commit cb8db0c

Please sign in to comment.