shape_ast/parser/expressions/control_flow/
mod.rs1use crate::ast::{Expr, FromQueryExpr, OrderBySpec, QueryClause};
17use crate::error::{Result, ShapeError};
18use crate::parser::{Rule, pair_location};
19use pest::iterators::Pair;
20
21use super::super::pair_span;
22
23mod conditionals;
24mod loops;
25mod pattern_matching;
26
27pub use conditionals::parse_if_expr;
29pub use loops::{
30 parse_async_let_expr, parse_async_scope_expr, parse_block_expr, parse_break_expr,
31 parse_for_expr, parse_let_expr, parse_loop_expr, parse_return_expr, parse_while_expr,
32};
33pub use pattern_matching::{parse_match_expr, parse_pattern};
34
35pub fn parse_from_query_expr(pair: Pair<Rule>) -> Result<Expr> {
38 let span = pair_span(&pair);
39 let pair_loc = pair_location(&pair);
40 let mut inner = pair.into_inner();
41
42 let variable_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
44 message: "expected variable name in from clause".to_string(),
45 location: Some(pair_loc.clone()),
46 })?;
47 let variable = variable_pair.as_str().to_string();
48
49 let source_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
50 message: "expected source expression in from clause".to_string(),
51 location: Some(pair_loc.clone()),
52 })?;
53 let source = Box::new(parse_query_source_expr(source_pair)?);
54
55 let mut clauses = Vec::new();
57 let mut select = None;
58
59 for part in inner {
60 match part.as_rule() {
61 Rule::query_clause => {
62 let clause_inner =
63 part.into_inner()
64 .next()
65 .ok_or_else(|| ShapeError::ParseError {
66 message: "expected query clause content".to_string(),
67 location: Some(pair_loc.clone()),
68 })?;
69 let clause = parse_query_clause(clause_inner)?;
70 clauses.push(clause);
71 }
72 Rule::where_query_clause => {
73 clauses.push(parse_where_query_clause(part)?);
74 }
75 Rule::order_by_query_clause => {
76 clauses.push(parse_order_by_query_clause(part)?);
77 }
78 Rule::group_by_query_clause => {
79 clauses.push(parse_group_by_query_clause(part)?);
80 }
81 Rule::join_query_clause => {
82 clauses.push(parse_join_query_clause(part)?);
83 }
84 Rule::let_query_clause => {
85 clauses.push(parse_let_query_clause(part)?);
86 }
87 Rule::select_query_clause => {
88 let select_inner =
89 part.into_inner()
90 .next()
91 .ok_or_else(|| ShapeError::ParseError {
92 message: "expected expression after select".to_string(),
93 location: Some(pair_loc.clone()),
94 })?;
95 select = Some(Box::new(parse_query_expr_inner(select_inner)?));
96 }
97 _ => {}
98 }
99 }
100
101 let select = select.ok_or_else(|| ShapeError::ParseError {
102 message: "from query requires a select clause".to_string(),
103 location: Some(pair_loc),
104 })?;
105
106 Ok(Expr::FromQuery(
107 Box::new(FromQueryExpr {
108 variable,
109 source,
110 clauses,
111 select,
112 }),
113 span,
114 ))
115}
116
117fn parse_query_source_expr(pair: Pair<Rule>) -> Result<Expr> {
119 match pair.as_rule() {
120 Rule::query_source_expr => {
121 let inner = pair
122 .into_inner()
123 .next()
124 .ok_or_else(|| ShapeError::ParseError {
125 message: "expected source expression".to_string(),
126 location: None,
127 })?;
128 super::parse_postfix_expr(inner)
129 }
130 _ => super::parse_postfix_expr(pair),
131 }
132}
133
134fn parse_query_expr_inner(pair: Pair<Rule>) -> Result<Expr> {
136 match pair.as_rule() {
137 Rule::query_expr_inner => {
138 let inner = pair
139 .into_inner()
140 .next()
141 .ok_or_else(|| ShapeError::ParseError {
142 message: "expected expression".to_string(),
143 location: None,
144 })?;
145 super::binary_ops::parse_comparison_expr(inner)
146 }
147 _ => super::binary_ops::parse_comparison_expr(pair),
148 }
149}
150
151fn parse_query_clause(pair: Pair<Rule>) -> Result<QueryClause> {
152 match pair.as_rule() {
153 Rule::where_query_clause => parse_where_query_clause(pair),
154 Rule::order_by_query_clause => parse_order_by_query_clause(pair),
155 Rule::group_by_query_clause => parse_group_by_query_clause(pair),
156 Rule::join_query_clause => parse_join_query_clause(pair),
157 Rule::let_query_clause => parse_let_query_clause(pair),
158 _ => Err(ShapeError::ParseError {
159 message: format!("unexpected query clause: {:?}", pair.as_rule()),
160 location: Some(pair_location(&pair)),
161 }),
162 }
163}
164
165fn parse_where_query_clause(pair: Pair<Rule>) -> Result<QueryClause> {
166 let pair_loc = pair_location(&pair);
167 let condition_pair = pair
168 .into_inner()
169 .next()
170 .ok_or_else(|| ShapeError::ParseError {
171 message: "expected condition expression in where clause".to_string(),
172 location: Some(pair_loc),
173 })?;
174 let condition = parse_query_expr_inner(condition_pair)?;
175 Ok(QueryClause::Where(Box::new(condition)))
176}
177
178fn parse_order_by_query_clause(pair: Pair<Rule>) -> Result<QueryClause> {
179 let mut specs = Vec::new();
180 for inner in pair.into_inner() {
181 if inner.as_rule() == Rule::order_by_spec {
182 specs.push(parse_order_by_spec(inner)?);
183 }
184 }
185 Ok(QueryClause::OrderBy(specs))
186}
187
188fn parse_order_by_spec(pair: Pair<Rule>) -> Result<OrderBySpec> {
189 let pair_loc = pair_location(&pair);
190 let mut inner = pair.into_inner();
191 let key_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
192 message: "expected key expression in order by".to_string(),
193 location: Some(pair_loc),
194 })?;
195 let key = Box::new(super::parse_postfix_expr(key_pair)?);
196 let descending = inner
197 .next()
198 .map(|dir| dir.as_str() == "desc")
199 .unwrap_or(false);
200 Ok(OrderBySpec { key, descending })
201}
202
203fn parse_group_by_query_clause(pair: Pair<Rule>) -> Result<QueryClause> {
204 let pair_loc = pair_location(&pair);
205 let mut inner = pair.into_inner();
206
207 let element_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
208 message: "expected element expression in group by".to_string(),
209 location: Some(pair_loc.clone()),
210 })?;
211 let element = Box::new(super::parse_postfix_expr(element_pair)?);
212
213 let key_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
214 message: "expected key expression in group by".to_string(),
215 location: Some(pair_loc),
216 })?;
217 let key = Box::new(super::parse_postfix_expr(key_pair)?);
218
219 let into_var = inner.next().map(|p| p.as_str().to_string());
220
221 Ok(QueryClause::GroupBy {
222 element,
223 key,
224 into_var,
225 })
226}
227
228fn parse_join_query_clause(pair: Pair<Rule>) -> Result<QueryClause> {
229 let pair_loc = pair_location(&pair);
230 let mut inner = pair.into_inner();
231
232 let variable = inner
233 .next()
234 .ok_or_else(|| ShapeError::ParseError {
235 message: "expected variable name in join".to_string(),
236 location: Some(pair_loc.clone()),
237 })?
238 .as_str()
239 .to_string();
240
241 let source_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
242 message: "expected source expression in join".to_string(),
243 location: Some(pair_loc.clone()),
244 })?;
245 let source = Box::new(super::parse_postfix_expr(source_pair)?);
246
247 let left_key_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
248 message: "expected left key expression in join".to_string(),
249 location: Some(pair_loc.clone()),
250 })?;
251 let left_key = Box::new(super::parse_postfix_expr(left_key_pair)?);
252
253 let right_key_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
254 message: "expected right key expression in join".to_string(),
255 location: Some(pair_loc),
256 })?;
257 let right_key = Box::new(super::parse_postfix_expr(right_key_pair)?);
258
259 let into_var = inner.next().map(|p| p.as_str().to_string());
260
261 Ok(QueryClause::Join {
262 variable,
263 source,
264 left_key,
265 right_key,
266 into_var,
267 })
268}
269
270fn parse_let_query_clause(pair: Pair<Rule>) -> Result<QueryClause> {
271 let pair_loc = pair_location(&pair);
272 let mut inner = pair.into_inner();
273
274 let variable = inner
275 .next()
276 .ok_or_else(|| ShapeError::ParseError {
277 message: "expected variable name in let clause".to_string(),
278 location: Some(pair_loc.clone()),
279 })?
280 .as_str()
281 .to_string();
282
283 let value_pair = inner.next().ok_or_else(|| ShapeError::ParseError {
284 message: "expected value expression in let clause".to_string(),
285 location: Some(pair_loc),
286 })?;
287 let value = Box::new(parse_query_expr_inner(value_pair)?);
288
289 Ok(QueryClause::Let { variable, value })
290}