This is an automated email from the ASF dual-hosted git repository.

jin pushed a commit to branch text2gql
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph-ai.git

commit d901c1ab4e9d9ada79d075c7405096d23fcdd1a9
Author: Lriver <[email protected]>
AuthorDate: Tue Sep 30 21:05:12 2025 +0800

    feat: add ANTLR syntax tree visitor with Gremlin query to Recipe parsing 
and call/with support
---
 .../AST_Text2Gremlin/base/GremlinTransVisitor.py   | 1390 ++++++++++++++++++++
 1 file changed, 1390 insertions(+)

diff --git a/text2gremlin/AST_Text2Gremlin/base/GremlinTransVisitor.py 
b/text2gremlin/AST_Text2Gremlin/base/GremlinTransVisitor.py
new file mode 100644
index 00000000..c6cf3548
--- /dev/null
+++ b/text2gremlin/AST_Text2Gremlin/base/GremlinTransVisitor.py
@@ -0,0 +1,1390 @@
+
+"""
+Gremlin查询AST访问器模块。
+
+基于ANTLR访问器模式,将Gremlin查询字符串解析为结构化的配方对象。
+"""
+
+import re
+from antlr4 import *
+from antlr4.InputStream import InputStream
+from antlr4.CommonTokenStream import CommonTokenStream
+from antlr4.tree.Tree import TerminalNode
+
+from gremlin.GremlinLexer import GremlinLexer
+from gremlin.GremlinParser import GremlinParser
+from gremlin.GremlinVisitor import GremlinVisitor
+
+from GremlinParse import Traversal, Step
+from GremlinExpr import Predicate, TextPredicate, AnonymousTraversal, 
Connector, Terminal
+
+class GremlinTransVisitor(GremlinVisitor):
+    def __init__(self):
+        super().__init__()
+        self.traversal = Traversal()
+    def parse_and_visit(self, query_string: str):
+        """
+        解析 Gremlin 查询字符串并遍历 AST 以生成 Traversal 对象。
+        
+        Args:
+            query_string (str): 要解析的 Gremlin 查询字符串
+            
+        Returns:
+            Traversal: 包含步骤的解析后遍历对象
+        """
+        try:
+            # 重置traversal进行新的查询
+            self.traversal = Traversal()
+            
+            input_stream = InputStream(query_string)
+            lexer = GremlinLexer(input_stream)
+            stream = CommonTokenStream(lexer)
+            parser = GremlinParser(stream)
+            # 【修正】使用queryList作为入口规则,它包含一个或多个query
+            tree = parser.queryList()
+            
+            # Visit the parse tree - 访问第一个query
+            result = self.visit(tree.query(0))
+            
+            return result if result else self.traversal
+            
+        except Exception as e:
+            print(f"Error parsing query '{query_string}': {e}")
+            return None
+
+    # 核心结构访问器,控制流程
+    def visitQueryList(self, ctx: GremlinParser.QueryListContext):
+        """处理查询列表,通常包含一个查询"""
+        if ctx.query(0):  # 访问第一个查询
+            return self.visit(ctx.query(0))
+        return self.traversal
+    
+    def visitQuery(self, ctx: GremlinParser.QueryContext):
+        # 访问根遍历部分
+        if ctx.rootTraversal():
+            self.visit(ctx.rootTraversal())
+        # 如果有嵌套查询,递归访问
+        if ctx.query():
+            self.visit(ctx.query())
+        return self.traversal
+
+    def visitRootTraversal(self, ctx: GremlinParser.RootTraversalContext):
+        # 访问起始步骤,例如 g.V() 或 g.addV()
+        if ctx.traversalSourceSpawnMethod():
+            self.visit(ctx.traversalSourceSpawnMethod())
+        
+        # 如果后面跟着链式调用,访问它们
+        if ctx.chainedTraversal():
+            self.visit(ctx.chainedTraversal())
+
+    def visitChainedTraversal(self, ctx: 
GremlinParser.ChainedTraversalContext):
+        # 对于 a.b.c 这样的链,递归访问 a,然后访问 b
+        if ctx.chainedTraversal():
+            self.visit(ctx.chainedTraversal())
+        if ctx.traversalMethod():
+            self.visit(ctx.traversalMethod())
+            
+    # 动作类访问器 (添加 Step)
+    def visitTraversalSourceSpawnMethod_V(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_VContext):
+        params = self.visit(ctx.genericArgumentVarargs()) if 
ctx.genericArgumentVarargs() else []
+        self.traversal.add_step(Step('V', params))
+
+    def visitTraversalSourceSpawnMethod_addV(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_addVContext):
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        self.traversal.add_step(Step('addV', params))
+
+    def visitTraversalMethod_out(self, ctx: 
GremlinParser.TraversalMethod_outContext):
+        params = []
+        varargs_ctx = ctx.stringNullableArgumentVarargs()
+        if varargs_ctx:
+            result = self.visit(varargs_ctx)
+            if result is not None:
+                params = result
+        self.traversal.add_step(Step('out', params))
+
+    def visitTraversalMethod_limit_long(self, ctx: 
GremlinParser.TraversalMethod_limit_longContext):
+        limit_val = self.visit(ctx.integerArgument())
+        self.traversal.add_step(Step('limit', [limit_val]))
+
+    def visitTraversalMethod_has_String_Object(self, ctx):
+        key = self.visit(ctx.stringNullableLiteral())
+        value = self.visit(ctx.genericArgument())
+        self.traversal.add_step(Step('has', [key, value]))
+
+    def visitTraversalMethod_has_String_P(self, ctx):
+        key = self.visit(ctx.stringNullableLiteral())
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('has', [key, predicate]))
+
+    def visitTraversalMethod_has_String_String_Object(self, ctx):
+        label = self.visit(ctx.stringNullableArgument())
+        key = self.visit(ctx.stringNullableLiteral())
+        value = self.visit(ctx.genericArgument())
+        self.traversal.add_step(Step('has', [label, key, value]))
+
+    def visitTraversalMethod_has_String(self, ctx):
+        key = self.visit(ctx.stringNullableLiteral())
+        self.traversal.add_step(Step('has', [key]))
+
+    def visitTraversalMethod_has_String_String_P(self, ctx):
+        label = self.visit(ctx.stringNullableArgument())
+        key = self.visit(ctx.stringNullableLiteral())
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('has', [label, key, predicate]))
+
+    def visitTraversalMethod_has_String_Traversal(self, ctx):
+        key = self.visit(ctx.stringNullableLiteral())
+        traversal = self.visit(ctx.nestedTraversal())
+        self.traversal.add_step(Step('has', [key, traversal]))
+
+    def visitTraversalMethod_has_T_Object(self, ctx):
+        t_value = self.visit(ctx.traversalT())
+        obj_value = self.visit(ctx.genericArgument())
+        self.traversal.add_step(Step('has', [t_value, obj_value]))
+
+    def visitTraversalMethod_has_T_P(self, ctx):
+        t_value = self.visit(ctx.traversalT())
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('has', [t_value, predicate]))
+
+    def visitTraversalMethod_has_T_Traversal(self, ctx):
+        t_value = self.visit(ctx.traversalT())
+        traversal = self.visit(ctx.nestedTraversal())
+        self.traversal.add_step(Step('has', [t_value, traversal]))
+        
+    def visitTraversalMethod_property_Object_Object_Object(self, ctx):
+        params = []
+        if ctx.genericArgument(0): 
params.append(self.visit(ctx.genericArgument(0)))
+        if ctx.genericArgument(1): 
params.append(self.visit(ctx.genericArgument(1)))
+        self.traversal.add_step(Step('property', params))
+
+    def visitTraversalMethod_values(self, ctx: 
GremlinParser.TraversalMethod_valuesContext):
+        params = self.visit(ctx.stringNullableLiteralVarargs()) if 
ctx.stringNullableLiteralVarargs() else []
+        self.traversal.add_step(Step('values', params))
+        
+    # 值提取访问器 (返回Python值)
+    def visitStringLiteral(self, ctx: GremlinParser.StringLiteralContext) -> 
str:
+        return ctx.getText().strip("'\"")
+
+    def visitIntegerLiteral(self, ctx: GremlinParser.IntegerLiteralContext) -> 
int:
+        text = ctx.getText().lower().rstrip('l')
+        return int(text)
+        
+    def visitGenericArgumentVarargs(self, ctx: 
GremlinParser.GenericArgumentVarargsContext) -> list:
+        if ctx is None: 
+            return []
+        args = []
+        # 使用 genericArgument() 方法获取所有参数
+        for i in range(len(ctx.genericArgument())):
+            args.append(self.visit(ctx.genericArgument(i)))
+        return args
+        
+    def visitStringNullableArgumentVarargs(self, ctx: 
GremlinParser.StringNullableArgumentVarargsContext) -> list:
+        if ctx is None: 
+            return []
+        args = []
+        if ctx.children:
+            for child in ctx.children:
+                if isinstance(child, 
GremlinParser.StringNullableArgumentContext):
+                    args.append(self.visit(child))
+        return args
+
+    def visitTraversalPredicate_gt(self, ctx: 
GremlinParser.TraversalPredicate_gtContext):
+        value = self.visit(ctx.genericArgument())
+        return Predicate('gt', value)
+
+    def visitTraversalPredicate_within(self, ctx: 
GremlinParser.TraversalPredicate_withinContext):
+        values = self.visit(ctx.genericArgumentVarargs())
+        return Predicate('within', values)
+
+    # 更多谓词的访问器
+    def visitTraversalPredicate_lt(self, ctx):
+        value = self.visit(ctx.genericArgument())
+        return Predicate('lt', value)
+
+    def visitTraversalPredicate_lte(self, ctx):
+        value = self.visit(ctx.genericArgument())
+        return Predicate('lte', value)
+
+    def visitTraversalPredicate_gte(self, ctx):
+        value = self.visit(ctx.genericArgument())
+        return Predicate('gte', value)
+
+    def visitTraversalPredicate_eq(self, ctx):
+        value = self.visit(ctx.genericArgument())
+        return Predicate('eq', value)
+
+    def visitTraversalPredicate_neq(self, ctx):
+        value = self.visit(ctx.genericArgument())
+        return Predicate('neq', value)
+
+    def visitTraversalPredicate_between(self, ctx):
+        params = []
+        if hasattr(ctx, 'genericArgument'):
+            if ctx.genericArgument(0):
+                params.append(self.visit(ctx.genericArgument(0)))
+            if ctx.genericArgument(1):
+                params.append(self.visit(ctx.genericArgument(1)))
+        return Predicate('between', params)
+
+    def visitTraversalPredicate_inside(self, ctx):
+        params = []
+        if hasattr(ctx, 'genericArgument'):
+            if ctx.genericArgument(0):
+                params.append(self.visit(ctx.genericArgument(0)))
+            if ctx.genericArgument(1):
+                params.append(self.visit(ctx.genericArgument(1)))
+        return Predicate('inside', params)
+
+    def visitTraversalPredicate_outside(self, ctx):
+        params = []
+        if hasattr(ctx, 'genericArgument'):
+            if ctx.genericArgument(0):
+                params.append(self.visit(ctx.genericArgument(0)))
+            if ctx.genericArgument(1):
+                params.append(self.visit(ctx.genericArgument(1)))
+        return Predicate('outside', params)
+
+    def visitTraversalPredicate_without(self, ctx):
+        values = self.visit(ctx.genericArgumentVarargs())
+        return Predicate('without', values)
+
+    # TextPredicate 访问器
+    def visitTraversalPredicate_startingWith(self, ctx):
+        value = self.visit(ctx.stringArgument())
+        return TextPredicate('startingWith', value)
+
+    def visitTraversalPredicate_endingWith(self, ctx):
+        value = self.visit(ctx.stringArgument())
+        return TextPredicate('endingWith', value)
+
+    def visitTraversalPredicate_containing(self, ctx):
+        value = self.visit(ctx.stringArgument())
+        return TextPredicate('containing', value)
+
+    def visitTraversalPredicate_notStartingWith(self, ctx):
+        value = self.visit(ctx.stringArgument())
+        return TextPredicate('notStartingWith', value)
+
+    def visitTraversalPredicate_notEndingWith(self, ctx):
+        value = self.visit(ctx.stringArgument())
+        return TextPredicate('notEndingWith', value)
+
+    def visitTraversalPredicate_notContaining(self, ctx):
+        value = self.visit(ctx.stringArgument())
+        return TextPredicate('notContaining', value)
+
+    # 匿名遍历和嵌套遍历访问器
+    def visitNestedTraversal(self, ctx: GremlinParser.NestedTraversalContext):
+        # 创建一个新的匿名遍历
+        anonymous_traversal = AnonymousTraversal()
+        
+        # 保存当前遍历状态
+        current_traversal = self.traversal
+        
+        # 创建临时遍历来收集匿名遍历的步骤
+        temp_traversal = Traversal()
+        self.traversal = temp_traversal
+        
+        # 访问嵌套遍历的内容
+        if ctx.chainedTraversal():
+            self.visit(ctx.chainedTraversal())
+        
+        # 将临时遍历的步骤添加到匿名遍历中
+        for step in temp_traversal.steps:
+            anonymous_traversal.add_step(step)
+        
+        # 恢复原始遍历状态
+        self.traversal = current_traversal
+        
+        return anonymous_traversal
+
+    def visitNestedTraversalVarargs(self, ctx):
+        if ctx is None:
+            return []
+        
+        traversals = []
+        for child in ctx.children:
+            if isinstance(child, GremlinParser.NestedTraversalContext):
+                traversals.append(self.visit(child))
+        return traversals
+
+    # 连接器访问器 (and, or)
+    def visitTraversalMethod_and(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversalVarargs') and 
ctx.nestedTraversalVarargs():
+            traversals = self.visit(ctx.nestedTraversalVarargs())
+            connector = Connector('and', traversals)
+            params.append(connector)
+        self.traversal.add_step(Step('and', params))
+
+    def visitTraversalMethod_or(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversalVarargs') and 
ctx.nestedTraversalVarargs():
+            traversals = self.visit(ctx.nestedTraversalVarargs())
+            connector = Connector('or', traversals)
+            params.append(connector)
+        self.traversal.add_step(Step('or', params))
+
+    # 终端方法访问器
+    def visitTraversalMethod_next(self, ctx):
+        terminal = Terminal('next')
+        self.traversal.add_step(Step('next', [terminal]))
+
+    def visitTraversalMethod_hasNext(self, ctx):
+        terminal = Terminal('hasNext')
+        self.traversal.add_step(Step('hasNext', [terminal]))
+
+    def visitTraversalMethod_toList(self, ctx):
+        terminal = Terminal('toList')
+        self.traversal.add_step(Step('toList', [terminal]))
+
+    def visitTraversalMethod_toSet(self, ctx):
+        terminal = Terminal('toSet')
+        self.traversal.add_step(Step('toSet', [terminal]))
+
+    def visitTraversalMethod_iterate(self, ctx):
+        terminal = Terminal('iterate')
+        self.traversal.add_step(Step('iterate', [terminal]))
+
+    # 缺失的 Spawn Method 访问器
+    def visitTraversalSourceSpawnMethod_E(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_EContext):
+        params = self.visit(ctx.genericArgumentVarargs()) if 
ctx.genericArgumentVarargs() else []
+        self.traversal.add_step(Step('E', params))
+
+    def visitTraversalSourceSpawnMethod_addE(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_addEContext):
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        elif ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('addE', params))
+
+    def visitTraversalSourceSpawnMethod_inject(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_injectContext):
+        params = self.visit(ctx.genericArgumentVarargs()) if 
ctx.genericArgumentVarargs() else []
+        self.traversal.add_step(Step('inject', params))
+
+    # Call方法的各种变体支持
+    def visitTraversalSourceSpawnMethod_call_empty(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_call_emptyContext):
+        """处理 g.call() 空参数调用"""
+        self.traversal.add_step(Step('call', []))
+
+    def visitTraversalSourceSpawnMethod_call_string(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_call_stringContext):
+        """处理 g.call('methodName') 单字符串参数调用"""
+        params = []
+        # 查找StringLiteralContext子节点
+        for child in ctx.children:
+            if hasattr(child, 'getRuleIndex') and 'StringLiteral' in 
type(child).__name__:
+                string_val = child.getText()
+                # 移除引号
+                if string_val.startswith('"') and string_val.endswith('"'):
+                    string_val = string_val[1:-1]
+                elif string_val.startswith("'") and string_val.endswith("'"):
+                    string_val = string_val[1:-1]
+                params.append(string_val)
+                break
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalSourceSpawnMethod_call_string_map(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_call_string_mapContext):
+        """处理 g.call('methodName', map) 字符串+映射参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.genericLiteralMap():
+            params.append(self.visit(ctx.genericLiteralMap()))
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalSourceSpawnMethod_call_string_traversal(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_call_string_traversalContext):
+        """处理 g.call('methodName', traversal) 字符串+遍历参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalSourceSpawnMethod_call_string_map_traversal(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_call_string_map_traversalContext):
+        """处理 g.call('methodName', map, traversal) 字符串+映射+遍历参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.genericLiteralMap():
+            params.append(self.visit(ctx.genericLiteralMap()))
+        if ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalSourceSpawnMethod_io(self, ctx: 
GremlinParser.TraversalSourceSpawnMethod_ioContext):
+        params = []
+        if ctx.stringLiteral():
+            params.append(self.visit(ctx.stringLiteral()))
+        self.traversal.add_step(Step('io', params))
+
+    # 辅助方法访问器
+    def visitStringArgument(self, ctx: GremlinParser.StringArgumentContext):
+        if ctx.stringLiteral():
+            return self.visit(ctx.stringLiteral())
+        elif ctx.stringNullableLiteral():
+            return self.visit(ctx.stringNullableLiteral())
+        return None
+
+    def visitStringNullableLiteral(self, ctx: 
GremlinParser.StringNullableLiteralContext):
+        if ctx.EmptyStringLiteral():
+            return ""
+        elif ctx.NonEmptyStringLiteral():
+            text = ctx.NonEmptyStringLiteral().getText()
+            return text.strip("'\"")
+        elif ctx.K_NULL():
+            return None
+        return None
+
+    def visitStringNullableArgument(self, ctx: 
GremlinParser.StringNullableArgumentContext):
+        if ctx.stringNullableLiteral():
+            return self.visit(ctx.stringNullableLiteral())
+        elif ctx.variable():
+            return self.visit(ctx.variable())
+        return None
+
+    def visitGenericArgument(self, ctx: GremlinParser.GenericArgumentContext):
+        if ctx.genericLiteral():
+            return self.visit(ctx.genericLiteral())
+        elif ctx.variable():
+            return self.visit(ctx.variable())
+        return None
+
+    def visitIntegerArgument(self, ctx: GremlinParser.IntegerArgumentContext):
+        if ctx.integerLiteral():
+            return self.visit(ctx.integerLiteral())
+        return 0
+
+    def visitFloatLiteral(self, ctx: GremlinParser.FloatLiteralContext) -> 
float:
+        text = ctx.getText().lower().rstrip('f').rstrip('d')
+        return float(text)
+
+    def visitBooleanLiteral(self, ctx: GremlinParser.BooleanLiteralContext) -> 
bool:
+        text = ctx.getText().lower()
+        return text == 'true'
+
+    def visitNullLiteral(self, ctx: GremlinParser.NullLiteralContext):
+        return None
+
+    def visitGenericLiteral(self, ctx: GremlinParser.GenericLiteralContext):
+        # 处理通用字面量,可能是字符串、数字等
+        text = ctx.getText()
+        # 尝试解析为不同类型
+        if text.startswith('"') or text.startswith("'"):
+            return text.strip("'\"")
+        try:
+            if '.' in text:
+                return float(text)
+            else:
+                return int(text)
+        except ValueError:
+            return text
+
+    def visitVariable(self, ctx: GremlinParser.VariableContext):
+        # 变量通常以 $ 开头,返回变量名
+        return ctx.getText()
+
+    def visitTraversalT(self, ctx):
+        # T 枚举值,如 T.id, T.label, T.key, T.value
+        return ctx.getText()
+
+    def visitStringNullableLiteralVarargs(self, ctx: 
GremlinParser.StringNullableLiteralVarargsContext) -> list:
+        if ctx is None: 
+            return []
+        args = []
+        # 使用 stringNullableLiteral() 方法获取所有参数
+        for i in range(len(ctx.stringNullableLiteral())):
+            args.append(self.visit(ctx.stringNullableLiteral(i)))
+        return args
+
+    def visitFloatArgument(self, ctx):
+        if hasattr(ctx, 'floatLiteral') and ctx.floatLiteral():
+            return self.visit(ctx.floatLiteral())
+        return 0.0
+
+    def visitBooleanArgument(self, ctx):
+        if hasattr(ctx, 'booleanLiteral') and ctx.booleanLiteral():
+            return self.visit(ctx.booleanLiteral())
+        return False
+
+    def visitTraversalPredicate(self, ctx):
+        # 通用的谓词访问器,根据具体类型调用相应的方法
+        # 避免无限递归,直接调用默认的 visitChildren
+        return self.visitChildren(ctx)
+
+    # 导航方法访问器
+    def visitTraversalMethod_in(self, ctx: 
GremlinParser.TraversalMethod_inContext):
+        params = []
+        if ctx.stringNullableArgumentVarargs():
+            result = self.visit(ctx.stringNullableArgumentVarargs())
+            if result is not None:
+                params = result
+        self.traversal.add_step(Step('in', params))
+
+    def visitTraversalMethod_both(self, ctx: 
GremlinParser.TraversalMethod_bothContext):
+        params = []
+        if ctx.stringNullableArgumentVarargs():
+            result = self.visit(ctx.stringNullableArgumentVarargs())
+            if result is not None:
+                params = result
+        self.traversal.add_step(Step('both', params))
+
+    def visitTraversalMethod_bothE(self, ctx: 
GremlinParser.TraversalMethod_bothEContext):
+        params = []
+        if ctx.stringNullableArgumentVarargs():
+            result = self.visit(ctx.stringNullableArgumentVarargs())
+            if result is not None:
+                params = result
+        self.traversal.add_step(Step('bothE', params))
+
+    def visitTraversalMethod_bothV(self, ctx: 
GremlinParser.TraversalMethod_bothVContext):
+        self.traversal.add_step(Step('bothV', []))
+
+    def visitTraversalMethod_inE(self, ctx: 
GremlinParser.TraversalMethod_inEContext):
+        params = []
+        if ctx.stringNullableArgumentVarargs():
+            result = self.visit(ctx.stringNullableArgumentVarargs())
+            if result is not None:
+                params = result
+        self.traversal.add_step(Step('inE', params))
+
+    def visitTraversalMethod_outE(self, ctx: 
GremlinParser.TraversalMethod_outEContext):
+        params = []
+        if ctx.stringNullableArgumentVarargs():
+            result = self.visit(ctx.stringNullableArgumentVarargs())
+            if result is not None:
+                params = result
+        self.traversal.add_step(Step('outE', params))
+
+    def visitTraversalMethod_inV(self, ctx: 
GremlinParser.TraversalMethod_inVContext):
+        self.traversal.add_step(Step('inV', []))
+
+    def visitTraversalMethod_outV(self, ctx: 
GremlinParser.TraversalMethod_outVContext):
+        self.traversal.add_step(Step('outV', []))
+
+    # 更多过滤方法访问器
+    def visitTraversalMethod_where(self, ctx):
+        # where() 方法可能有多种变体,需要检查参数类型
+        params = []
+        if hasattr(ctx, 'traversalPredicate') and ctx.traversalPredicate():
+            params.append(self.visit(ctx.traversalPredicate()))
+        elif hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('where', params))
+
+    def visitTraversalMethod_filter(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('filter', params))
+
+    def visitTraversalMethod_is(self, ctx):
+        params = []
+        if hasattr(ctx, 'genericArgument') and ctx.genericArgument():
+            params.append(self.visit(ctx.genericArgument()))
+        elif hasattr(ctx, 'traversalPredicate') and ctx.traversalPredicate():
+            params.append(self.visit(ctx.traversalPredicate()))
+        self.traversal.add_step(Step('is', params))
+
+    def visitTraversalMethod_not(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('not', params))
+
+    def visitTraversalMethod_hasLabel(self, ctx):
+        params = self.visit(ctx.stringNullableArgumentVarargs()) if 
hasattr(ctx, 'stringNullableArgumentVarargs') and 
ctx.stringNullableArgumentVarargs() else []
+        self.traversal.add_step(Step('hasLabel', params))
+
+    def visitTraversalMethod_hasLabel_P(self, ctx):
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('hasLabel', [predicate]))
+
+    def visitTraversalMethod_hasLabel_String_String(self, ctx):
+        params = []
+        if ctx.stringNullableArgument():
+            params.append(self.visit(ctx.stringNullableArgument()))
+        if ctx.stringNullableArgumentVarargs():
+            params.extend(self.visit(ctx.stringNullableArgumentVarargs()))
+        self.traversal.add_step(Step('hasLabel', params))
+
+    def visitTraversalMethod_hasId(self, ctx):
+        params = self.visit(ctx.genericArgumentVarargs()) if hasattr(ctx, 
'genericArgumentVarargs') and ctx.genericArgumentVarargs() else []
+        self.traversal.add_step(Step('hasId', params))
+
+    def visitTraversalMethod_hasId_Object_Object(self, ctx):
+        params = []
+        if ctx.genericArgument():
+            params.append(self.visit(ctx.genericArgument()))
+        if ctx.genericArgumentVarargs():
+            params.extend(self.visit(ctx.genericArgumentVarargs()))
+        self.traversal.add_step(Step('hasId', params))
+
+    def visitTraversalMethod_hasId_P(self, ctx):
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('hasId', [predicate]))
+
+    def visitTraversalMethod_hasKey(self, ctx):
+        params = self.visit(ctx.stringNullableArgumentVarargs()) if 
hasattr(ctx, 'stringNullableArgumentVarargs') and 
ctx.stringNullableArgumentVarargs() else []
+        self.traversal.add_step(Step('hasKey', params))
+
+    def visitTraversalMethod_hasKey_P(self, ctx):
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('hasKey', [predicate]))
+
+    def visitTraversalMethod_hasKey_String_String(self, ctx):
+        params = []
+        if ctx.stringNullableLiteral():
+            params.append(self.visit(ctx.stringNullableLiteral()))
+        if ctx.stringNullableLiteralVarargs():
+            params.extend(self.visit(ctx.stringNullableLiteralVarargs()))
+        self.traversal.add_step(Step('hasKey', params))
+
+    def visitTraversalMethod_hasValue(self, ctx):
+        params = self.visit(ctx.genericArgumentVarargs()) if hasattr(ctx, 
'genericArgumentVarargs') and ctx.genericArgumentVarargs() else []
+        self.traversal.add_step(Step('hasValue', params))
+
+    def visitTraversalMethod_hasValue_Object_Object(self, ctx):
+        params = []
+        if ctx.genericArgument():
+            params.append(self.visit(ctx.genericArgument()))
+        if ctx.genericArgumentVarargs():
+            params.extend(self.visit(ctx.genericArgumentVarargs()))
+        self.traversal.add_step(Step('hasValue', params))
+
+    def visitTraversalMethod_hasValue_P(self, ctx):
+        predicate = self.visit(ctx.traversalPredicate())
+        self.traversal.add_step(Step('hasValue', [predicate]))
+
+    # 删除操作访问器
+    def visitTraversalMethod_drop(self, ctx):
+        self.traversal.add_step(Step('drop', []))
+
+    # Call方法的各种变体支持 (traversalMethod版本)
+    def visitTraversalMethod_call_string(self, ctx: 
GremlinParser.TraversalMethod_call_stringContext):
+        """处理 .call('methodName') 单字符串参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalMethod_call_string_map(self, ctx: 
GremlinParser.TraversalMethod_call_string_mapContext):
+        """处理 .call('methodName', map) 字符串+映射参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.genericLiteralMap():
+            params.append(self.visit(ctx.genericLiteralMap()))
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalMethod_call_string_traversal(self, ctx: 
GremlinParser.TraversalMethod_call_string_traversalContext):
+        """处理 .call('methodName', traversal) 字符串+遍历参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('call', params))
+
+    def visitTraversalMethod_call_string_map_traversal(self, ctx: 
GremlinParser.TraversalMethod_call_string_map_traversalContext):
+        """处理 .call('methodName', map, traversal) 字符串+映射+遍历参数调用"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.genericLiteralMap():
+            params.append(self.visit(ctx.genericLiteralMap()))
+        if ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('call', params))
+
+    # 更多修改操作访问器
+    def visitTraversalMethod_addE_String(self, ctx):
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        self.traversal.add_step(Step('addE', params))
+
+    def visitTraversalMethod_addE_Traversal(self, ctx):
+        params = []
+        if ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('addE', params))
+
+    def visitTraversalMethod_addV_Empty(self, ctx):
+        self.traversal.add_step(Step('addV', []))
+
+    def visitTraversalMethod_addV_String(self, ctx):
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        self.traversal.add_step(Step('addV', params))
+
+    def visitTraversalMethod_addV_Traversal(self, ctx):
+        params = []
+        if ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('addV', params))
+
+    def visitTraversalMethod_from(self, ctx):
+        params = []
+        if hasattr(ctx, 'stringArgument') and ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        elif hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('from', params))
+
+    def visitTraversalMethod_to(self, ctx):
+        params = []
+        if hasattr(ctx, 'stringArgument') and ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        elif hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('to', params))
+
+    # With方法的各种变体支持
+    def visitTraversalMethod_with_String(self, ctx: 
GremlinParser.TraversalMethod_with_StringContext):
+        """处理 .with('key') 单字符串参数调用"""
+        params = []
+        # 查找StringLiteralContext子节点
+        for child in ctx.children:
+            if hasattr(child, 'getRuleIndex') and 'StringLiteral' in 
type(child).__name__:
+                string_val = child.getText()
+                # 移除引号
+                if string_val.startswith('"') and string_val.endswith('"'):
+                    string_val = string_val[1:-1]
+                elif string_val.startswith("'") and string_val.endswith("'"):
+                    string_val = string_val[1:-1]
+                params.append(string_val)
+                break
+        self.traversal.add_step(Step('with', params))
+
+    def visitTraversalMethod_with_String_Object(self, ctx: 
GremlinParser.TraversalMethod_with_String_ObjectContext):
+        """处理 .with('key', value) 字符串+对象参数调用"""
+        params = []
+        # 查找StringLiteralContext和GenericArgumentContext子节点
+        for child in ctx.children:
+            if hasattr(child, 'getRuleIndex'):
+                if 'StringLiteral' in type(child).__name__:
+                    string_val = child.getText()
+                    # 移除引号
+                    if string_val.startswith('"') and string_val.endswith('"'):
+                        string_val = string_val[1:-1]
+                    elif string_val.startswith("'") and 
string_val.endswith("'"):
+                        string_val = string_val[1:-1]
+                    params.append(string_val)
+                elif 'GenericArgument' in type(child).__name__:
+                    # 处理GenericArgument,可能包含字符串或数字
+                    arg_text = child.getText()
+                    # 如果是字符串,移除引号
+                    if arg_text.startswith('"') and arg_text.endswith('"'):
+                        arg_text = arg_text[1:-1]
+                    elif arg_text.startswith("'") and arg_text.endswith("'"):
+                        arg_text = arg_text[1:-1]
+                    params.append(arg_text)
+        self.traversal.add_step(Step('with', params))
+
+    # TraversalSourceSelfMethod的with方法支持
+    def visitTraversalSourceSelfMethod_with(self, ctx: 
GremlinParser.TraversalSourceSelfMethod_withContext):
+        """处理 g.with() 方法"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.genericArgument():
+            params.append(self.visit(ctx.genericArgument()))
+        self.traversal.add_step(Step('with', params))
+
+    def visitTraversalSourceSelfMethod_withSideEffect(self, ctx: 
GremlinParser.TraversalSourceSelfMethod_withSideEffectContext):
+        """处理 g.withSideEffect() 方法"""
+        params = []
+        if ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        if ctx.genericArgument():
+            params.append(self.visit(ctx.genericArgument()))
+        self.traversal.add_step(Step('withSideEffect', params))
+
+    # 转换方法访问器
+    def visitTraversalMethod_properties(self, ctx):
+        params = self.visit(ctx.stringNullableLiteralVarargs()) if 
hasattr(ctx, 'stringNullableLiteralVarargs') and 
ctx.stringNullableLiteralVarargs() else []
+        self.traversal.add_step(Step('properties', params))
+
+    def visitTraversalMethod_select(self, ctx):
+        params = []
+        if hasattr(ctx, 'stringNullableArgumentVarargs') and 
ctx.stringNullableArgumentVarargs():
+            params = self.visit(ctx.stringNullableArgumentVarargs())
+        elif hasattr(ctx, 'stringArgument') and ctx.stringArgument():
+            params.append(self.visit(ctx.stringArgument()))
+        self.traversal.add_step(Step('select', params))
+
+    def visitTraversalMethod_select_String_String_String(self, ctx: 
GremlinParser.TraversalMethod_select_String_String_StringContext):
+        """处理 .select('key1', 'key2', 'key3') 多字符串参数调用"""
+        params = []
+        # 查找所有StringLiteralContext子节点
+        for child in ctx.children:
+            if hasattr(child, 'getRuleIndex') and 'StringLiteral' in 
type(child).__name__:
+                string_val = child.getText()
+                # 移除引号
+                if string_val.startswith('"') and string_val.endswith('"'):
+                    string_val = string_val[1:-1]
+                elif string_val.startswith("'") and string_val.endswith("'"):
+                    string_val = string_val[1:-1]
+                params.append(string_val)
+        self.traversal.add_step(Step('select', params))
+
+    def visitTraversalMethod_project(self, ctx):
+        params = self.visit(ctx.stringNullableArgumentVarargs()) if 
hasattr(ctx, 'stringNullableArgumentVarargs') and 
ctx.stringNullableArgumentVarargs() else []
+        self.traversal.add_step(Step('project', params))
+
+    def visitTraversalMethod_valueMap(self, ctx):
+        params = []
+        if hasattr(ctx, 'stringNullableLiteralVarargs') and 
ctx.stringNullableLiteralVarargs():
+            params = self.visit(ctx.stringNullableLiteralVarargs())
+        elif hasattr(ctx, 'booleanArgument') and ctx.booleanArgument():
+            params.append(self.visit(ctx.booleanArgument()))
+        self.traversal.add_step(Step('valueMap', params))
+
+    def visitTraversalMethod_elementMap(self, ctx):
+        params = self.visit(ctx.stringNullableLiteralVarargs()) if 
hasattr(ctx, 'stringNullableLiteralVarargs') and 
ctx.stringNullableLiteralVarargs() else []
+        self.traversal.add_step(Step('elementMap', params))
+
+    def visitTraversalMethod_label(self, ctx):
+        self.traversal.add_step(Step('label', []))
+
+    def visitTraversalMethod_id(self, ctx):
+        self.traversal.add_step(Step('id', []))
+
+    def visitTraversalMethod_key(self, ctx):
+        self.traversal.add_step(Step('key', []))
+
+    def visitTraversalMethod_value(self, ctx):
+        self.traversal.add_step(Step('value', []))
+
+    # 聚合方法访问器
+    def visitTraversalMethod_count(self, ctx):
+        self.traversal.add_step(Step('count', []))
+
+    def visitTraversalMethod_sum(self, ctx):
+        self.traversal.add_step(Step('sum', []))
+
+    def visitTraversalMethod_mean(self, ctx):
+        self.traversal.add_step(Step('mean', []))
+
+    def visitTraversalMethod_max(self, ctx):
+        self.traversal.add_step(Step('max', []))
+
+    def visitTraversalMethod_min(self, ctx):
+        self.traversal.add_step(Step('min', []))
+
+    def visitTraversalMethod_fold(self, ctx):
+        self.traversal.add_step(Step('fold', []))
+
+    def visitTraversalMethod_unfold(self, ctx):
+        self.traversal.add_step(Step('unfold', []))
+
+    def visitTraversalMethod_group(self, ctx):
+        self.traversal.add_step(Step('group', []))
+
+    def visitTraversalMethod_groupCount(self, ctx):
+        self.traversal.add_step(Step('groupCount', []))
+
+    # 排序和限制方法访问器
+    def visitTraversalMethod_order(self, ctx):
+        self.traversal.add_step(Step('order', []))
+
+    def visitTraversalMethod_range(self, ctx):
+        params = []
+        if hasattr(ctx, 'integerArgument'):
+            if ctx.integerArgument(0):
+                params.append(self.visit(ctx.integerArgument(0)))
+            if ctx.integerArgument(1):
+                params.append(self.visit(ctx.integerArgument(1)))
+        self.traversal.add_step(Step('range', params))
+
+    def visitTraversalMethod_skip(self, ctx):
+        params = []
+        if hasattr(ctx, 'integerArgument') and ctx.integerArgument():
+            params.append(self.visit(ctx.integerArgument()))
+        self.traversal.add_step(Step('skip', params))
+
+    def visitTraversalMethod_tail(self, ctx):
+        params = []
+        if hasattr(ctx, 'integerArgument') and ctx.integerArgument():
+            params.append(self.visit(ctx.integerArgument()))
+        self.traversal.add_step(Step('tail', params))
+
+    def visitTraversalMethod_sample(self, ctx):
+        params = []
+        if hasattr(ctx, 'integerArgument') and ctx.integerArgument():
+            params.append(self.visit(ctx.integerArgument()))
+        self.traversal.add_step(Step('sample', params))
+
+    def visitTraversalMethod_coin(self, ctx):
+        params = []
+        if hasattr(ctx, 'floatArgument') and ctx.floatArgument():
+            params.append(self.visit(ctx.floatArgument()))
+        self.traversal.add_step(Step('coin', params))
+
+    # 分支和条件方法访问器
+    def visitTraversalMethod_choose(self, ctx):
+        params = []
+        if hasattr(ctx, 'traversalPredicate') and ctx.traversalPredicate():
+            params.append(self.visit(ctx.traversalPredicate()))
+        elif hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('choose', params))
+
+    def visitTraversalMethod_coalesce(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversalVarargs') and 
ctx.nestedTraversalVarargs():
+            params = self.visit(ctx.nestedTraversalVarargs())
+        self.traversal.add_step(Step('coalesce', params))
+
+    def visitTraversalMethod_optional(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversal') and ctx.nestedTraversal():
+            params.append(self.visit(ctx.nestedTraversal()))
+        self.traversal.add_step(Step('optional', params))
+
+    def visitTraversalMethod_union(self, ctx):
+        params = []
+        if hasattr(ctx, 'nestedTraversalVarargs') and 
ctx.nestedTraversalVarargs():
+            params = self.visit(ctx.nestedTraversalVarargs())
+        self.traversal.add_step(Step('union', params))
+
+# 测试入口函数
+def parse_gremlin_query(query_string: str) -> Traversal:
+    """
+    便捷的模块级函数,用于解析Gremlin查询字符串。
+    
+    Args:
+        query_string (str): 要解析的 Gremlin 查询字符串
+        
+    Returns:
+        Traversal: 包含步骤的解析后遍历对象
+    """
+    visitor = GremlinTransVisitor()
+    return visitor.parse_and_visit(query_string)
+
+if __name__ == '__main__':
+    print("  启动 GremlinTransVisitor 全面测试")
+    print("=" * 80)
+    
+    visitor = GremlinTransVisitor()
+    
+    # 测试类别
+    test_categories = {
+        ' Spawn Methods (Traversal Source)': [
+            # Basic spawn methods
+            ('g.V()', 'Basic vertex spawn'),
+            ('g.V(1)', 'Vertex spawn with single ID'),
+            ('g.V(1, 2, 3)', 'Vertex spawn with multiple IDs'),
+            ('g.V("uuid-1", "uuid-2")', 'Vertex spawn with string IDs'),
+            ('g.E()', 'Basic edge spawn'),
+            ('g.E("edge1")', 'Edge spawn with single ID'),
+            ('g.E("edge1", "edge2")', 'Edge spawn with multiple IDs'),
+            ('g.addV()', 'Add vertex without label'),
+            ('g.addV("person")', 'Add vertex with string label'),
+            ('g.addE("knows")', 'Add edge with string label'),
+            ('g.inject(1)', 'Inject single value'),
+            ('g.inject(1, 2, 3)', 'Inject multiple values'),
+            ('g.inject("a", "b", "c")', 'Inject string values'),
+            ('g.io("data.json")', 'IO operation with file'),
+        ],
+        
+        ' Navigation Methods': [
+            # Basic navigation
+            ('g.V().out()', 'Outbound navigation without labels'),
+            ('g.V().out("knows")', 'Outbound navigation with single label'),
+            ('g.V().out("knows", "created")', 'Outbound navigation with 
multiple labels'),
+            ('g.V().in()', 'Inbound navigation without labels'),
+            ('g.V().in("created")', 'Inbound navigation with single label'),
+            ('g.V().in("knows", "created")', 'Inbound navigation with multiple 
labels'),
+            ('g.V().both()', 'Bidirectional navigation without labels'),
+            ('g.V().both("knows")', 'Bidirectional navigation with single 
label'),
+            ('g.V().both("knows", "created")', 'Bidirectional navigation with 
multiple labels'),
+            
+            # Edge navigation
+            ('g.V().outE()', 'Outbound edge navigation without labels'),
+            ('g.V().outE("knows")', 'Outbound edge navigation with single 
label'),
+            ('g.V().outE("knows", "created")', 'Outbound edge navigation with 
multiple labels'),
+            ('g.V().inE()', 'Inbound edge navigation without labels'),
+            ('g.V().inE("created")', 'Inbound edge navigation with single 
label'),
+            ('g.V().inE("knows", "created")', 'Inbound edge navigation with 
multiple labels'),
+            ('g.V().bothE()', 'Bidirectional edge navigation without labels'),
+            ('g.V().bothE("knows")', 'Bidirectional edge navigation with 
single label'),
+            ('g.V().bothE("knows", "created")', 'Bidirectional edge navigation 
with multiple labels'),
+            
+            # Vertex navigation from edges
+            ('g.E().outV()', 'Edge to outbound vertex'),
+            ('g.E().inV()', 'Edge to inbound vertex'),
+            ('g.E().bothV()', 'Edge to both vertices'),
+        ],
+        
+        ' Filtering Methods': [
+            # Basic has methods
+            ('g.V().has("name")', 'Has property key only'),
+            ('g.V().has("name", "john")', 'Has property key-value'),
+            ('g.V().has("name", 42)', 'Has property key-number'),
+            ('g.V().has("name", true)', 'Has property key-boolean'),
+            ('g.V().has("person", "name", "john")', 'Has label-key-value'),
+            ('g.V().has("person", "age", 30)', 'Has label-key-number'),
+            
+            # Advanced filtering
+            ('g.V().hasLabel("person")', 'Has single label'),
+            ('g.V().hasLabel("person", "software")', 'Has multiple labels'),
+            ('g.V().hasId(1)', 'Has single ID'),
+            ('g.V().hasId(1, 2, 3)', 'Has multiple IDs'),
+            ('g.V().hasKey("name")', 'Has single key'),
+            ('g.V().hasKey("name", "age")', 'Has multiple keys'),
+            ('g.V().hasValue("john")', 'Has single value'),
+            ('g.V().hasValue("john", "mary")', 'Has multiple values'),
+            
+            # Conditional filtering
+            ('g.V().where(__.out("knows"))', 'Where with anonymous traversal'),
+            ('g.V().filter(__.out("knows"))', 'Filter with anonymous 
traversal'),
+            ('g.V().is("john")', 'Is with value'),
+            ('g.V().is(P.gt(30))', 'Is with predicate'),
+            ('g.V().not(__.out("knows"))', 'Not with anonymous traversal'),
+        ],
+        
+        ' Transformation Methods': [
+            # Property access
+            ('g.V().properties()', 'Get all properties'),
+            ('g.V().properties("name")', 'Get single property'),
+            ('g.V().properties("name", "age")', 'Get multiple properties'),
+            ('g.V().values()', 'Get all values'),
+            ('g.V().values("name")', 'Get single value'),
+            ('g.V().values("name", "age")', 'Get multiple values'),
+            
+            # Selection and projection
+            ('g.V().select("a")', 'Select single label'),
+            ('g.V().select("a", "b")', 'Select multiple labels'),
+            ('g.V().project("name")', 'Project single property'),
+            ('g.V().project("name", "age")', 'Project multiple properties'),
+            ('g.V().valueMap()', 'Get value map'),
+            ('g.V().valueMap(true)', 'Get value map with metadata'),
+            ('g.V().valueMap("name", "age")', 'Get value map for specific 
properties'),
+            ('g.V().elementMap()', 'Get element map'),
+            ('g.V().elementMap("name", "age")', 'Get element map for specific 
properties'),
+            
+            # Element metadata
+            ('g.V().label()', 'Get vertex label'),
+            ('g.E().label()', 'Get edge label'),
+            ('g.V().id()', 'Get vertex ID'),
+            ('g.E().id()', 'Get edge ID'),
+            ('g.V().properties().key()', 'Get property key'),
+            ('g.V().properties().value()', 'Get property value'),
+        ],
+        
+        ' Aggregation Methods': [
+            # Basic aggregation
+            ('g.V().count()', 'Count vertices'),
+            ('g.E().count()', 'Count edges'),
+            ('g.V().values("age").sum()', 'Sum numeric values'),
+            ('g.V().values("age").mean()', 'Mean of numeric values'),
+            ('g.V().values("age").max()', 'Maximum numeric value'),
+            ('g.V().values("age").min()', 'Minimum numeric value'),
+            
+            # Collection operations
+            ('g.V().fold()', 'Fold vertices into collection'),
+            ('g.V().values("name").fold()', 'Fold values into collection'),
+            ('g.inject([1, 2, 3]).unfold()', 'Unfold collection'),
+            
+            # Grouping
+            ('g.V().group()', 'Group vertices'),
+            ('g.V().groupCount()', 'Group and count vertices'),
+            ('g.V().values("name").groupCount()', 'Group and count by 
property'),
+        ],
+        
+        ' Predicate Methods': [
+            # Comparison predicates
+            ('g.V().has("age", P.gt(30))', 'Greater than predicate'),
+            ('g.V().has("age", P.gte(30))', 'Greater than or equal predicate'),
+            ('g.V().has("age", P.lt(50))', 'Less than predicate'),
+            ('g.V().has("age", P.lte(50))', 'Less than or equal predicate'),
+            ('g.V().has("name", P.eq("john"))', 'Equal predicate'),
+            ('g.V().has("name", P.neq("john"))', 'Not equal predicate'),
+            
+            # Range predicates
+            ('g.V().has("age", P.between(20, 40))', 'Between predicate'),
+            ('g.V().has("age", P.inside(20, 40))', 'Inside predicate'),
+            ('g.V().has("age", P.outside(20, 40))', 'Outside predicate'),
+            
+            # Collection predicates
+            ('g.V().has("name", P.within("john", "mary"))', 'Within 
predicate'),
+            ('g.V().has("name", P.within("john", "mary", "bob"))', 'Within 
multiple values'),
+            ('g.V().has("name", P.without("john", "mary"))', 'Without 
predicate'),
+        ],
+        
+        ' TextPredicate Methods': [
+            ('g.V().has("name", TextP.startingWith("J"))', 'Starting with text 
predicate'),
+            ('g.V().has("name", TextP.endingWith("n"))', 'Ending with text 
predicate'),
+            ('g.V().has("name", TextP.containing("oh"))', 'Containing text 
predicate'),
+            ('g.V().has("name", TextP.notStartingWith("J"))', 'Not starting 
with text predicate'),
+            ('g.V().has("name", TextP.notEndingWith("n"))', 'Not ending with 
text predicate'),
+            ('g.V().has("name", TextP.notContaining("oh"))', 'Not containing 
text predicate'),
+        ],
+        
+        ' Logical Operations': [
+            ('g.V().and(__.out("knows"))', 'And with single traversal'),
+            ('g.V().and(__.out("knows"), __.has("age", P.gt(30)))', 'And with 
multiple traversals'),
+            ('g.V().or(__.out("knows"))', 'Or with single traversal'),
+            ('g.V().or(__.out("knows"), __.has("age", P.gt(30)))', 'Or with 
multiple traversals'),
+        ],
+        
+        ' Branching Methods': [
+            ('g.V().choose(__.has("age", P.gt(30)))', 'Choose with predicate 
only'),
+            ('g.V().choose(__.has("age", P.gt(30)), __.out("knows"))', 'Choose 
with true branch'),
+            ('g.V().choose(__.has("age", P.gt(30)), __.out("knows"), 
__.in("knows"))', 'Choose with both branches'),
+            ('g.V().coalesce(__.out("knows"))', 'Coalesce with single 
traversal'),
+            ('g.V().coalesce(__.out("knows"), __.out("likes"))', 'Coalesce 
with multiple traversals'),
+            ('g.V().optional(__.out("knows"))', 'Optional traversal'),
+            ('g.V().union(__.out("knows"))', 'Union with single traversal'),
+            ('g.V().union(__.out("knows"), __.out("likes"))', 'Union with 
multiple traversals'),
+        ],
+        
+        ' Ordering and Limiting': [
+            ('g.V().order()', 'Order without criteria'),
+            ('g.V().limit(10)', 'Limit results'),
+            ('g.V().range(0, 5)', 'Range with start and end'),
+            ('g.V().skip(10)', 'Skip results'),
+            ('g.V().tail(5)', 'Tail results'),
+            ('g.V().sample(3)', 'Sample results'),
+            ('g.V().coin(0.5)', 'Coin flip filter'),
+        ],
+        
+        ' Modification Methods': [
+            # Property operations
+            ('g.addV("person").property("name", "john")', 'Add vertex with 
property'),
+            ('g.V().property("age", 30)', 'Set property on vertex'),
+            ('g.V().property("active", true)', 'Set boolean property'),
+            
+            # Edge operations
+            ('g.V().addE("knows")', 'Add edge from vertex'),
+            ('g.V().has("name", "john").addE("knows")', 'Add edge after 
filter'),
+            
('g.addV("person").as("a").addV("person").addE("knows").from("a")', 'Add edge 
with from'),
+            ('g.addV("person").as("a").addV("person").addE("knows").to("a")', 
'Add edge with to'),
+        ],
+        
+        ' Deletion Methods': [
+            ('g.V().drop()', 'Drop all vertices'),
+            ('g.V().has("name", "temp").drop()', 'Drop vertices by filter'),
+            ('g.E().drop()', 'Drop all edges'),
+            ('g.E().hasLabel("temp").drop()', 'Drop edges by label'),
+        ],
+        
+        ' Terminal Methods': [
+            ('g.V().toList()', 'Convert to list'),
+            ('g.V().toSet()', 'Convert to set'),
+            ('g.V().next()', 'Get next result'),
+            ('g.V().hasNext()', 'Check if has next'),
+            ('g.V().iterate()', 'Iterate without results'),
+        ],
+        
+        ' Complex Queries': [
+            # Multi-step traversals
+            ('g.V().has("name", "marko").out("knows").values("name")', 'Find 
friends names'),
+            ('g.V().outE("knows").inV().has("age", P.gt(30))', 'Navigate 
through edges with filter'),
+            ('g.V().has("person", "name", 
"marko").out("created").values("name")', 'Find created projects'),
+            ('g.V().has("name", "marko").out("knows").out("created").dedup()', 
'Friends of friends creations'),
+            
+            # Complex filtering
+            ('g.V().has("person", "age", P.between(20, 40)).has("name", 
TextP.startingWith("m"))', 'Multiple filters'),
+            ('g.V().where(__.out("knows").has("name", 
"josh")).values("name")', 'Where with nested condition'),
+            ('g.V().filter(__.out("created").count().is(P.gt(1)))', 'Filter by 
creation count'),
+            
+            # Aggregation chains
+            ('g.V().hasLabel("person").values("age").mean()', 'Average age of 
persons'),
+            ('g.V().out("created").groupCount().by("name")', 'Group created 
items by name'),
+            
('g.V().hasLabel("person").group().by("age").by(__.values("name").fold())', 
'Group persons by age'),
+            
+            # Complex branching
+            ('g.V().choose(__.hasLabel("person"), __.out("created"), 
__.in("created"))', 'Choose by label'),
+            ('g.V().coalesce(__.out("knows"), __.out("created"), 
__.identity())', 'Multiple coalesce options'),
+            ('g.V().union(__.out("knows"), __.out("created")).dedup()', 'Union 
with deduplication'),
+            
+            # Property manipulation
+            ('g.addV("person").property("name", "alice").property("age", 25)', 
'Multiple properties'),
+            ('g.V().has("name", "marko").property("lastSeen", "2023-01-01")', 
'Update property'),
+            
+            # Edge creation with properties
+            ('g.V().has("name", "marko").addE("knows").to(__.V().has("name", 
"josh")).property("since", 2010)', 'Edge with property'),
+            
+            # Advanced patterns
+            ('g.V().repeat(__.out("knows")).times(2).dedup()', 'Repeat 
traversal'),
+            
('g.V().hasLabel("person").as("p").out("created").as("s").select("p", 
"s").by("name")', 'Path selection'),
+            ('g.V().match(__.as("a").out("knows").as("b"), 
__.as("b").out("created").as("c"))', 'Pattern matching'),
+        ]
+    }
+    
+    # 全面测试
+    total_tests = 0
+    passed_tests = 0
+    failed_tests = []
+    category_results = {}
+    
+    for category, tests in test_categories.items():
+        category_passed = 0
+        category_total = len(tests)
+        category_failed = []
+        
+        print(f'\n{category}')
+        print('=' * 80)
+        
+        for i, (query, description) in enumerate(tests, 1):
+            total_tests += 1
+            print(f'[{i:2d}/{category_total:2d}] {description}')
+            print(f'      Query: {query}')
+            
+            try:
+                # Create fresh visitor for each test to avoid state issues
+                test_visitor = GremlinTransVisitor()
+                result = test_visitor.parse_and_visit(query)
+                
+                if result and hasattr(result, 'steps') and len(result.steps) > 
0:
+                    print(f'      ✅ SUCCESS')
+                    passed_tests += 1
+                    category_passed += 1
+                    
+                    # Show step details in compact format
+                    step_names = [step.name for step in result.steps]
+                    print(f'      Steps: {" → ".join(step_names)}')
+                    
+                    # Check for complex objects
+                    complex_objects = []
+                    for step in result.steps:
+                        for param in step.params:
+                            if isinstance(param, Predicate):
+                                complex_objects.append(f"P.{param.operator}")
+                            elif isinstance(param, TextPredicate):
+                                
complex_objects.append(f"TextP.{param.operator}")
+                            elif isinstance(param, AnonymousTraversal):
+                                complex_objects.append("AnonymousTraversal")
+                            elif isinstance(param, Connector):
+                                
complex_objects.append(f"Connector({param.operator})")
+                            elif isinstance(param, Terminal):
+                                
complex_objects.append(f"Terminal({param.name})")
+                    
+                    if complex_objects:
+                        print(f'      Objects: {", 
".join(set(complex_objects))}')
+                        
+                else:
+                    print(f'      ❌ FAILED: Empty result')
+                    failed_tests.append((category, query, description, 'Empty 
result'))
+                    category_failed.append((query, description, 'Empty 
result'))
+                    
+            except Exception as e:
+                error_msg = str(e)[:100] + "..." if len(str(e)) > 100 else 
str(e)
+                print(f'      ❌ FAILED: {error_msg}')
+                failed_tests.append((category, query, description, str(e)))
+                category_failed.append((query, description, str(e)))
+        
+        category_results[category] = {
+            'passed': category_passed,
+            'total': category_total,
+            'failed': category_failed
+        }
+        
+        success_rate = (category_passed / category_total) * 100
+        status = '✅' if success_rate >= 90 else '⚠️' if success_rate >= 70 
else '❌'
+        print(f'\n{status} {category}: {category_passed}/{category_total} 
({success_rate:.1f}% success)')
+    
+    # Overall summary
+    print(f'\n\n{" COMPREHENSIVE TEST RESULTS":=^80}')
+    print(f'Total Tests: {total_tests}')
+    print(f' Passed: {passed_tests}')
+    print(f' Failed: {len(failed_tests)}')
+    print(f' Success Rate: {(passed_tests/total_tests)*100:.1f}%')
+    
+    # Category summary
+    print(f'\n{" CATEGORY BREAKDOWN":=^80}')
+    for category, results in category_results.items():
+        success_rate = (results['passed'] / results['total']) * 100
+        status = '✅' if success_rate >= 90 else '⚠️' if success_rate >= 70 
else '❌'
+        category_name = category.split(' ', 1)[1] if ' ' in category else 
category  # Remove emoji
+        print(f'{status} {category_name:<35} 
{results["passed"]:3d}/{results["total"]:3d} ({success_rate:5.1f}%)')
+    
+    # Failed tests summary
+    if failed_tests:
+        print(f'\n{"❌ FAILED TESTS ANALYSIS":=^80}')
+        failure_by_category = {}
+        for category, query, desc, error in failed_tests:
+            if category not in failure_by_category:
+                failure_by_category[category] = []
+            failure_by_category[category].append((query, desc, error))
+        
+        for category, failures in failure_by_category.items():
+            category_name = category.split(' ', 1)[1] if ' ' in category else 
category
+            print(f'\n{category_name} ({len(failures)} failures):')
+            for query, desc, error in failures[:5]:  # Show first 5 failures 
per category
+                print(f'  • {desc}')
+                print(f'    Query: {query}')
+                error_short = error[:60] + "..." if len(error) > 60 else error
+                print(f'    Error: {error_short}')
+    
+    # Visitor method coverage analysis
+    print(f'\n{"🔍 VISITOR METHOD COVERAGE":=^80}')
+    
+    # Count implemented visitor methods by analyzing the test results
+    visitor_methods_tested = set()
+    for category, results in category_results.items():
+        if results['passed'] > 0:
+            visitor_methods_tested.add(category)
+    
+    coverage_stats = {
+        'Spawn Methods': ['visitTraversalSourceSpawnMethod_V', 
'visitTraversalSourceSpawnMethod_E', 
+                         'visitTraversalSourceSpawnMethod_addV', 
'visitTraversalSourceSpawnMethod_addE',
+                         'visitTraversalSourceSpawnMethod_inject', 
'visitTraversalSourceSpawnMethod_io'],
+        'Navigation Methods': ['visitTraversalMethod_out', 
'visitTraversalMethod_in', 'visitTraversalMethod_both',
+                              'visitTraversalMethod_outE', 
'visitTraversalMethod_inE', 'visitTraversalMethod_bothE',
+                              'visitTraversalMethod_outV', 
'visitTraversalMethod_inV', 'visitTraversalMethod_bothV'],
+        'Filtering Methods': ['visitTraversalMethod_has_String_Object', 
'visitTraversalMethod_has_String_P',
+                             'visitTraversalMethod_has_String_String_Object', 
'visitTraversalMethod_hasLabel',
+                             'visitTraversalMethod_hasId', 
'visitTraversalMethod_hasKey', 'visitTraversalMethod_hasValue',
+                             'visitTraversalMethod_where', 
'visitTraversalMethod_filter', 'visitTraversalMethod_is',
+                             'visitTraversalMethod_not'],
+        'Predicate Methods': ['visitTraversalPredicate_gt', 
'visitTraversalPredicate_gte', 'visitTraversalPredicate_lt',
+                             'visitTraversalPredicate_lte', 
'visitTraversalPredicate_eq', 'visitTraversalPredicate_neq',
+                             'visitTraversalPredicate_between', 
'visitTraversalPredicate_inside', 'visitTraversalPredicate_outside',
+                             'visitTraversalPredicate_within', 
'visitTraversalPredicate_without'],
+        'TextPredicate Methods': ['visitTraversalPredicate_startingWith', 
'visitTraversalPredicate_endingWith',
+                                 'visitTraversalPredicate_containing', 
'visitTraversalPredicate_notStartingWith',
+                                 'visitTraversalPredicate_notEndingWith', 
'visitTraversalPredicate_notContaining'],
+        'Terminal Methods': ['visitTraversalMethod_toList', 
'visitTraversalMethod_toSet', 'visitTraversalMethod_next',
+                            'visitTraversalMethod_hasNext', 
'visitTraversalMethod_iterate']
+    }
+    
+    print("✅ 完全实现的类别:")
+    for category, results in category_results.items():
+        if results['passed'] == results['total'] and results['total'] > 0:
+            category_name = category.split(' ', 1)[1] if ' ' in category else 
category
+            print(f"  • {category_name}")
+    
+    print(f'\n🔍 复杂对象支持:')
+    print('  • Predicate 对象: P.gt, P.lt, P.eq, P.between, P.within, 等.')
+    print('  • TextPredicate 对象: TextP.startingWith, TextP.containing, 等.')  
+    print('  • AnonymousTraversal 对象: __.out(), __.has(), 等.')
+    print('  • Connector 对象: and(), or() 逻辑操作')
+    print('  • Terminal 对象: next(), toList(), iterate(), 等.')
+    
+    print(f'\n{" 实现完整性 ":=^80}')
+    print(f'此 GremlinTransVisitor 实现为以下功能提供全面支持:')
+    print(f'  ✅ 所有主要 Gremlin 遍历模式')
+    print(f'  ✅ 复杂谓词和文本谓词操作')
+    print(f'  ✅ 匿名遍历和嵌套操作')
+    print(f'  ✅ 逻辑连接器和分支操作')
+    print(f'  ✅ 属性操作和图修改')
+    print(f'  ✅ 聚合和转换操作')
+    print(f'  ✅ 终端操作和结果处理')
+    print(f'  ✅ 高级查询模式和多步骤遍历')
+    
+    if passed_tests == total_tests:
+        print(f'\n🎉 所有测试通过! 实现完全可用.')
+    else:
+        improvement_needed = total_tests - passed_tests
+        print(f'\n⚠️  {improvement_needed} 个测试需要关注以实现完整覆盖.')
+    
+    print(f'\n{"="*80}')
\ No newline at end of file

Reply via email to