5757from .operations .call import Call
5858from .operations .create_node import CreateNode
5959from .operations .create_relationship import CreateRelationship
60+ from .operations .delete_node import DeleteNode
61+ from .operations .delete_relationship import DeleteRelationship
6062from .operations .limit import Limit
6163from .operations .load import Load
6264from .operations .match import Match
@@ -185,8 +187,8 @@ def _parse_tokenized(self, is_sub_query: bool = False) -> ASTNode:
185187 new_root .add_child (union )
186188 return new_root
187189
188- if not isinstance (operation , (Return , Call , CreateNode , CreateRelationship )):
189- raise ValueError ("Last statement must be a RETURN, WHERE, CALL, or CREATE statement" )
190+ if not isinstance (operation , (Return , Call , CreateNode , CreateRelationship , DeleteNode , DeleteRelationship )):
191+ raise ValueError ("Last statement must be a RETURN, WHERE, CALL, CREATE, or DELETE statement" )
190192
191193 return root
192194
@@ -198,7 +200,8 @@ def _parse_operation(self) -> Optional[Operation]:
198200 self ._parse_load () or
199201 self ._parse_call () or
200202 self ._parse_match () or
201- self ._parse_create ()
203+ self ._parse_create () or
204+ self ._parse_delete ()
202205 )
203206
204207 def _parse_with (self ) -> Optional [With ]:
@@ -431,6 +434,54 @@ def _parse_create(self) -> Optional[Operation]:
431434 else :
432435 return CreateNode (node , query )
433436
437+ def _parse_delete (self ) -> Optional [Operation ]:
438+ """Parse DELETE VIRTUAL statement for nodes and relationships."""
439+ if not self .token .is_delete ():
440+ return None
441+ self .set_next_token ()
442+ self ._expect_and_skip_whitespace_and_comments ()
443+ if not self .token .is_virtual ():
444+ raise ValueError ("Expected VIRTUAL" )
445+ self .set_next_token ()
446+ self ._expect_and_skip_whitespace_and_comments ()
447+
448+ node = self ._parse_node ()
449+ if node is None :
450+ raise ValueError ("Expected node definition" )
451+
452+ relationship : Optional [Relationship ] = None
453+ if self .token .is_subtract () and self .peek () and self .peek ().is_opening_bracket ():
454+ self .set_next_token () # skip -
455+ self .set_next_token () # skip [
456+ if not self .token .is_colon ():
457+ raise ValueError ("Expected ':' for relationship type" )
458+ self .set_next_token ()
459+ if not self .token .is_identifier_or_keyword ():
460+ raise ValueError ("Expected relationship type identifier" )
461+ rel_type = self .token .value or ""
462+ self .set_next_token ()
463+ if not self .token .is_closing_bracket ():
464+ raise ValueError ("Expected closing bracket for relationship definition" )
465+ self .set_next_token ()
466+ if not self .token .is_subtract ():
467+ raise ValueError ("Expected '-' for relationship definition" )
468+ self .set_next_token ()
469+ # Skip optional direction indicator '>'
470+ if self .token .is_greater_than ():
471+ self .set_next_token ()
472+ target = self ._parse_node ()
473+ if target is None :
474+ raise ValueError ("Expected target node definition" )
475+ relationship = Relationship ()
476+ relationship .type = rel_type
477+ relationship .source = node
478+ relationship .target = target
479+
480+ if relationship is not None :
481+ return DeleteRelationship (relationship )
482+ else :
483+ return DeleteNode (node )
484+
434485 def _parse_union (self ) -> Optional [Union ]:
435486 """Parse a UNION or UNION ALL keyword."""
436487 if not self .token .is_union ():
0 commit comments