Skip to content

Commit 32ff6c6

Browse files
committed
#187: Eliminate use of nulls.
Started with the Shorthands.
1 parent 24d911c commit 32ff6c6

File tree

17 files changed

+107
-50
lines changed

17 files changed

+107
-50
lines changed

core/src/main/java/io/parsingdata/metal/Shorthand.java

Lines changed: 35 additions & 34 deletions
Large diffs are not rendered by default.

core/src/main/java/io/parsingdata/metal/data/ParseGraph.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public class ParseGraph implements ParseItem {
3737
public final Token definition;
3838
public final long size;
3939

40-
public static final Token NONE = new Token("NONE", null) {
40+
public static final Token NONE = new Token("NONE", Encoding.DEFAULT) {
4141
@Override protected Optional<Environment> parseImpl(final String scope, final Environment environment, final Encoding encoding) throws IOException { throw new IllegalStateException("This placeholder may not be invoked."); }
4242
@Override public String toString() { return "None"; }
4343
};

core/src/main/java/io/parsingdata/metal/encoding/Encoding.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
public class Encoding {
2626

27+
public static final Encoding DEFAULT = new Encoding();
28+
2729
public static final Sign DEFAULT_SIGNED = Sign.UNSIGNED;
2830
public static final Charset DEFAULT_CHARSET = StandardCharsets.US_ASCII;
2931
public static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.BIG_ENDIAN;
@@ -54,6 +56,10 @@ public Encoding(final Sign sign, final Charset charset, final ByteOrder byteOrde
5456
this.byteOrder = byteOrder;
5557
}
5658

59+
public boolean isDefault() {
60+
return equals(DEFAULT);
61+
}
62+
5763
@Override
5864
public String toString() {
5965
return getClass().getSimpleName() + "(" + sign + "," + charset + "," + byteOrder + ")";

core/src/main/java/io/parsingdata/metal/expression/comparison/ComparisonExpression.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,23 @@
4949
*/
5050
public abstract class ComparisonExpression implements Expression {
5151

52+
private static final ValueExpression DEFAULT_VALUE_EXPRESSION = (graph, encoding) -> ImmutableList.create(graph.current().map(identity()));
53+
5254
public final ValueExpression value;
5355
public final ValueExpression predicate;
5456

5557
public ComparisonExpression(final ValueExpression value, final ValueExpression predicate) {
56-
this.value = value;
58+
this.value = checkNotNull(value, "value");
5759
this.predicate = checkNotNull(predicate, "predicate");
5860
}
5961

62+
public ComparisonExpression(final ValueExpression predicate) {
63+
this(DEFAULT_VALUE_EXPRESSION, predicate);
64+
}
65+
6066
@Override
6167
public boolean eval(final ParseGraph graph, final Encoding encoding) {
62-
final ImmutableList<Optional<Value>> values = value == null ? ImmutableList.create(graph.current().map(identity())) : value.eval(graph, encoding);
68+
final ImmutableList<Optional<Value>> values = value.eval(graph, encoding);
6369
if (values.isEmpty()) { return false; }
6470
final ImmutableList<Optional<Value>> predicates = predicate.eval(graph, encoding);
6571
if (values.size != predicates.size) { return false; }
@@ -77,7 +83,7 @@ private SafeTrampoline<Boolean> compare(final ImmutableList<Optional<Value>> cur
7783

7884
@Override
7985
public String toString() {
80-
return getClass().getSimpleName() + "(" + (value == null ? "" : value + ",") + predicate + ")";
86+
return getClass().getSimpleName() + "(" + (value.equals(DEFAULT_VALUE_EXPRESSION) ? "" : value + ",") + predicate + ")";
8187
}
8288

8389
@Override

core/src/main/java/io/parsingdata/metal/expression/comparison/Eq.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public Eq(final ValueExpression value, final ValueExpression predicate) {
3636
super(value, predicate);
3737
}
3838

39+
public Eq(final ValueExpression predicate) {
40+
super(predicate);
41+
}
42+
3943
@Override
4044
public boolean compare(final Value left, final Value right) {
4145
final byte[] leftBytes = left.getValue();

core/src/main/java/io/parsingdata/metal/expression/comparison/EqNum.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public EqNum(final ValueExpression value, final ValueExpression predicate) {
3838
super(value, predicate);
3939
}
4040

41+
public EqNum(final ValueExpression predicate) {
42+
super(predicate);
43+
}
44+
4145
@Override
4246
public boolean compare(final Value left, final Value right) {
4347
return left.asNumeric().compareTo(right.asNumeric()) == 0;

core/src/main/java/io/parsingdata/metal/expression/comparison/EqStr.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public EqStr(final ValueExpression value, final ValueExpression predicate) {
3737
super(value, predicate);
3838
}
3939

40+
public EqStr(final ValueExpression predicate) {
41+
super(predicate);
42+
}
43+
4044
@Override
4145
public boolean compare(final Value left, final Value right) {
4246
return left.asString().equals(right.asString());

core/src/main/java/io/parsingdata/metal/expression/comparison/GtNum.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public GtNum(final ValueExpression value, final ValueExpression predicate) {
3636
super(value, predicate);
3737
}
3838

39+
public GtNum(final ValueExpression predicate) {
40+
super(predicate);
41+
}
42+
3943
@Override
4044
public boolean compare(final Value left, final Value right) {
4145
return left.asNumeric().compareTo(right.asNumeric()) > 0;

core/src/main/java/io/parsingdata/metal/expression/comparison/LtNum.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public LtNum(final ValueExpression value, final ValueExpression predicate) {
3636
super(value, predicate);
3737
}
3838

39+
public LtNum(final ValueExpression predicate) {
40+
super(predicate);
41+
}
42+
3943
@Override
4044
public boolean compare(final Value left, final Value right) {
4145
return left.asNumeric().compareTo(right.asNumeric()) < 0;

core/src/main/java/io/parsingdata/metal/expression/value/Fold.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ public abstract class Fold implements ValueExpression {
5050
public final BinaryOperator<ValueExpression> reducer;
5151
public final ValueExpression initial;
5252

53+
public Fold(final ValueExpression values, final BinaryOperator<ValueExpression> reducer) {
54+
this(values, reducer, (graph, encoding) -> new ImmutableList<>());
55+
}
56+
5357
public Fold(final ValueExpression values, final BinaryOperator<ValueExpression> reducer, final ValueExpression initial) {
5458
this.values = checkNotNull(values, "values");
5559
this.reducer = checkNotNull(reducer, "reducer");

core/src/main/java/io/parsingdata/metal/expression/value/FoldLeft.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ public FoldLeft(final ValueExpression values, final BinaryOperator<ValueExpressi
3838
super(values, reducer, initial);
3939
}
4040

41+
public FoldLeft(final ValueExpression values, final BinaryOperator<ValueExpression> reducer) {
42+
super(values, reducer);
43+
}
44+
4145
@Override
4246
protected ImmutableList<Optional<Value>> prepareValues(final ImmutableList<Optional<Value>> values) {
4347
return reverse(values);

core/src/main/java/io/parsingdata/metal/expression/value/FoldRight.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public FoldRight(final ValueExpression values, final BinaryOperator<ValueExpress
3737
super(values, reducer, initial);
3838
}
3939

40+
public FoldRight(final ValueExpression values, final BinaryOperator<ValueExpression> reducer) {
41+
super(values, reducer);
42+
}
43+
4044
@Override
4145
protected ImmutableList<Optional<Value>> prepareValues(final ImmutableList<Optional<Value>> values) {
4246
return values;

core/src/main/java/io/parsingdata/metal/expression/value/reference/Ref.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,31 +51,35 @@ public class Ref<T> implements ValueExpression {
5151
public final Predicate<ParseValue> predicate;
5252
public final ValueExpression limit;
5353

54+
private Ref(final T reference, final Predicate<ParseValue> predicate) {
55+
this(reference, predicate, null);
56+
}
57+
5458
private Ref(final T reference, final Predicate<ParseValue> predicate, final ValueExpression limit) {
5559
this.reference = checkNotNull(reference, "reference");
5660
this.predicate = checkNotNull(predicate, "predicate");
5761
this.limit = limit;
5862
}
5963

6064
public static class NameRef extends Ref<String> {
61-
public NameRef(final String reference) { this(reference, null); }
65+
public NameRef(final String reference) { super(reference, (value) -> value.matches(reference)); }
6266
public NameRef(final String reference, final ValueExpression limit) { super(reference, (value) -> value.matches(reference), limit); }
6367
}
6468

6569
public static class DefinitionRef extends Ref<Token> {
66-
public DefinitionRef(final Token reference) { this(reference, null); }
70+
public DefinitionRef(final Token reference) { super(reference, (value) -> value.definition.equals(reference)); }
6771
public DefinitionRef(final Token reference, final ValueExpression limit) { super(reference, (value) -> value.definition.equals(reference), limit); }
6872
}
6973

7074
@Override
7175
public ImmutableList<Optional<Value>> eval(final ParseGraph graph, final Encoding encoding) {
72-
if (limit == null) { return evalImpl(graph, NO_LIMIT); }
73-
ImmutableList<Optional<Value>> evaluatedLimit = limit.eval(graph, encoding);
76+
if (limit == null) { return evalImpl(graph, predicate, NO_LIMIT);}
77+
final ImmutableList<Optional<Value>> evaluatedLimit = limit.eval(graph, encoding);
7478
if (evaluatedLimit.size != 1 || !evaluatedLimit.head.isPresent()) { throw new IllegalArgumentException("Limit must evaluate to a single non-empty value."); }
75-
return evalImpl(graph, evaluatedLimit.head.get().asNumeric().intValue());
79+
return evalImpl(graph, predicate, evaluatedLimit.head.get().asNumeric().intValue());
7680
}
7781

78-
private ImmutableList<Optional<Value>> evalImpl(final ParseGraph graph, final int limit) {
82+
private static ImmutableList<Optional<Value>> evalImpl(final ParseGraph graph, final Predicate<ParseValue> predicate, final int limit) {
7983
return wrap(getAllValues(graph, predicate, limit), new ImmutableList<Optional<Value>>()).computeResult();
8084
}
8185

core/src/main/java/io/parsingdata/metal/token/Token.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ public abstract class Token {
5858

5959
protected Token(final String name, final Encoding encoding) {
6060
this.name = checkNotNull(name, "name");
61-
this.encoding = encoding;
61+
this.encoding = checkNotNull(encoding, "encoding");
6262
}
6363

6464
public Optional<Environment> parse(final String scope, final Environment environment, final Encoding encoding) throws IOException {
65-
final Encoding activeEncoding = this.encoding != null ? this.encoding : encoding;
65+
final Encoding activeEncoding = this.encoding.isDefault() ? encoding : this.encoding;
6666
final Optional<Environment> result = parseImpl(makeScope(checkNotNull(scope, "scope")), checkNotNull(environment, "environment"), activeEncoding);
6767
environment.callbacks.handle(this, environment, result);
6868
return result;

core/src/main/java/io/parsingdata/metal/token/TokenRef.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
*/
4545
public class TokenRef extends Token {
4646

47-
private static final Token LOOKUP_FAILED = new Token("LOOKUP_FAILED", null) {
47+
private static final Token LOOKUP_FAILED = new Token("LOOKUP_FAILED", Encoding.DEFAULT) {
4848
@Override
4949
protected Optional<Environment> parseImpl(final String scope, final Environment environment, final Encoding encoding) throws IOException {
5050
return failure();

core/src/test/java/io/parsingdata/metal/ArgumentsTest.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.junit.Assert.fail;
2222

2323
import static io.parsingdata.metal.Shorthand.con;
24+
import static io.parsingdata.metal.encoding.Encoding.DEFAULT;
2425

2526
import java.io.IOException;
2627
import java.lang.reflect.Constructor;
@@ -43,6 +44,7 @@
4344
import io.parsingdata.metal.expression.logical.And;
4445
import io.parsingdata.metal.expression.logical.Not;
4546
import io.parsingdata.metal.expression.value.Cat;
47+
import io.parsingdata.metal.expression.value.Fold;
4648
import io.parsingdata.metal.expression.value.FoldLeft;
4749
import io.parsingdata.metal.expression.value.FoldRight;
4850
import io.parsingdata.metal.expression.value.ValueExpression;
@@ -73,7 +75,7 @@ public class ArgumentsTest {
7375
final private static ValueExpression VALID_VE = con(1);
7476
final private static BinaryOperator<ValueExpression> VALID_REDUCER = (left, right) -> null;
7577
final private static Expression VALID_E = new Expression() { @Override public boolean eval(final ParseGraph graph, final Encoding encoding) { return false; }};
76-
final private static Token VALID_T = new Token("", null) { @Override protected Optional<Environment> parseImpl(final String scope, final Environment environment, final Encoding encoding) throws IOException { return null; } };
78+
final private static Token VALID_T = new Token("", DEFAULT) { @Override protected Optional<Environment> parseImpl(final String scope, final Environment environment, final Encoding encoding) throws IOException { return null; } };
7779

7880
private final Class<?> _class;
7981
private final Object[] _arguments;
@@ -147,7 +149,13 @@ public ArgumentsTest(final Class<?> argumentsClass, final Object[] arguments) {
147149
@Test
148150
public void runConstructor() throws Throwable {
149151
final Constructor<?>[] constructors = _class.getConstructors();
150-
assertEquals(1, constructors.length);
152+
if (_class.equals(Eq.class) || _class.getSuperclass().equals(Fold.class)) {
153+
assertEquals(2, constructors.length);
154+
}
155+
else {
156+
assertEquals(1, constructors.length);
157+
}
158+
151159
try {
152160
constructors[0].newInstance(_arguments);
153161
fail("Should have thrown an IllegalArgumentException.");

core/src/test/java/io/parsingdata/metal/token/TokenTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class TokenTest {
1616

1717
@Rule
1818
public ExpectedException thrown = ExpectedException.none();
19-
private final Token token = new Token("", null) {
19+
private final Token token = new Token("", Encoding.DEFAULT) {
2020
@Override
2121
protected Optional<Environment> parseImpl(String scope, Environment environment, Encoding encoding) throws IOException {
2222
return null;

0 commit comments

Comments
 (0)