1use super::Rule;
4use super::dml::{parse_property_kv, parse_query_pairs};
5use crate::ast::*;
6
7pub fn parse_expression(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
9 let rule = pair.as_rule();
11 let children: Vec<_> = pair.clone().into_inner().collect();
12
13 if rule == Rule::case_expr {
15 return parse_case_expr(pair);
16 }
17
18 if rule == Rule::comparison_expr {
21 if children.len() == 1 {
22 return parse_expression(children[0].clone());
23 }
24 let left = parse_expression(children[0].clone())?;
25 if children.len() == 2 {
26 return parse_comparison_suffix(children[1].clone(), left);
28 }
29 if children.len() == 3 {
30 let op_str = children[1].as_str();
32 let op = match op_str {
33 "=" => BinaryOp::Equal,
34 "<>" => BinaryOp::NotEqual,
35 "<" => BinaryOp::LessThan,
36 ">" => BinaryOp::GreaterThan,
37 "<=" => BinaryOp::LessThanOrEqual,
38 ">=" => BinaryOp::GreaterThanOrEqual,
39 _ => return Err(format!("Unknown comparison_op: {}", op_str)),
40 };
41 let right = parse_expression(children[2].clone())?;
42 return Ok(Expression::BinaryOp(op, Box::new(left), Box::new(right)));
43 }
44 return Err(format!("Unexpected comparison_expr with {} children", children.len()));
45 }
46
47 if matches!(
49 rule,
50 Rule::expression
51 | Rule::or_expr
52 | Rule::xor_expr
53 | Rule::and_expr
54 | Rule::not_expr
55 | Rule::additive_expr
56 | Rule::multiplicative_expr
57 | Rule::unary_expr
58 ) {
59 if children.len() == 1 {
60 return parse_expression(children[0].clone());
61 }
62 if children.len() >= 3 {
63 let mut result = parse_expression(children[0].clone())?;
64 let mut i = 1;
65 while i + 1 < children.len() {
66 let op = match children[i].as_str() {
67 "OR" => BinaryOp::Or,
68 "XOR" => BinaryOp::Xor,
69 "AND" => BinaryOp::And,
70 "+" => BinaryOp::Add,
71 "-" => BinaryOp::Subtract,
72 "*" => BinaryOp::Multiply,
73 "/" => BinaryOp::Divide,
74 "%" => BinaryOp::Modulo,
75 _ => return Err(format!("Unknown op: {}", children[i].as_str())),
76 };
77 let right = parse_expression(children[i + 1].clone())?;
78 result = Expression::BinaryOp(op, Box::new(result), Box::new(right));
79 i += 2;
80 }
81 return Ok(result);
82 }
83 }
84
85 if rule == Rule::not_expr && children.len() == 2 {
87 let inner = parse_expression(children[1].clone())?;
88 return Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)));
89 }
90
91 match rule {
92 Rule::primary => {
93 if children.len() == 2
96 && children[0].as_rule() == Rule::variable
97 && children[1].as_rule() == Rule::function_args
98 {
99 let mut name = children[0].as_str().to_string();
100 let mut args = Vec::new();
101 let mut pending_distinct = false;
102 for c in children[1].clone().into_inner() {
103 if c.as_rule() == Rule::distinct_flag {
104 pending_distinct = true;
105 } else if c.as_rule() == Rule::star {
106 args.push(Expression::Star);
107 } else if c.as_rule() == Rule::expression {
108 args.push(parse_expression(c)?);
109 }
110 }
111 if pending_distinct {
112 name = mangle_distinct_aggregate(&name)?;
113 if args.len() != 1 || matches!(args[0], Expression::Star) {
114 return Err("DISTINCT requires exactly one non-* argument".into());
115 }
116 }
117 return Ok(Expression::FunctionCall(name, args));
118 }
119 parse_expression(children.into_iter().next().ok_or("Empty primary")?)
120 }
121 Rule::literal => parse_literal(children.into_iter().next().ok_or("Empty literal")?),
122 Rule::string => Ok(Expression::Constant(Constant::String(unescape_string(pair.as_str())))),
123 Rule::integer => {
124 let v: i64 = pair.as_str().parse().map_err(|e| format!("Int: {e}"))?;
125 Ok(Expression::Constant(Constant::Integer(v)))
126 }
127 Rule::float => {
128 let v: f64 = pair.as_str().parse().map_err(|e| format!("Float: {e}"))?;
129 Ok(Expression::Constant(Constant::Float(v)))
130 }
131 Rule::boolean_literal => Ok(Expression::Constant(Constant::Bool(
132 pair.as_str().to_uppercase() == "TRUE",
133 ))),
134 Rule::null_literal => Ok(Expression::Constant(Constant::Null)),
135 Rule::variable => Ok(Expression::Variable(pair.as_str().to_string())),
136 Rule::parameter => {
137 let name = pair.as_str().strip_prefix('$').unwrap_or(pair.as_str()).to_string();
138 Ok(Expression::Parameter(name))
139 }
140 Rule::list_literal => {
141 let items = children
142 .into_iter()
143 .filter(|c| c.as_rule() == Rule::expression)
144 .map(parse_expression)
145 .collect::<Result<Vec<_>, _>>()?;
146 Ok(Expression::List(items))
147 }
148 Rule::map_literal => {
149 let mut entries = Vec::new();
150 for c in children {
151 if c.as_rule() == Rule::property_key_value {
152 entries.push(parse_property_kv(c)?);
153 }
154 }
155 Ok(Expression::Map(entries))
156 }
157 Rule::postfix_expr => {
158 let mut children = pair.clone().into_inner();
159 let mut result = parse_expression(children.next().ok_or("Empty postfix")?)?;
160 for child in children {
161 if child.as_rule() == Rule::property_access {
162 let prop = child.into_inner().next().unwrap().as_str().to_string();
163 result = Expression::PropertyAccess(Box::new(result), prop);
164 } else if child.as_rule() == Rule::expression {
165 let idx = parse_expression(child)?;
172 let one = Expression::Constant(Constant::Integer(1));
173 result = Expression::FunctionCall(
174 "list_extract".to_string(),
175 vec![
176 result,
177 Expression::BinaryOp(BinaryOp::Add, Box::new(idx), Box::new(one)),
178 ],
179 );
180 }
181 }
182 Ok(result)
183 }
184 Rule::exists_subquery => {
185 for c in children {
187 if c.as_rule() == Rule::query_statement {
188 let query = parse_query_pairs(c)?;
189 return Ok(Expression::ExistsSubquery(Box::new(query)));
190 }
191 }
192 Err("EXISTS subquery requires a query statement".into())
193 }
194 Rule::list_predicate => {
195 let children: Vec<_> = pair.clone().into_inner().collect();
199 if children.len() < 3 {
200 return Err(format!("Invalid list predicate syntax: {} children", children.len()));
201 }
202 let full_text = pair.as_str();
204 let quantifier_str = full_text.split('(').next().unwrap_or("").to_uppercase();
205 let quantifier = match quantifier_str.as_str() {
206 "ANY" => Quantifier::Any,
207 "ALL" => Quantifier::All,
208 "NONE" => Quantifier::None,
209 "SINGLE" => Quantifier::Single,
210 _ => return Err(format!("Unknown quantifier: {}", quantifier_str)),
211 };
212 let var_name = children[0].as_str().to_string();
213 let list = parse_expression(children[1].clone())?;
214 let predicate = parse_expression(children[2].clone())?;
215 Ok(Expression::ListPredicate {
216 quantifier,
217 list: Box::new(list),
218 var_name,
219 predicate: Box::new(predicate),
220 })
221 }
222 Rule::lambda_expr => {
223 let mut children = pair.clone().into_inner();
224 let var_name = children.next().ok_or("Lambda missing variable")?.as_str().to_string();
225 let body = parse_expression(children.next().ok_or("Lambda missing body")?)?;
226 Ok(Expression::Lambda {
227 var_name,
228 body: Box::new(body),
229 })
230 }
231 Rule::function_args => {
232 if children.is_empty() {
236 return Ok(Expression::Constant(Constant::Null));
237 }
238 let mut name = pair.as_str().split('(').next().unwrap_or("").to_string();
240 let mut pending_distinct = false;
241 let mut args: Vec<Expression> = Vec::new();
242 for c in children.into_iter() {
243 if c.as_rule() == Rule::distinct_flag {
244 pending_distinct = true;
245 } else if c.as_rule() == Rule::expression {
246 args.push(parse_expression(c)?);
247 }
248 }
249 if pending_distinct {
250 name = mangle_distinct_aggregate(&name)?;
251 if args.len() != 1 {
252 return Err("DISTINCT requires exactly one argument".into());
253 }
254 }
255 Ok(Expression::FunctionCall(name, args))
256 }
257 Rule::property_access => Err("property_access should be handled within postfix_expr".into()),
258 _ => {
259 if let Some(child) = children.into_iter().next() {
261 parse_expression(child)
262 } else {
263 Err(format!("Cannot parse: {:?}", rule))
264 }
265 }
266 }
267}
268
269pub fn parse_comparison_suffix(pair: pest::iterators::Pair<Rule>, left: Expression) -> Result<Expression, String> {
271 fn get_rhs(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
273 let rhs_pair = pair
274 .into_inner()
275 .find(|p| p.as_rule() == Rule::additive_expr)
276 .ok_or_else(|| "Operator missing right-hand expression".to_string())?;
277 parse_expression(rhs_pair)
278 }
279
280 match pair.as_rule() {
281 Rule::is_check_op => {
282 let text = pair.as_str();
283 if text.contains("NOT") {
284 Ok(Expression::UnaryOp(UnaryOp::IsNotNull, Box::new(left)))
285 } else {
286 Ok(Expression::UnaryOp(UnaryOp::IsNull, Box::new(left)))
287 }
288 }
289 Rule::in_op => {
290 let right = get_rhs(pair)?;
291 Ok(Expression::BinaryOp(BinaryOp::In, Box::new(left), Box::new(right)))
292 }
293 Rule::not_in_op => {
294 let right = get_rhs(pair)?;
295 Ok(Expression::BinaryOp(BinaryOp::NotIn, Box::new(left), Box::new(right)))
296 }
297 Rule::starts_with_op => {
298 let right = get_rhs(pair)?;
299 Ok(Expression::BinaryOp(
300 BinaryOp::StartsWith,
301 Box::new(left),
302 Box::new(right),
303 ))
304 }
305 Rule::not_starts_with_op => {
306 let right = get_rhs(pair)?;
307 let inner = Expression::BinaryOp(BinaryOp::StartsWith, Box::new(left), Box::new(right));
308 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
309 }
310 Rule::ends_with_op => {
311 let right = get_rhs(pair)?;
312 Ok(Expression::BinaryOp(
313 BinaryOp::EndsWith,
314 Box::new(left),
315 Box::new(right),
316 ))
317 }
318 Rule::not_ends_with_op => {
319 let right = get_rhs(pair)?;
320 let inner = Expression::BinaryOp(BinaryOp::EndsWith, Box::new(left), Box::new(right));
321 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
322 }
323 Rule::contains_op => {
324 let right = get_rhs(pair)?;
325 Ok(Expression::BinaryOp(
326 BinaryOp::Contains,
327 Box::new(left),
328 Box::new(right),
329 ))
330 }
331 Rule::not_contains_op => {
332 let right = get_rhs(pair)?;
333 let inner = Expression::BinaryOp(BinaryOp::Contains, Box::new(left), Box::new(right));
334 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
335 }
336 Rule::like_op => {
337 let right = get_rhs(pair)?;
338 Ok(Expression::BinaryOp(BinaryOp::Like, Box::new(left), Box::new(right)))
339 }
340 Rule::between_op => {
341 let mut children = pair.into_inner();
342 let lower_pair = children
343 .find(|p| p.as_rule() == Rule::additive_expr)
344 .ok_or_else(|| "BETWEEN missing lower bound expression".to_string())?;
345 let upper_pair = children
346 .find(|p| p.as_rule() == Rule::additive_expr)
347 .ok_or_else(|| "BETWEEN missing upper bound expression".to_string())?;
348 let lower_expr = parse_expression(lower_pair)?;
349 let upper_expr = parse_expression(upper_pair)?;
350 let ge = Expression::BinaryOp(
351 BinaryOp::GreaterThanOrEqual,
352 Box::new(left.clone()),
353 Box::new(lower_expr),
354 );
355 let le = Expression::BinaryOp(BinaryOp::LessThanOrEqual, Box::new(left), Box::new(upper_expr));
356 Ok(Expression::BinaryOp(BinaryOp::And, Box::new(ge), Box::new(le)))
357 }
358 r => Err(format!("Unknown comparison suffix: {:?}", r)),
359 }
360}
361
362pub fn parse_case_expr(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
364 let mut subject: Option<Expression> = None;
365 let mut alternatives: Vec<CaseAlternative> = Vec::new();
366 let mut else_expr: Option<Expression> = None;
367
368 for child in pair.into_inner() {
369 match child.as_rule() {
370 Rule::case_subject => {
371 if let Some(expr_pair) = child.into_inner().next() {
373 subject = Some(parse_expression(expr_pair)?);
374 }
375 }
376 Rule::case_when => {
377 let mut exprs = child
379 .into_inner()
380 .filter(|p| p.as_rule() == Rule::expression)
381 .map(parse_expression)
382 .collect::<Result<Vec<_>, _>>()?;
383 if exprs.len() < 2 {
384 return Err("CASE WHEN clause requires both WHEN and THEN expressions".into());
385 }
386 let then = exprs.remove(1);
387 let when = exprs.remove(0);
388 alternatives.push(CaseAlternative { when, then });
389 }
390 Rule::case_else => {
391 if let Some(expr_pair) = child.into_inner().find(|p| p.as_rule() == Rule::expression) {
392 else_expr = Some(parse_expression(expr_pair)?);
393 }
394 }
395 _ => {} }
397 }
398
399 if alternatives.is_empty() {
400 return Err("CASE expression requires at least one WHEN clause".into());
401 }
402
403 Ok(Expression::Case(CaseExpr {
404 subject: subject.map(Box::new),
405 alternatives,
406 else_expr: else_expr.map(Box::new),
407 }))
408}
409
410pub fn parse_literal(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
412 match pair.as_rule() {
413 Rule::string => Ok(Expression::Constant(Constant::String(unescape_string(pair.as_str())))),
414 Rule::integer => {
415 let s = pair.as_str();
416 Ok(Expression::Constant(Constant::Integer(
417 s.trim().parse().map_err(|e| format!("Int: {e} (for string '{s}')"))?,
418 )))
419 }
420 Rule::float => {
421 let s = pair.as_str();
422 Ok(Expression::Constant(Constant::Float(
423 s.trim().parse().map_err(|e| format!("Float: {e} (for string '{s}')"))?,
424 )))
425 }
426 Rule::boolean_literal => Ok(Expression::Constant(Constant::Bool(
427 pair.as_str().to_uppercase() == "TRUE",
428 ))),
429 Rule::null_literal => Ok(Expression::Constant(Constant::Null)),
430 _ => Err(format!("Unknown literal: {:?}", pair.as_rule())),
431 }
432}
433
434fn mangle_distinct_aggregate(name: &str) -> Result<String, String> {
441 let lower = name.to_lowercase();
442 let is_aggregate = matches!(
443 lower.as_str(),
444 "count" | "sum" | "avg" | "min" | "max" | "collect" | "stddev" | "variance"
445 );
446 if !is_aggregate {
447 return Err(format!(
448 "DISTINCT is only supported in aggregate functions, got '{name}'"
449 ));
450 }
451 Ok(format!("{lower}_distinct"))
452}
453
454pub fn unescape_string(s: &str) -> String {
456 let s = s.trim_matches(|c| c == '"' || c == '\'');
457 let mut r = String::with_capacity(s.len());
458 let mut chars = s.chars();
459 while let Some(c) = chars.next() {
460 if c == '\\' {
461 match chars.next() {
462 Some('n') => r.push('\n'),
463 Some('t') => r.push('\t'),
464 Some('r') => r.push('\r'),
465 Some('\\') => r.push('\\'),
466 Some('"') => r.push('"'),
467 Some('\'') => r.push('\''),
468 Some(o) => {
469 r.push('\\');
470 r.push(o);
471 }
472 None => r.push('\\'),
473 }
474 } else {
475 r.push(c);
476 }
477 }
478 r
479}