-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Current iteration #242
Current iteration #242
Changes from 15 commits
e725c68
e6b2f37
0e12551
dac4afb
b449cff
a294916
ec291c2
c3c961e
cab9c3e
3450821
0d2401b
ad98634
f8f5034
a17967c
b2961aa
6fa43c5
ebfcf71
6b72849
fe71ac2
8f9d2c3
97a66c5
5442e7a
93716c3
fd803d8
c63f84c
840c354
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright 2013-2016 Netherlands Forensic Institute | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
jvdb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
package io.parsingdata.metal.expression.value.reference; | ||
|
||
import static java.math.BigInteger.ONE; | ||
import static java.math.BigInteger.ZERO; | ||
|
||
import static io.parsingdata.metal.Trampoline.complete; | ||
import static io.parsingdata.metal.Trampoline.intermediate; | ||
import static io.parsingdata.metal.expression.value.ConstantFactory.createFromNumeric; | ||
|
||
import java.math.BigInteger; | ||
import java.util.Optional; | ||
|
||
import io.parsingdata.metal.Trampoline; | ||
import io.parsingdata.metal.Util; | ||
import io.parsingdata.metal.data.ImmutableList; | ||
import io.parsingdata.metal.data.ParseGraph; | ||
import io.parsingdata.metal.data.ParseItem; | ||
import io.parsingdata.metal.data.ParseState; | ||
import io.parsingdata.metal.encoding.Encoding; | ||
import io.parsingdata.metal.expression.value.Value; | ||
import io.parsingdata.metal.expression.value.ValueExpression; | ||
|
||
/** | ||
* A {@link ValueExpression} that represents the current iteration in an | ||
* iterable {@link io.parsingdata.metal.token.Token} (e.g. when inside a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps import the class names? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
* {@link io.parsingdata.metal.token.Rep} or | ||
* {@link io.parsingdata.metal.token.RepN}). | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps also mention it can be checked if a Token is iterable, using a method reference link? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. |
||
public class CurrentIteration implements ValueExpression { | ||
|
||
@Override | ||
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) { | ||
final ParseGraph currentIterable = findCurrentIterable(parseState.order, ParseGraph.EMPTY).computeResult(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool way to calculate the iteration by the way 😄 |
||
if (currentIterable.isEmpty()) { return ImmutableList.create(Optional.empty()); } | ||
|
||
final BigInteger currentIteration = countIterable(currentIterable, ZERO).computeResult(); | ||
return ImmutableList.create(Optional.of(createFromNumeric(currentIteration, new Encoding()))); | ||
} | ||
|
||
private Trampoline<ParseGraph> findCurrentIterable(final ParseItem item, final ParseGraph iterableCandidate) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would really like some inline comments or javadoc stating what these things do 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not applicable anymore. ;) These methods are removed, because of the new implementation. |
||
if (!item.isGraph()) { return complete(() -> iterableCandidate); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would happen if I would do something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you mean infinite loop, no, but there will be a null pointer exception, because the head becomes null. Nice catch! Will add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see your point now. Because a def of size 0 is not added to the parseGraph. However, then the iterable is in fact empty, which will return an empty value and the parsing will fail, see line 50. So it will not blow up. It is a nice discussion though what you would expect to be "an iteration". Should a parsing attempt, where eventually 0 bytes are parsed, be considered an iteration? Also, would we expect There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, if I read the code as is, I think your first comment does happen (I indeed meant something like a NPE)? Because there is no value yet when you eval CURRENT_ITERATION, and the only way the recursion stops is if it encounters a value? Could you add these samples as a test? As to the discussion, I would probably expect your example to work, because we are in fact in an iteration? I also think conceptually a 0 bytes parsed should still be considered an iteration, as I feel it is the iteration that happens, not what happens inside the iteration (wow, confusing sentence 😄). What would be the downsides of this, or what problems would it pose? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I implemented CURRENT_INDEX differently. Instead of extracting it from ParseGraph, it is kept in the ParseState. I added tests for examples similar to I will need to improve the code a little before I commit. |
||
if (item.getDefinition().isIterable()) { | ||
return intermediate(() -> findCurrentIterable(item.asGraph().head, item.asGraph())); | ||
} | ||
return intermediate(() -> findCurrentIterable(item.asGraph().head, iterableCandidate)); | ||
} | ||
|
||
private Trampoline<BigInteger> countIterable(final ParseGraph graph, final BigInteger count) { | ||
if (!graph.isEmpty()) { return intermediate(() -> countIterable(graph.tail, count.add(ONE))); } | ||
return complete(() -> count.subtract(ONE)); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return getClass().getSimpleName(); | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object obj) { | ||
return Util.notNullAndSameClass(this, obj); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return getClass().hashCode(); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright 2013-2016 Netherlands Forensic Institute | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.parsingdata.metal.expression.value.reference; | ||
|
||
import static io.parsingdata.metal.Shorthand.CURRENT_ITERATION; | ||
import static io.parsingdata.metal.Shorthand.con; | ||
import static io.parsingdata.metal.Shorthand.def; | ||
import static io.parsingdata.metal.Shorthand.eq; | ||
import static io.parsingdata.metal.Shorthand.not; | ||
import static io.parsingdata.metal.Shorthand.rep; | ||
import static io.parsingdata.metal.Shorthand.repn; | ||
import static io.parsingdata.metal.Shorthand.seq; | ||
import static io.parsingdata.metal.Shorthand.whl; | ||
import static io.parsingdata.metal.util.EncodingFactory.enc; | ||
import static io.parsingdata.metal.util.ParseStateFactory.stream; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
|
||
import org.junit.runners.Parameterized; | ||
|
||
import io.parsingdata.metal.token.Token; | ||
import io.parsingdata.metal.util.ParameterizedParse; | ||
|
||
public class CurrentIterationTest extends ParameterizedParse { | ||
|
||
public static final Token VALUE_EQ_ITERATION = def("value", con(1), eq(CURRENT_ITERATION)); | ||
public static final Token VALUE_NOT_EQ_ITERATION = def("value", con(1), not(eq(CURRENT_ITERATION))); | ||
public static final Token VALUE_EQ_255 = def("value", con(1), eq(con(255))); | ||
|
||
@Parameterized.Parameters(name="{0} ({4})") | ||
public static Collection<Object[]> data() { | ||
return Arrays.asList(new Object[][] { | ||
{ "[0, 1, 2, 3, 255] rep(CURRENT_ITERATION), def(255)", seq(rep(VALUE_EQ_ITERATION), VALUE_EQ_255), stream(0, 1, 2, 3, 255), enc(), true }, | ||
{ "[0, 1, 2, 3] repn=4(CURRENT_ITERATION)", repn(VALUE_EQ_ITERATION, con(4)), stream(0, 1, 2, 3), enc(), true }, | ||
{ "[255, 0, 1, 2, 3, 255] def(255), while<3(CURRENT_ITERATION), def (255)", seq(VALUE_EQ_255, whl(VALUE_EQ_ITERATION, not(eq(con(3)))), VALUE_EQ_255), stream(255, 0, 1, 2, 3, 255), enc(), true }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick: the description of the test should actually be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, correct. I will adjust it. |
||
{ "[0, 0, 1, 2, 1, 0, 1, 2] repn=2(CURRENT_ITERATION, repn=3(CURRENT_ITERATION))", repn(seq(VALUE_EQ_ITERATION, repn(VALUE_EQ_ITERATION, con(3))), con(2)), stream(0, 0, 1, 2, 1, 0, 1, 2), enc(), true }, | ||
{ "[0, 1] seq(CURRENT_ITERATION, ...)", seq(VALUE_EQ_ITERATION, VALUE_EQ_ITERATION), stream(0, 1), enc(), false }, | ||
{ "[0] CURRENT_ITERATION", VALUE_EQ_ITERATION, stream(0), enc(), false }, | ||
{ "[0, 1] seq(!CURRENT_ITERATION, ...)", seq(VALUE_NOT_EQ_ITERATION, VALUE_NOT_EQ_ITERATION), stream(0, 1), enc(), true }, | ||
{ "[0] !CURRENT_ITERATION", VALUE_NOT_EQ_ITERATION, stream(0), enc(), true } | ||
}); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2018?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.