linkrs_query/parser/parsing/dml_parser/
create.rs1use super::*;
2use crate::parser::parsing::pattern_common;
3
4impl DmlParser {
5 pub fn parse_create_data_after_token(
11 &mut self,
12 ctx: &mut ParseContext,
13 start_span: crate::parser::ast::types::Span,
14 ) -> Result<Stmt, ParseError> {
15 let mut patterns = Vec::new();
17
18 loop {
19 let pattern = self.parse_create_pattern(ctx)?;
20 patterns.push(pattern);
21
22 if !ctx.match_token(TokenKind::Comma) {
23 break;
24 }
25 }
26
27 let span = ctx.span_since(start_span.start);
28
29 Ok(Stmt::Create(CreateStmt {
30 span,
31 target: CreateTarget::Path { patterns },
32 if_not_exists: false,
33 }))
34 }
35
36 fn parse_create_pattern(
40 &mut self,
41 ctx: &mut ParseContext,
42 ) -> Result<crate::parser::ast::pattern::Pattern, ParseError> {
43 use crate::parser::ast::pattern::*;
44
45 let start_node = self.parse_node_pattern(ctx)?;
46
47 if !matches!(
52 ctx.current_token().kind,
53 TokenKind::Minus | TokenKind::BackArrow
54 ) {
55 return Ok(Pattern::Node(start_node));
56 }
57
58 let start = start_node.span.start;
59 let mut elements = vec![PathElement::Node(start_node)];
60 while matches!(
61 ctx.current_token().kind,
62 TokenKind::Minus | TokenKind::BackArrow
63 ) {
64 let edge = self.parse_edge_pattern(ctx)?;
65 elements.push(PathElement::CreateEdge(edge));
66
67 let node = self.parse_node_pattern(ctx)?;
68 elements.push(PathElement::Node(node));
69 }
70
71 let end_span = ctx.current_span();
72 Ok(Pattern::Path(PathPattern {
73 span: ctx.merge_span(start, end_span.end),
74 elements,
75 name: None,
76 }))
77 }
78
79 fn parse_node_pattern(
81 &mut self,
82 ctx: &mut ParseContext,
83 ) -> Result<crate::parser::ast::pattern::NodePattern, ParseError> {
84 use crate::parser::ast::pattern::*;
85
86 let start_span = ctx.current_span();
87 ctx.expect_token(TokenKind::LParen)?;
88
89 let variable = if ctx.current_token().kind.is_identifier() {
91 Some(ctx.expect_identifier()?)
92 } else {
93 None
94 };
95
96 let mut labels = Vec::new();
97 if ctx.match_token(TokenKind::Colon) {
98 loop {
99 let label = ctx.expect_identifier()?;
100 pattern_common::reject_qualified_reference(ctx, &label)?;
101 labels.push(label);
102 if !ctx.match_token(TokenKind::Colon) {
103 break;
104 }
105 }
106 }
107
108 let properties = if ctx.match_token(TokenKind::LBrace) {
109 let props = self.parse_property_map(ctx)?;
110 ctx.expect_token(TokenKind::RBrace)?;
111 Some(props)
112 } else {
113 None
114 };
115
116 ctx.expect_token(TokenKind::RParen)?;
117
118 let span = ctx.span_since(start_span.start);
119
120 Ok(NodePattern {
121 span,
122 variable,
123 labels,
124 properties,
125 predicates: Vec::new(),
126 })
127 }
128
129 fn parse_edge_pattern(
135 &mut self,
136 ctx: &mut ParseContext,
137 ) -> Result<crate::parser::ast::pattern::CreateEdgePattern, ParseError> {
138 use crate::parser::ast::pattern::*;
139
140 let start_span = ctx.current_span();
141
142 let incoming =
143 ctx.match_token(TokenKind::BackArrow) || ctx.match_token(TokenKind::LeftArrow);
144 ctx.expect_token(TokenKind::Minus)?;
145
146 ctx.expect_token(TokenKind::LBracket)?;
147
148 let variable = if ctx.current_token().kind.is_identifier() {
149 Some(ctx.expect_identifier()?)
150 } else {
151 None
152 };
153
154 let mut edge_types = Vec::new();
155 if ctx.match_token(TokenKind::Colon) {
156 let edge_type = ctx.expect_identifier()?;
157 pattern_common::reject_qualified_reference(ctx, &edge_type)?;
158 edge_types.push(edge_type);
159 }
160
161 let properties = if ctx.match_token(TokenKind::LBrace) {
162 let props = self.parse_property_map(ctx)?;
163 ctx.expect_token(TokenKind::RBrace)?;
164 Some(props)
165 } else {
166 None
167 };
168
169 ctx.expect_token(TokenKind::RBracket)?;
170
171 let closing = ctx.current_token().kind.clone();
173 let direction =
174 pattern_common::resolve_edge_direction(incoming, &closing).ok_or_else(|| {
175 ParseError::new(
176 crate::parser::core::error::ParseErrorKind::SyntaxError,
177 "Expected '-', '->', or '<-' after edge pattern".to_string(),
178 ctx.current_position(),
179 )
180 })?;
181 ctx.next_token();
182
183 let span = ctx.span_since(start_span.start);
184
185 Ok(CreateEdgePattern {
186 span,
187 variable,
188 edge_types,
189 properties,
190 direction,
191 })
192 }
193}