Skip to content

Commit

Permalink
#274: Refactored ValueExpression and Token implementations to adhere …
Browse files Browse the repository at this point in the history
…to the defined naming scheme around ValueExpression instances.
  • Loading branch information
jvdb committed Dec 17, 2018
1 parent 0e93cfa commit c7b54c8
Show file tree
Hide file tree
Showing 33 changed files with 278 additions and 274 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* Base class for {@link ValueExpression}s with two operands.
* <p>
* A BinaryValueExpression implements a ValueExpression that has two operands:
* <code>left</code> and <code>right</code> (both {@link ValueExpression}s).
* <code>lefts</code> and <code>rights</code> (both {@link ValueExpression}s).
* Both operands are themselves first evaluated. If at least one of the
* operands evaluates to {@link Optional#empty()}, the result of the
* ValueExpression itself will be empty as well.
Expand All @@ -45,27 +45,27 @@
* size of the longest list.
* <p>
* To implement a BinaryValueExpression, only the
* {@link #eval(Value, Value, ParseState, Encoding)} must be implemented,
* {@link #eval(Value, Value, ParseState, Encoding)} method must be implemented,
* handling the case of evaluating two values. This base class takes care of
* evaluating the operands and handling list semantics.
*
* @see UnaryValueExpression
*/
public abstract class BinaryValueExpression implements ValueExpression {

public final ValueExpression left;
public final ValueExpression right;
public final ValueExpression lefts;
public final ValueExpression rights;

public BinaryValueExpression(final ValueExpression left, final ValueExpression right) {
this.left = checkNotNull(left, "left");
this.right = checkNotNull(right, "right");
public BinaryValueExpression(final ValueExpression lefts, final ValueExpression rights) {
this.lefts = checkNotNull(lefts, "lefts");
this.rights = checkNotNull(rights, "rights");
}

public abstract Optional<Value> eval(final Value left, final Value right, final ParseState parseState, final Encoding encoding);
public abstract Optional<Value> eval(final Value leftValue, final Value rightValue, final ParseState parseState, final Encoding encoding);

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
return evalLists(left.eval(parseState, encoding), right.eval(parseState, encoding), parseState, encoding);
return evalLists(lefts.eval(parseState, encoding), rights.eval(parseState, encoding), parseState, encoding);
}

private ImmutableList<Optional<Value>> evalLists(final ImmutableList<Optional<Value>> leftValues, final ImmutableList<Optional<Value>> rightValues, final ParseState parseState, final Encoding encoding) {
Expand All @@ -88,19 +88,19 @@ private Trampoline<ImmutableList<Optional<Value>>> padList(final ImmutableList<O

@Override
public String toString() {
return getClass().getSimpleName() + "(" + left + "," + right + ")";
return getClass().getSimpleName() + "(" + lefts + "," + rights + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(left, ((BinaryValueExpression)obj).left)
&& Objects.equals(right, ((BinaryValueExpression)obj).right);
&& Objects.equals(lefts, ((BinaryValueExpression)obj).lefts)
&& Objects.equals(rights, ((BinaryValueExpression)obj).rights);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), left, right);
return Objects.hash(getClass(), lefts, rights);
}

}
35 changes: 18 additions & 17 deletions core/src/main/java/io/parsingdata/metal/expression/value/Bytes.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,34 +34,35 @@
import io.parsingdata.metal.encoding.Encoding;

/**
* A {@link ValueExpression} that splits the results of evaluating its operand
* into individual bytes.
* A {@link ValueExpression} that splits the results of evaluating its
* <code>operands</code> field into individual bytes.
* <p>
* A Bytes expression has a single <code>operand</code> (a
* {@link ValueExpression}). When evaluated, it evaluates <code>operand</code>
* A Bytes expression has a single <code>operands</code> field (a
* {@link ValueExpression}). When evaluated, it evaluates <code>operands</code>
* and instead of returning the list of results, each result is split into
* {@link Value} objects representing each individual byte of the original
* result.
* <p>
* For example, if <code>operand</code> evaluates to a list of two values, of
* 2 and 3 bytes respectively, the Bytes expression turns this into a list of
* 5 values, representing the individual bytes of the original results.
* For example, if <code>operands</code> evaluates to a list of two values, of
* 2 and 3 bytes respectively, the <code>Bytes</code> expression turns this
* into a list of 5 values, representing the individual bytes of the original
* results.
*/
public class Bytes implements ValueExpression {

public final ValueExpression operand;
public final ValueExpression operands;

public Bytes(final ValueExpression operand) {
this.operand = checkNotNull(operand, "operand");
public Bytes(final ValueExpression operands) {
this.operands = checkNotNull(operands, "operands");
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
final ImmutableList<Optional<Value>> input = operand.eval(parseState, encoding);
if (input.isEmpty()) {
return input;
final ImmutableList<Optional<Value>> evaluatedOperands = operands.eval(parseState, encoding);
if (evaluatedOperands.isEmpty()) {
return evaluatedOperands;
}
return toByteValues(new ImmutableList<>(), input.head, input.tail, encoding).computeResult();
return toByteValues(new ImmutableList<>(), evaluatedOperands.head, evaluatedOperands.tail, encoding).computeResult();
}

private Trampoline<ImmutableList<Optional<Value>>> toByteValues(final ImmutableList<Optional<Value>> output, final Optional<Value> head, final ImmutableList<Optional<Value>> tail, final Encoding encoding) {
Expand All @@ -80,18 +81,18 @@ private Trampoline<ImmutableList<Optional<Value>>> extractByteValues(final Immut

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
return getClass().getSimpleName() + "(" + operands + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((Bytes)obj).operand);
&& Objects.equals(operands, ((Bytes)obj).operands);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
return Objects.hash(getClass(), operands);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@
*/
public class Cat extends BinaryValueExpression {

public Cat(final ValueExpression left, final ValueExpression right) {
super(left, right);
public Cat(final ValueExpression lefts, final ValueExpression rights) {
super(lefts, rights);
}

@Override
public Optional<Value> eval(final Value left, final Value right, final ParseState parseState, final Encoding encoding) {
return ConcatenatedValueSource.create(ImmutableList.create(Optional.of(left)).add(Optional.of(right)))
.flatMap(source -> createFromSource(source, ZERO, left.getLength().add(right.getLength())))
public Optional<Value> eval(final Value leftValue, final Value rightValue, final ParseState parseState, final Encoding encoding) {
return ConcatenatedValueSource.create(ImmutableList.create(Optional.of(leftValue)).add(Optional.of(rightValue)))
.flatMap(source -> createFromSource(source, ZERO, leftValue.getLength().add(rightValue.getLength())))
.map(source -> new Value(source, encoding));
}

Expand Down
28 changes: 14 additions & 14 deletions core/src/main/java/io/parsingdata/metal/expression/value/Elvis.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,27 @@
* A {@link ValueExpression} that implements the Elvis operator:
* <pre>?:</pre>.
* <p>
* An Elvis expression has two operands: <code>left</code> and
* <code>right</code> (both {@link ValueExpression}s). Both operands are
* An Elvis expression has two operands: <code>lefts</code> and
* <code>rights</code> (both {@link ValueExpression}s). Both operands are
* evaluated. The return value is a list with the size of the longest list
* returned by the two evaluations. At each index, the value at that index in
* the result returned by evaluating <code>left</code> is placed, except if it
* the result returned by evaluating <code>lefts</code> is placed, except if it
* does not exist or is {@link Optional#empty()}, in which case the value at
* that index in the result returned by evaluating right is placed there.
* that index in the result returned by evaluating rights is placed there.
*/
public class Elvis implements ValueExpression {

public final ValueExpression left;
public final ValueExpression right;
public final ValueExpression lefts;
public final ValueExpression rights;

public Elvis(final ValueExpression left, final ValueExpression right) {
this.left = checkNotNull(left, "left");
this.right = checkNotNull(right, "right");
public Elvis(final ValueExpression lefts, final ValueExpression rights) {
this.lefts = checkNotNull(lefts, "lefts");
this.rights = checkNotNull(rights, "rights");
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
return reverse(eval(new ImmutableList<>(), left.eval(parseState, encoding), right.eval(parseState, encoding)).computeResult());
return reverse(eval(new ImmutableList<>(), lefts.eval(parseState, encoding), rights.eval(parseState, encoding)).computeResult());
}

private Trampoline<ImmutableList<Optional<Value>>> eval(final ImmutableList<Optional<Value>> result, final ImmutableList<Optional<Value>> leftValues, final ImmutableList<Optional<Value>> rightValues) {
Expand All @@ -69,19 +69,19 @@ private Trampoline<ImmutableList<Optional<Value>>> eval(final ImmutableList<Opti

@Override
public String toString() {
return getClass().getSimpleName() + "(" + left + "," + right + ")";
return getClass().getSimpleName() + "(" + lefts + "," + rights + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(left, ((Elvis)obj).left)
&& Objects.equals(right, ((Elvis)obj).right);
&& Objects.equals(lefts, ((Elvis)obj).lefts)
&& Objects.equals(rights, ((Elvis)obj).rights);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), left, right);
return Objects.hash(getClass(), lefts, rights);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,58 +33,58 @@
* A {@link ValueExpression} that expands a result by copying and concatenating
* it a specified amount of times.
* <p>
* An Expand expression has two operands: <code>base</code> and
* An Expand expression has two operands: <code>bases</code> and
* <code>count</code> (both {@link ValueExpression}s). Both operands are
* evaluated. An <code>IllegalStateException</code> is thrown if evaluating
* <code>count</code> yields more than a single value. Multiple copies of the
* result of evaluating <code>base</code> are concatenated. The amount of copies
* result of evaluating <code>bases</code> are concatenated. The amount of copies
* equals the result of evaluating <code>count</code>.
*/
public class Expand implements ValueExpression {

public final ValueExpression base;
public final ValueExpression bases;
public final ValueExpression count;

public Expand(final ValueExpression base, final ValueExpression count) {
this.base = checkNotNull(base, "base");
public Expand(final ValueExpression bases, final ValueExpression count) {
this.bases = checkNotNull(bases, "bases");
this.count = checkNotNull(count, "count");
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
final ImmutableList<Optional<Value>> base = this.base.eval(parseState, encoding);
if (base.isEmpty()) {
return base;
final ImmutableList<Optional<Value>> evaluatedBases = bases.eval(parseState, encoding);
if (evaluatedBases.isEmpty()) {
return evaluatedBases;
}
final ImmutableList<Optional<Value>> count = this.count.eval(parseState, encoding);
if (count.size != 1 || !count.head.isPresent()) {
final ImmutableList<Optional<Value>> evaluatedCount = count.eval(parseState, encoding);
if (evaluatedCount.size != 1 || !evaluatedCount.head.isPresent()) {
throw new IllegalArgumentException("Count must evaluate to a single non-empty value.");
}
return expand(base, count.head.get().asNumeric().intValueExact(), new ImmutableList<>()).computeResult();
return expand(evaluatedBases, evaluatedCount.head.get().asNumeric().intValueExact(), new ImmutableList<>()).computeResult();
}

private Trampoline<ImmutableList<Optional<Value>>> expand(final ImmutableList<Optional<Value>> base, final int count, final ImmutableList<Optional<Value>> aggregate) {
if (count < 1) {
private Trampoline<ImmutableList<Optional<Value>>> expand(final ImmutableList<Optional<Value>> baseValues, final int countValue, final ImmutableList<Optional<Value>> aggregate) {
if (countValue < 1) {
return complete(() -> aggregate);
}
return intermediate(() -> expand(base, count - 1, aggregate.add(base)));
return intermediate(() -> expand(baseValues, countValue - 1, aggregate.add(baseValues)));
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + base + "," + count + ")";
return getClass().getSimpleName() + "(" + bases + "," + count + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(base, ((Expand)obj).base)
&& Objects.equals(bases, ((Expand)obj).bases)
&& Objects.equals(count, ((Expand)obj).count);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), base, count);
return Objects.hash(getClass(), bases, count);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,18 @@ public Fold(final ValueExpression values, final BinaryOperator<ValueExpression>

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
final ImmutableList<Optional<Value>> initial = this.initial != null ? this.initial.eval(parseState, encoding) : new ImmutableList<>();
if (initial.size > 1) {
final ImmutableList<Optional<Value>> evaluatedInitial = initial != null ? initial.eval(parseState, encoding) : new ImmutableList<>();
if (evaluatedInitial.size > 1) {
return new ImmutableList<>();
}
final ImmutableList<Optional<Value>> values = prepareValues(this.values.eval(parseState, encoding));
if (values.isEmpty() || containsEmpty(values).computeResult()) {
return initial;
final ImmutableList<Optional<Value>> preparedValues = prepareValues(this.values.eval(parseState, encoding));
if (preparedValues.isEmpty() || containsEmpty(preparedValues).computeResult()) {
return evaluatedInitial;
}
if (!initial.isEmpty()) {
return ImmutableList.create(fold(parseState, encoding, reducer, initial.head, values).computeResult());
if (!evaluatedInitial.isEmpty()) {
return ImmutableList.create(fold(parseState, encoding, reducer, evaluatedInitial.head, preparedValues).computeResult());
}
return ImmutableList.create(fold(parseState, encoding, reducer, values.head, values.tail).computeResult());
return ImmutableList.create(fold(parseState, encoding, reducer, preparedValues.head, preparedValues.tail).computeResult());
}

private Trampoline<Optional<Value>> fold(final ParseState parseState, final Encoding encoding, final BinaryOperator<ValueExpression> reducer, final Optional<Value> head, final ImmutableList<Optional<Value>> tail) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static java.math.BigInteger.ZERO;

import static io.parsingdata.metal.Util.checkNotNull;
import static io.parsingdata.metal.data.Slice.createFromSource;

import java.util.Objects;
Expand All @@ -38,34 +39,34 @@
*/
public class FoldCat implements ValueExpression {

public final ValueExpression operand;
public final ValueExpression operands;

public FoldCat(final ValueExpression operand) {
this.operand = operand;
public FoldCat(final ValueExpression operands) {
this.operands = checkNotNull(operands, "operands");
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
return ConcatenatedValueSource.create(operand.eval(parseState, encoding))
return ConcatenatedValueSource.create(operands.eval(parseState, encoding))
.flatMap(source -> createFromSource(source, ZERO, source.length))
.map(slice -> new ImmutableList<Optional<Value>>().add(Optional.of(new Value(slice, encoding))))
.orElseGet(() -> ImmutableList.create(Optional.empty()));
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
return getClass().getSimpleName() + "(" + operands + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((FoldCat)obj).operand);
&& Objects.equals(operands, ((FoldCat)obj).operands);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
return Objects.hash(getClass(), operands);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.parsingdata.metal.expression.value;

import static io.parsingdata.metal.Util.checkNotNull;
import static io.parsingdata.metal.data.Selection.reverse;

import java.util.Objects;
Expand All @@ -38,7 +39,7 @@ public class Reverse implements ValueExpression {
public final ValueExpression values;

public Reverse(final ValueExpression values) {
this.values = values;
this.values = checkNotNull(values, "values");
}

@Override
Expand Down
Loading

0 comments on commit c7b54c8

Please sign in to comment.