Skip to content

Commit

Permalink
(#360) Renamed defU shorthand to def and reimplemented until using seq.
Browse files Browse the repository at this point in the history
  • Loading branch information
mvanaken committed Mar 1, 2023
1 parent 94d00df commit c3e1593
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 40 deletions.
75 changes: 58 additions & 17 deletions core/src/main/java/io/parsingdata/metal/Shorthand.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,38 @@ private Shorthand() {}
/** "DEFinition": Instantiates a {@link Def} with {@code size = con(size)} and {@code encoding = null}, nested in a {@link Post}. */
public static Token def(final String name, final long size, final Expression predicate) { return def(name, size, predicate, null); }


/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined. */
public static Token def(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator, final Encoding encoding) { return new Until(name, initialSize, stepSize, maxSize, terminator, false, encoding); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code encoding = null}. */
public static Token def(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator) { return def(name, initialSize, stepSize, maxSize, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code maxSize = null}. */
public static Token def(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator, final Encoding encoding) { return def(name, initialSize, stepSize, null, terminator, encoding); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code maxSize = null} and {@code encoding = null}. */
public static Token def(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator) { return def(name, initialSize, stepSize, null, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code stepSize = null} and {@code maxSize = null}. */
public static Token def(final String name, final ValueExpression initialSize, final Token terminator, final Encoding encoding) { return def(name, initialSize, null, terminator, encoding); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code stepSize = null}, {@code maxSize = null} and {@code encoding = null}. */
public static Token def(final String name, final ValueExpression initialSize, final Token terminator) { return def(name, initialSize, null, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code initialSize = null}, {@code stepSize = null} and {@code maxSize = null}. */
public static Token def(final String name, final Token terminator, final Encoding encoding) { return def(name, null, terminator, encoding); }

/** "DEFinition": Instantiates a {@link Until} where the size of the def is dynamically determined with {@code initialSize = null}, {@code stepSize = null}, {@code maxSize = null} and {@code encoding = null}. */
public static Token def(final String name, final Token terminator) { return def(name, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} with the expression nested in a {@link Post} and {@code initialSize = con(1)}. */
public static Token def(final String name, final Expression predicate, final Encoding encoding) { return def(name, con(1), post(EMPTY, predicate), encoding); }

/** "DEFinition": Instantiates a {@link Until} where the terminator is the expression nested in a {@link Post}, {@code initialSize = con(1)} and {@code encoding = null}. */
public static Token def(final String name, final Expression predicate) { return def(name, predicate, null); }


/** "NO Data": denotes data that is not required during parsing and afterwards. Instantiates a {@link Def} with {@code name = EMPTY_NAME} and {@code encoding = null}. */
public static Token nod(final SingleValueExpression size) { return def(EMPTY_NAME, size); }

Expand Down Expand Up @@ -180,23 +212,32 @@ private Shorthand() {}
/** @see Tie */ public static Token tie(final String name, final Token token, final ValueExpression dataExpression) { return tie(name, token, dataExpression, null); }
/** @see Tie */ public static Token tie(final Token token, final ValueExpression dataExpression, final Encoding encoding) { return tie(NO_NAME, token, dataExpression, encoding); }
/** @see Tie */ public static Token tie(final Token token, final ValueExpression dataExpression) { return tie(token, dataExpression, null); }
/** @see Until */ public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator, final Encoding encoding) { return new Until(name, initialSize, stepSize, maxSize, terminator, true, encoding); }
/** @see Until */ public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator) { return until(name, initialSize, stepSize, maxSize, terminator, null); }
/** @see Until */ public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator, final Encoding encoding) { return until(name, initialSize, stepSize, null, terminator, encoding); }
/** @see Until */ public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator) { return until(name, initialSize, stepSize, null, terminator, null); }
/** @see Until */ public static Token until(final String name, final ValueExpression initialSize, final Token terminator, final Encoding encoding) { return until(name, initialSize, null, terminator, encoding); }
/** @see Until */ public static Token until(final String name, final ValueExpression initialSize, final Token terminator) { return until(name, initialSize, null, terminator, null); }
/** @see Until */ public static Token until(final String name, final Token terminator, final Encoding encoding) { return until(name, null, terminator, encoding); }
/** @see Until */ public static Token until(final String name, final Token terminator) { return until(name, terminator, null); }

public static Token defU(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator, final Encoding encoding) { return new Until(name, initialSize, stepSize, maxSize, terminator, false, encoding); }
public static Token defU(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator) { return defU(name, initialSize, stepSize, maxSize, terminator, null); }
public static Token defU(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator, final Encoding encoding) { return defU(name, initialSize, stepSize, null, terminator, encoding); }
public static Token defU(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator) { return defU(name, initialSize, stepSize, null, terminator, null); }
public static Token defU(final String name, final ValueExpression initialSize, final Token terminator, final Encoding encoding) { return defU(name, initialSize, null, terminator, encoding); }
public static Token defU(final String name, final ValueExpression initialSize, final Token terminator) { return defU(name, initialSize, null, terminator, null); }
public static Token defU(final String name, final Token terminator, final Encoding encoding) { return defU(name, null, terminator, encoding); }
public static Token defU(final String name, final Token terminator) { return defU(name, terminator, null); }


/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq}. */
public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator, final Encoding encoding) { return seq(name, def(name, initialSize, stepSize, maxSize, terminator, encoding), terminator); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code encoding = null}. */
public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final ValueExpression maxSize, final Token terminator) { return until(name, initialSize, stepSize, maxSize, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code maxSize = null}. */
public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator, final Encoding encoding) { return until(name, initialSize, stepSize, null, terminator, encoding); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code maxSize = null} and {@code encoding = null}. */
public static Token until(final String name, final ValueExpression initialSize, final ValueExpression stepSize, final Token terminator) { return until(name, initialSize, stepSize, null, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code stepSize = null} and {@code maxSize = null}. */
public static Token until(final String name, final ValueExpression initialSize, final Token terminator, final Encoding encoding) { return until(name, initialSize, null, terminator, encoding); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code stepSize = null}, {@code maxSize = null} and {@code encoding = null}. */
public static Token until(final String name, final ValueExpression initialSize, final Token terminator) { return until(name, initialSize, null, terminator, null); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code initialSize = null}, {@code stepSize = null} and {@code maxSize = null}. */
public static Token until(final String name, final Token terminator, final Encoding encoding) { return until(name, null, terminator, encoding); }

/** "DEFinition": Instantiates a {@link Until} and its terminator nested in a {@link Seq} with {@code initialSize = null}, {@code stepSize = null}, {@code maxSize = null} and {@code encoding = null}. */
public static Token until(final String name, final Token terminator) { return until(name, terminator, null); }


/** "WHEN": denotes a logical implication, parses the {@code token} only if the {@code predicate} evaluates to {code true} and subsequently only fails if {@code token} does not successfully parse. A composition of {@link Cho} and {@link Pre}. */
public static Token when(final String name, final Token token, final Expression predicate, final Encoding encoding) { return cho(name, encoding, pre(def(EMPTY_NAME, 0), not(predicate)), token); }
Expand Down
70 changes: 47 additions & 23 deletions core/src/test/java/io/parsingdata/metal/token/UntilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import static io.parsingdata.metal.Shorthand.EMPTY;
import static io.parsingdata.metal.Shorthand.con;
import static io.parsingdata.metal.Shorthand.def;
import static io.parsingdata.metal.Shorthand.defU;
import static io.parsingdata.metal.Shorthand.def;
import static io.parsingdata.metal.Shorthand.eq;
import static io.parsingdata.metal.Shorthand.last;
import static io.parsingdata.metal.Shorthand.mod;
Expand All @@ -47,10 +47,10 @@
import io.parsingdata.metal.data.ParseState;
import io.parsingdata.metal.data.ParseValue;
import io.parsingdata.metal.encoding.Encoding;
import io.parsingdata.metal.expression.Expression;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.runners.Parameterized.Parameters;

class UntilTest {

Expand All @@ -59,29 +59,30 @@ class UntilTest {
private static final String INPUT_3 = "Another way to scroll...";
private static final String INPUT = INPUT_1 + "\n" + INPUT_2 + "\n" + INPUT_3 + "\n";

public static final Expression ENDS_WITH_NEWLINE = eq(mod(last(ref("line")), con(256)), con('\n'));
public static final Token NEWLINE = def("newline", con(1), eq(con('\n')));
public static final Token END_WITH_NEWLINE_POST = post(EMPTY, eq(mod(last(ref("line")), con(256)), con('\n')));
public static final Token END_WITH_NEWLINE_POST = post(EMPTY, ENDS_WITH_NEWLINE);
public static final Token END_WITH_NEWLINE_SUB = sub(NEWLINE, sub(CURRENT_OFFSET, con(1)));
public static final Token NEXT_START_WITH_TERMINATOR = sub(NEWLINE, CURRENT_OFFSET);

@Parameters(name="{0}")
static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ "until: terminator not part of line, available in parseGraph", until("line", NEWLINE), 3, 3, INPUT_1, INPUT_2, INPUT_3},
{ "until: terminator part of line, not available in parseGraph", until("line", con(1), END_WITH_NEWLINE_POST), 3, 0, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "until: terminator part of line, available in parseGraph", until("line", con(1), END_WITH_NEWLINE_SUB), 3, 3, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "until: terminator part of next line, available in parseGraph", until("line", con(1), NEXT_START_WITH_TERMINATOR), 3, 3, INPUT_1, '\n' + INPUT_2, '\n' + INPUT_3},

{ "defU: terminator not part of line, available in parseGraph", seq(defU("line", NEWLINE), NEWLINE), 3, 3, INPUT_1, INPUT_2, INPUT_3},
{ "defU: terminator part of line, not available in parseGraph", defU("line", con(1), END_WITH_NEWLINE_POST), 3, 0, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "defU: terminator part of line, not available in parseGraph", defU("line", con(1), END_WITH_NEWLINE_SUB), 3, 0, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "defU: terminator part of next line, not available in parseGraph", defU("line", con(1), NEWLINE), 3, 0, INPUT_1, '\n' + INPUT_2, '\n' + INPUT_3},
{ "defU: terminator part of next line, not available in parseGraph", defU("line", con(1), NEXT_START_WITH_TERMINATOR), 3, 0, INPUT_1, '\n' + INPUT_2, '\n' + INPUT_3},
// "defU: terminator part of line, available in parseGraph" is not possible with defU, only with until.
{ "def: terminator not part of line, available in parseGraph", seq(def("line", NEWLINE), NEWLINE), 3, 3, INPUT_1, INPUT_2, INPUT_3},
{ "def: terminator part of line, not available in parseGraph", def("line", con(1), END_WITH_NEWLINE_POST), 3, 0, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "def: terminator part of line, not available in parseGraph", def("line", con(1), END_WITH_NEWLINE_SUB), 3, 0, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "def: terminator part of line, not available in parseGraph", def("line", ENDS_WITH_NEWLINE), 3, 0, INPUT_1 + '\n', INPUT_2 + '\n', INPUT_3 + '\n'},
{ "def: terminator part of next line, not available in parseGraph", def("line", con(1), NEWLINE), 3, 0, INPUT_1, '\n' + INPUT_2, '\n' + INPUT_3},
{ "def: terminator part of next line, not available in parseGraph", def("line", con(1), NEXT_START_WITH_TERMINATOR), 3, 0, INPUT_1, '\n' + INPUT_2, '\n' + INPUT_3},
// "def: terminator part of line, available in parseGraph" is not possible with def, only with until.
});
}

@ParameterizedTest
@ParameterizedTest(name="{0}")
@MethodSource("data")
void repTest(final String name, final Token token, final int lineCount, final int newlineCount, final String line1, final String line2, final String line3) {
final Optional<ParseState> parseState = rep(token).parse(env(stream(INPUT, US_ASCII)));
Expand All @@ -97,22 +98,21 @@ void repTest(final String name, final Token token, final int lineCount, final in
assertEquals(newlineCount, newLines.size);
}

@Parameters(name="{0}")
static Collection<Object[]> defUShorthands() {
static Collection<Object[]> shorthandTokenTest() {
return Arrays.asList(new Object[][] {
{ "defU", defU("line", NEWLINE) },
{ "defU initial size", defU("line", con(13), NEWLINE)},
{ "defU initial size + encoding", defU("line", con(13), NEWLINE, Encoding.DEFAULT_ENCODING)},
{ "defU step size", defU("line", con(13), con(1), NEWLINE)},
{ "defU step size + encoding", defU("line", con(13), con(1), NEWLINE, Encoding.DEFAULT_ENCODING)},
{ "defU max size", defU("line", con(13), con(1), con(24), NEWLINE)},
{ "defU max size + encoding", defU("line", con(13), con(1), con(24), NEWLINE, Encoding.DEFAULT_ENCODING)},
{ "def", def("line", NEWLINE) },
{ "def initial size", def("line", con(13), NEWLINE)},
{ "def initial size + encoding", def("line", con(13), NEWLINE, Encoding.DEFAULT_ENCODING)},
{ "def step size", def("line", con(13), con(1), NEWLINE)},
{ "def step size + encoding", def("line", con(13), con(1), NEWLINE, Encoding.DEFAULT_ENCODING)},
{ "def max size", def("line", con(13), con(1), con(24), NEWLINE)},
{ "def max size + encoding", def("line", con(13), con(1), con(24), NEWLINE, Encoding.DEFAULT_ENCODING)},
});
}

@ParameterizedTest
@MethodSource("defUShorthands")
void shorthandTest(final String name, final Token token) {
@ParameterizedTest(name="{0}")
@MethodSource
void shorthandTokenTest(final String name, final Token token) {
final Optional<ParseState> parseState = rep(seq(token, NEWLINE)).parse(env(stream(INPUT, US_ASCII)));
assertTrue(parseState.isPresent());

Expand All @@ -126,6 +126,30 @@ void shorthandTest(final String name, final Token token) {
assertEquals(3, newLines.size);
}

static Collection<Object[]> shorthandExpressionTest() {
return Arrays.asList(new Object[][] {
{ "def token", def("line", con(1), END_WITH_NEWLINE_POST)},
{ "def expression", def("line", ENDS_WITH_NEWLINE)},
{ "def expression + encoding", def("line", ENDS_WITH_NEWLINE, Encoding.DEFAULT_ENCODING)},
});
}

@ParameterizedTest(name="{0}")
@MethodSource
void shorthandExpressionTest(final String name, final Token token) {
final Optional<ParseState> parseState = rep(token).parse(env(stream(INPUT, US_ASCII)));
assertTrue(parseState.isPresent());

ImmutableList<ParseValue> values = getAllValues(parseState.get().order, "line");
assertEquals(3, values.size);
assertEquals(INPUT_1 + "\n", values.tail.tail.head.asString());
assertEquals(INPUT_2 + "\n", values.tail.head.asString());
assertEquals(INPUT_3 + "\n", values.head.asString());

ImmutableList<ParseValue> newLines = getAllValues(parseState.get().order, "newline");
assertEquals(0, newLines.size);
}

@Test
void allDefaultValueExpressions() {
assertTrue(until("value", def("terminator", 1, eq(con(0)))).parse(env(stream(1, 2, 3, 0))).isPresent());
Expand Down

0 comments on commit c3e1593

Please sign in to comment.