You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by jo...@apache.org on 2017/11/23 08:16:07 UTC

[32/50] tinkerpop git commit: Traversal parser for tests

Traversal parser for tests


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/5dd3d6c8
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5dd3d6c8
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5dd3d6c8

Branch: refs/heads/TINKERPOP-1827
Commit: 5dd3d6c84dd95f2fa8569a80c2094e7a2f91bec4
Parents: 458b58d
Author: Jorge Bay Gondra <jo...@gmail.com>
Authored: Thu Oct 26 13:06:04 2017 +0200
Committer: Jorge Bay Gondra <jo...@gmail.com>
Committed: Thu Nov 23 09:08:06 2017 +0100

----------------------------------------------------------------------
 .../Gherkin/CommonSteps.cs                      |  13 +-
 .../Gherkin/GherkinTestRunner.cs                |  45 +++-
 .../TraversalEvaluation/ITokenParameter.cs      |  30 +++
 .../TraversalEvaluation/NumericParameter.cs     |  68 +++++
 .../StaticTraversalParameter.cs                 |  57 ++++
 .../TraversalEvaluation/StringParameter.cs      |  69 +++++
 .../Gherkin/TraversalEvaluation/Token.cs        |  76 ++++++
 .../TraversalEvaluationTests.cs                 |  79 ++++++
 .../TraversalEvaluation/TraversalParser.cs      | 261 +++++++++++++++++++
 .../TraversalPredicateParameter.cs              |  60 +++++
 .../TraversalTokenParameter.cs                  |  60 +++++
 .../Gherkin/TraversalTranslations.cs            | 102 --------
 12 files changed, 810 insertions(+), 110 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 50ea9b8..16aef9d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -29,6 +29,7 @@ using System.Net.Http.Headers;
 using System.Runtime.CompilerServices;
 using Gherkin.Ast;
 using Gremlin.Net.IntegrationTest.Gherkin.Attributes;
+using Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Structure;
 using Newtonsoft.Json;
@@ -67,6 +68,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
             _result = enumerable.Cast<object>().ToArray();
         }
 
+        [When("iterated next")]
+        public void IterateNext()
+        {
+            if (!(_traversal is ITraversal))
+            {
+                throw new InvalidOperationException("Traversal should be set before iterating");
+            }
+            _result = _traversal.Next();
+        }
+
         [Given("the traversal of")]
         public void TranslateTraversal(string traversalText)
         {
@@ -74,7 +85,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
             {
                 throw new InvalidOperationException("g should be a traversal source");
             }
-            _traversal = TraversalTranslations.GetTraversal(traversalText, _g);
+            _traversal = TraversalParser.GetTraversal(traversalText, _g);
         }
 
         [Then("the result should be (\\w+)")]

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index e1df3a8..7523b0b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Reflection;
 using System.Text.RegularExpressions;
@@ -146,8 +147,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                     WriteOutput($"  Scenario: {resultScenario.Key.Name}");
                     foreach (var step in resultScenario.Key.Steps)
                     {
-                        Exception failure;
-                        resultScenario.Value.TryGetValue(step, out failure);
+                        resultScenario.Value.TryGetValue(step, out var failure);
                         if (failure == null)
                         {
                             WriteOutput($"    {step.Keyword} {step.Text}");
@@ -295,11 +295,42 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
 
         private IEnumerable<Feature> GetFeatures()
         {
-            // TODO: go through all the .feature files
-            const string gherkinFile = "/Users/jorge/workspace/temp/count.feature";
-            var parser = new Parser();
-            var doc = parser.Parse(gherkinFile);
-            yield return doc.Feature;
+            var rootPath = GetRootPath();
+            var path = Path.Combine(rootPath, "gremlin-test", "features");
+            WriteOutput(path);
+            WriteOutput("------");
+
+            var files = new [] {"/Users/jorge/workspace/temp/count.feature"};
+            //var files = Directory.GetFiles(path, "*.feature", SearchOption.AllDirectories);
+            foreach (var gherkinFile in files)
+            {
+                var parser = new Parser();
+                WriteOutput("Parsing " + gherkinFile);
+                var doc = parser.Parse(gherkinFile);
+                yield return doc.Feature;   
+            }
+        }
+
+        private string GetRootPath()
+        {
+            var codeBaseUrl = new Uri(GetType().GetTypeInfo().Assembly.CodeBase);
+            var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
+            DirectoryInfo rootDir = null;
+            for (var dir = Directory.GetParent(Path.GetDirectoryName(codeBasePath));
+                dir.Parent != null;
+                dir = dir.Parent)
+            {
+                if (dir.Name == "gremlin-dotnet" && dir.Parent?.Name == "tinkerpop")
+                {
+                    rootDir = dir.Parent;
+                    break;
+                }   
+            }
+            if (rootDir == null)
+            {
+                throw new FileNotFoundException("tinkerpop root not found in path");
+            }
+            return rootDir.FullName;
         }
 
         private void PrintGherkin()

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
new file mode 100644
index 0000000..1c940db
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
@@ -0,0 +1,30 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    public interface ITokenParameter
+    {
+        
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
new file mode 100644
index 0000000..9effc17
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
@@ -0,0 +1,68 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    public class NumericParameter<T> : ITokenParameter, IEquatable<NumericParameter<T>> where T : struct
+    {
+        public bool Equals(NumericParameter<T> other)
+        {
+            return Value.Equals(other.Value);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((NumericParameter<T>) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Value.GetHashCode();
+        }
+
+        public T Value { get; }
+        
+        public NumericParameter(T value)
+        {
+            Value = value;
+        }
+
+        public override string ToString()
+        {
+            return $"NumericParameter<{typeof(T).Name}>({Value})";
+        }
+    }
+
+    internal static class NumericParameter
+    {
+        public static NumericParameter<TType> Create<TType>(TType value) where TType : struct
+        {
+            return new NumericParameter<TType>(value);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
new file mode 100644
index 0000000..b054cbc
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
@@ -0,0 +1,57 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    internal class StaticTraversalParameter : ITokenParameter, IEquatable<StaticTraversalParameter>
+    {
+        public bool Equals(StaticTraversalParameter other)
+        {
+            return Parts.SequenceEqual(other.Parts);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((StaticTraversalParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Parts != null ? Parts.GetHashCode() : 0;
+        }
+
+        public IList<Token> Parts { get; }
+        
+        public StaticTraversalParameter(IList<Token> parts)
+        {
+            Parts = parts;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
new file mode 100644
index 0000000..ad182b5
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
@@ -0,0 +1,69 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    internal class StringParameter : ITokenParameter, IEquatable<StringParameter>
+    {
+        public bool Equals(StringParameter other)
+        {
+            return string.Equals(Value, other.Value);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((StringParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return (Value != null ? Value.GetHashCode() : 0);
+        }
+
+        public string Value { get; }
+
+        public StringParameter(string value)
+        {
+            Value = value;
+        }
+
+        public static StringParameter Parse(string text, ref int i)
+        {
+            i++;
+            var endIndex = text.IndexOf('"', i);
+            var result = new StringParameter(text.Substring(i, endIndex - i));
+            i = endIndex;
+            return result;
+        }
+
+        public override string ToString()
+        {
+            return $"{GetType().Name}({Value})";
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
new file mode 100644
index 0000000..633e2b5
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
@@ -0,0 +1,76 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    internal class Token : IEquatable<Token>
+    {
+        private static readonly IList<ITokenParameter> EmptyParameters = new ITokenParameter[0];
+        
+        public bool Equals(Token other)
+        {
+            if (!string.Equals(Name, other.Name))
+            {
+                return false;
+            }
+            return  (Parameters ?? EmptyParameters).SequenceEqual(other.Parameters ?? EmptyParameters);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((Token) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                return ((Name != null ? Name.GetHashCode() : 0) * 397) ^
+                       (Parameters != null ? Parameters.GetHashCode() : 0);
+            }
+        }
+
+        public string Name { get; }
+
+        public ICollection<ITokenParameter> Parameters { get; }
+            
+        public Token(string name, ICollection<ITokenParameter> parameters = null)
+        {
+            Name = name;
+            Parameters = parameters;
+        }
+            
+        public Token(string name, ITokenParameter parameter)
+        {
+            Name = name;
+            Parameters = new[] {parameter};
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
new file mode 100644
index 0000000..ea65cd2
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
@@ -0,0 +1,79 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Xunit;
+using Xunit.Abstractions;
+using Xunit.Sdk;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    public class TraversalEvaluationTests
+    {
+        private readonly ITestOutputHelper _output;
+
+        public TraversalEvaluationTests(ITestOutputHelper output)
+        {
+            _output = output;
+        }
+        
+        [Fact]
+        public void Traversal_Parser_Should_Parse_Parts()
+        {
+            var items = new[]
+            {
+                Tuple.Create("g.V().count()", new[] {new Token("count")}),
+                Tuple.Create("g.V().values(\"name\")",
+                    new[] {new Token("values", new StringParameter("name"))}),
+                Tuple.Create("g.V().constant(123l)", 
+                    new[] {new Token("constant", new[] {NumericParameter.Create(123L)})}),
+                Tuple.Create("g.V().has(\"no\").count()",
+                    new[] {new Token("has", new StringParameter("no")), new Token("count")}),
+                Tuple.Create("g.V().has(\"lang\", \"java\")",
+                    new[] {new Token("has", new[] {new StringParameter("lang"), new StringParameter("java")})}),
+                Tuple.Create("g.V().where(__.in(\"knows\"))",
+                    new[] {new Token("where", new[] {new StaticTraversalParameter(
+                        new[] {new Token("__"), new Token("in", new StringParameter("knows"))})})}),
+                Tuple.Create("g.V().has(\"age\", P.gt(27)", 
+                    new[] {new Token("has", new ITokenParameter[] { new StringParameter("age"),
+                        new TraversalPredicateParameter(
+                            new[] { new Token("P"), new Token("gt", NumericParameter.Create(27)) }) })})
+            };
+            foreach (var item in items)
+            {
+                var parts = TraversalParser.ParseParts(item.Item1);
+                _output.WriteLine("Parsing " + item.Item1);
+                if (parts[parts.Count-1].Parameters != null)
+                {
+                    _output.WriteLine("{0}", parts[parts.Count-1].Parameters.Count);
+                    _output.WriteLine("Values: " +
+                                      string.Join(", ", parts[parts.Count - 1].Parameters.Select(p => p.ToString())));
+                }
+                Assert.Equal(new[] {new Token("g"), new Token("V")}.Concat(item.Item2), parts);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
new file mode 100644
index 0000000..0ac97ff
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -0,0 +1,261 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using Gremlin.Net.Process.Traversal;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    public class TraversalParser
+    {
+        private static readonly IDictionary<string, Func<GraphTraversalSource, ITraversal>> FixedTranslations = 
+            new Dictionary<string, Func<GraphTraversalSource, ITraversal>>
+            {
+                { "g.V().has(\"no\").count()", g => g.V().Has("no").Count() },
+                { "g.V().fold().count(Scope.local)", g => g.V().Fold<object>().Count(Scope.Local)}
+            };
+        
+        private static readonly Regex RegexInteger = new Regex(@"\d+", RegexOptions.Compiled);
+        private static readonly Regex RegexDouble = new Regex(@"\d+\.\d+", RegexOptions.Compiled);
+        private static readonly Regex RegexFloat =
+            new Regex(@"\d+\.\d+f", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+        private static readonly Regex RegexLong = new Regex(@"\d+l", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+        internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g)
+        {
+            Func<GraphTraversalSource, ITraversal> traversalBuilder;
+            if (!FixedTranslations.TryGetValue(traversalText, out traversalBuilder))
+            {
+                return BuildFromMethods(traversalText, g);
+            }
+            return traversalBuilder(g);
+        }
+
+        private static ITraversal BuildFromMethods(string traversalText, GraphTraversalSource g)
+        {
+            var parts = traversalText.Split('.');
+            if (parts[0] != "g")
+            {
+                throw BuildException(traversalText);
+            }
+            ITraversal traversal;
+            switch (parts[1])
+            {
+                case "V()":
+                    traversal = g.V();
+                    break;
+                case "E()":
+                    traversal = g.E();
+                    break;
+                default:
+                    throw BuildException(traversalText);
+            }
+            for (var i = 2; i < parts.Length; i++)
+            {
+                var name = GetCsharpName(parts[i], traversalText);
+                var method = traversal.GetType().GetMethod(name);
+                if (method == null)
+                {
+                    throw new InvalidOperationException($"Traversal method '{parts[i]}' not found for testing");
+                }
+                if (method.IsGenericMethod)
+                {
+                    throw new InvalidOperationException(
+                        $"Can not build traversal to test as '{name}()' method is generic");
+                }
+                traversal = (ITraversal) method.Invoke(traversal, new object[] { new object[0]});
+            }
+            return traversal;
+        }
+
+        private static string GetCsharpName(string part, string traversalText)
+        {
+            if (!part.EndsWith("()"))
+            {
+                throw BuildException(traversalText);
+            }
+            // Transform to PascalCasing and remove the parenthesis
+            return char.ToUpper(part[0]) + part.Substring(1, part.Length - 3);
+        }
+
+        private static Exception BuildException(string traversalText)
+        {
+            return new InvalidOperationException($"Can not build a traversal to test from '{traversalText}'");
+        }
+
+        internal static IList<Token> ParseParts(string traversalText)
+        {
+            var index = 0;
+            return ParseTokens(traversalText, ref index);
+        }
+
+        private static IList<Token> ParseTokens(string text, ref int i)
+        {
+            var result = new List<Token>();
+            var startIndex = i;
+            var parsing = ParsingPart.Name;
+            string name = null;
+            var parameters = new List<ITokenParameter>();
+            while (i < text.Length)
+            {
+                switch (text[i])
+                {
+                    case '.':
+                        if (name == null)
+                        {
+                            name = text.Substring(startIndex, i - startIndex);
+                        }
+                        startIndex = i + 1;
+                        result.Add(new Token(name, parameters));
+                        name = null;
+                        parameters = new List<ITokenParameter>();
+                        parsing = ParsingPart.Name;
+                        break;
+                    case '(':
+                    {
+                        name = text.Substring(startIndex, i - startIndex);
+                        i++;
+                        parsing = ParsingPart.StartParameters;
+                        var param = ParseParameter(text, ref i);
+                        if (param == null)
+                        {
+                            parsing = ParsingPart.EndParameters;
+                        }
+                        else
+                        {
+                            parameters.Add(param);
+                        }
+                        break;
+                    }
+                    case ',' when text[i+1] != ' ':
+                    case ' ' when text[i+1] != ' ':
+                    {
+                        if (parsing != ParsingPart.StartParameters)
+                        {
+                            throw new InvalidOperationException(
+                                "Can not parse space or comma chars outside parameters");
+                        }
+                        i++;
+                        var param = ParseParameter(text, ref i);
+                        if (param == null)
+                        {
+                            parsing = ParsingPart.EndParameters;
+                        }
+                        else
+                        {
+                            parameters.Add(param);
+                        }
+                        break;
+                    }
+                    case ')' when parsing != ParsingPart.StartParameters:
+                        // The traversal already ended
+                        i--;
+                        if (name != null)
+                        {
+                            result.Add(new Token(name, parameters));
+                        }
+                        return result;
+                    case ')':
+                        parsing = ParsingPart.EndParameters;
+                        break;
+                }
+                i++;
+            }
+            if (name != null)
+            {
+                result.Add(new Token(name, parameters));
+            }
+            return result;
+        }
+
+        private static ITokenParameter ParseParameter(string text, ref int i)
+        {
+            var firstChar = text[i];
+            if (firstChar == ')')
+            {
+                return null;
+            }
+            if (firstChar == '"')
+            {
+                return StringParameter.Parse(text, ref i);
+            }
+            if (char.IsDigit(firstChar))
+            {
+                return ParseNumber(text, ref i);
+            }
+            if (text.Substring(i, 3).StartsWith("__."))
+            {
+                return new StaticTraversalParameter(ParseTokens(text, ref i));
+            }
+            if (text.Substring(i, 2).StartsWith("T."))
+            {
+                return new TraversalTokenParameter(ParseTokens(text, ref i));
+            }
+            if (text.Substring(i, 2).StartsWith("P."))
+            {
+                return new TraversalPredicateParameter(ParseTokens(text, ref i));
+            }
+            return null;
+        }
+        
+        private static ITokenParameter ParseNumber(string text, ref int i)
+        {
+            var match = RegexLong.Match(text.Substring(i));
+            if (match.Success)
+            {
+                i += match.Value.Length - 1;
+                return NumericParameter.Create(Convert.ToInt64(match.Value.Substring(0, match.Value.Length-1)));
+            }
+            match = RegexFloat.Match(text.Substring(i));
+            if (match.Success)
+            {
+                i += match.Value.Length - 1;
+                return NumericParameter.Create(Convert.ToSingle(match.Value.Substring(0, match.Value.Length-1)));
+            }
+            match = RegexDouble.Match(text.Substring(i));
+            if (match.Success)
+            {
+                i += match.Value.Length;
+                return NumericParameter.Create(Convert.ToSingle(match.Value));
+            }
+            match = RegexInteger.Match(text.Substring(i));
+            if (!match.Success)
+            {
+                throw new InvalidOperationException(
+                    $"Could not parse numeric value from the beginning of {text.Substring(i)}");
+            }
+            i += match.Value.Length;
+            return NumericParameter.Create(Convert.ToInt32(match.Value));
+        }
+        
+        private enum ParsingPart
+        {
+            Name,
+            StartParameters,
+            EndParameters
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
new file mode 100644
index 0000000..d9bf061
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
@@ -0,0 +1,60 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for a traversal predicate (ie: P.gt())
+    /// </summary>
+    internal class TraversalPredicateParameter : ITokenParameter, IEquatable<TraversalPredicateParameter>
+    {
+        public bool Equals(TraversalPredicateParameter other)
+        {
+            return Parts.SequenceEqual(other.Parts);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((TraversalPredicateParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Parts != null ? Parts.GetHashCode() : 0;
+        }
+
+        public IList<Token> Parts { get; }
+        
+        public TraversalPredicateParameter(IList<Token> parts)
+        {
+            Parts = parts;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
new file mode 100644
index 0000000..5a5e8c1
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
@@ -0,0 +1,60 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for a traversal token (ie: T.label)
+    /// </summary>
+    internal class TraversalTokenParameter : ITokenParameter, IEquatable<TraversalTokenParameter>
+    {
+        public bool Equals(TraversalTokenParameter other)
+        {
+            return Parts.SequenceEqual(other.Parts);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != GetType()) return false;
+            return Equals((TraversalTokenParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Parts != null ? Parts.GetHashCode() : 0;
+        }
+
+        public IList<Token> Parts { get; }
+        
+        public TraversalTokenParameter(IList<Token> parts)
+        {
+            Parts = parts;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5dd3d6c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs
deleted file mode 100644
index af02b8c..0000000
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalTranslations.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-#region License
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-#endregion
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using Gremlin.Net.Process.Traversal;
-
-namespace Gremlin.Net.IntegrationTest.Gherkin
-{
-    internal class TraversalTranslations
-    {
-        private static readonly IDictionary<string, Func<GraphTraversalSource, ITraversal>> FixedTranslations = 
-            new Dictionary<string, Func<GraphTraversalSource, ITraversal>>
-            {
-                { "g.V().has(\"no\").count()", g => g.V().Has("no").Count() },
-                { "g.V().fold().count(Scope.local)", g => g.V().Fold<object>().Count(Scope.Local)}
-            };
-
-        internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g)
-        {
-            Func<GraphTraversalSource, ITraversal> traversalBuilder;
-            if (!FixedTranslations.TryGetValue(traversalText, out traversalBuilder))
-            {
-                return BuildFromMethods(traversalText, g);
-            }
-            return traversalBuilder(g);
-        }
-
-        private static ITraversal BuildFromMethods(string traversalText, GraphTraversalSource g)
-        {
-            var parts = traversalText.Split('.');
-            if (parts[0] != "g")
-            {
-                throw BuildException(traversalText);
-            }
-            ITraversal traversal;
-            switch (parts[1])
-            {
-                case "V()":
-                    traversal = g.V();
-                    break;
-                case "E()":
-                    traversal = g.E();
-                    break;
-                default:
-                    throw BuildException(traversalText);
-            }
-            for (var i = 2; i < parts.Length; i++)
-            {
-                var name = GetCsharpName(parts[i], traversalText);
-                var method = traversal.GetType().GetMethod(name);
-                if (method == null)
-                {
-                    throw new InvalidOperationException($"Traversal method '{parts[i]}' not found for testing");
-                }
-                if (method.IsGenericMethod)
-                {
-                    throw new InvalidOperationException(
-                        $"Can not build traversal to test as '{name}()' method is generic");
-                }
-                traversal = (ITraversal) method.Invoke(traversal, new object[] { new object[0]});
-            }
-            return traversal;
-        }
-
-        private static string GetCsharpName(string part, string traversalText)
-        {
-            if (!part.EndsWith("()"))
-            {
-                throw BuildException(traversalText);
-            }
-            // Transform to PascalCasing and remove the parenthesis
-            return char.ToUpper(part[0]) + part.Substring(1, part.Length - 3);
-        }
-
-        private static Exception BuildException(string traversalText)
-        {
-            return new InvalidOperationException($"Can not build a traversal to test from '{traversalText}'");
-        }
-    }
-}
\ No newline at end of file