I wrote a small parser that is able to extract variables from an exp4j equation. So far, it is pretty durable. This is a much cleaner way of determining variables than via label, side-effect, and map analysis. However, this means that the by()-modulations are with respects to the order in which the variables are contained in the equation.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/624a8d70 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/624a8d70 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/624a8d70 Branch: refs/heads/TINKERPOP-1799 Commit: 624a8d706e150cc15dc2412d66d3ac9a61b90682 Parents: 6f1a1f7 Author: Marko A. Rodriguez <[email protected]> Authored: Wed Oct 4 10:27:48 2017 -0600 Committer: Marko A. Rodriguez <[email protected]> Committed: Wed Oct 4 10:27:48 2017 -0600 ---------------------------------------------------------------------- .../process/traversal/step/map/MathStep.java | 35 +++++++++++++++----- .../structure/TinkerGraphPlayTest.java | 2 +- 2 files changed, 27 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/624a8d70/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java index 645ea06..aec395c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java @@ -28,7 +28,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating; import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping; import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent; import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement; -import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing; import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; @@ -51,14 +50,7 @@ public final class MathStep<S> extends MapStep<S, Double> implements ByModulatin public MathStep(final Traversal.Admin traversal, final String equation) { super(traversal); this.equation = equation; - final Set<String> labels = TraversalHelper.getLabels(TraversalHelper.getRootTraversal(this.getTraversal())); - this.variables = new LinkedHashSet<>(); - for (final String label : labels) { - if (this.equation.contains(label)) - this.variables.add(label); - } - if (this.equation.contains(CURRENT)) - this.variables.add(CURRENT); + this.variables = MathStep.getVariables(this.equation); this.expression = new ExpressionBuilder(this.equation) .variables(this.variables) .build(); @@ -125,4 +117,29 @@ public final class MathStep<S> extends MapStep<S, Double> implements ByModulatin public Set<String> getScopeKeys() { return this.variables; } + + private static final Set<String> getVariables(final String equation) { + final StringBuilder builder = new StringBuilder(); + final char[] chars = equation.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if ('+' == chars[i] || '-' == chars[i] || '*' == chars[i] || + '/' == chars[i] || '^' == chars[i] || '%' == chars[i] || + '(' == chars[i] || ')' == chars[i]) + builder.append(" "); + else + builder.append(chars[i]); + } + final Set<String> variables = new LinkedHashSet<>(); + for (final String slot : builder.toString().split(" ")) { + if (!slot.trim().isEmpty() && !slot.equals("abs") && !slot.equals("acos") && + !slot.equals("asin") && !slot.equals("atan") && !slot.equals("cbrt") && + !slot.equals("ceil") && !slot.equals("cos") && !slot.equals("cosh") && + !slot.equals("exp") && !slot.equals("floor") && !slot.equals("log") && + !slot.equals("log10") && !slot.equals("log2") && !slot.equals("sin") && + !slot.equals("sinh") && !slot.equals("sqrt") && !slot.equals("tan") && + !slot.equals("tanh") && !slot.equals("signum")) + variables.add(slot); + } + return variables; + } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/624a8d70/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java index 0af81bd..b93f7ab 100644 --- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java @@ -71,7 +71,7 @@ public class TinkerGraphPlayTest { public void testPlay8() throws Exception { Graph graph = TinkerFactory.createModern(); GraphTraversalSource g = graph.traversal(); - System.out.println(g.V().as("a").out("knows").math("((a ^ _) / a)").by("age").by(bothE().count()).toList()); + System.out.println(g.withSideEffect("x",10.1d).V().as("a").out("knows").math("((a ^ _) / a) + x").by("age").by(bothE().count()).by().toList()); } @Test
