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 name = children[0].as_str().to_string();
100 let mut args = Vec::new();
101 let args_text = children[1].as_str().replace(" ", "");
102 for c in children[1].clone().into_inner() {
103 if c.as_rule() == Rule::expression {
104 args.push(parse_expression(c)?);
105 }
106 }
107 if args.is_empty() && args_text == "(*)" {
108 args.push(Expression::Star);
109 }
110 return Ok(Expression::FunctionCall(name, args));
111 }
112 parse_expression(children.into_iter().next().ok_or("Empty primary")?)
113 }
114 Rule::literal => parse_literal(children.into_iter().next().ok_or("Empty literal")?),
115 Rule::string => Ok(Expression::Constant(Constant::String(unescape_string(pair.as_str())))),
116 Rule::integer => {
117 let v: i64 = pair.as_str().parse().map_err(|e| format!("Int: {e}"))?;
118 Ok(Expression::Constant(Constant::Integer(v)))
119 }
120 Rule::float => {
121 let v: f64 = pair.as_str().parse().map_err(|e| format!("Float: {e}"))?;
122 Ok(Expression::Constant(Constant::Float(v)))
123 }
124 Rule::boolean_literal => Ok(Expression::Constant(Constant::Bool(
125 pair.as_str().to_uppercase() == "TRUE",
126 ))),
127 Rule::null_literal => Ok(Expression::Constant(Constant::Null)),
128 Rule::variable => Ok(Expression::Variable(pair.as_str().to_string())),
129 Rule::parameter => {
130 let name = pair.as_str().strip_prefix('$').unwrap_or(pair.as_str()).to_string();
131 Ok(Expression::Parameter(name))
132 }
133 Rule::list_literal => {
134 let items = children
135 .into_iter()
136 .filter(|c| c.as_rule() == Rule::expression)
137 .map(parse_expression)
138 .collect::<Result<Vec<_>, _>>()?;
139 Ok(Expression::List(items))
140 }
141 Rule::map_literal => {
142 let mut entries = Vec::new();
143 for c in children {
144 if c.as_rule() == Rule::property_key_value {
145 entries.push(parse_property_kv(c)?);
146 }
147 }
148 Ok(Expression::Map(entries))
149 }
150 Rule::postfix_expr => {
151 let mut children = pair.clone().into_inner();
152 let mut result = parse_expression(children.next().ok_or("Empty postfix")?)?;
153 for child in children {
154 if child.as_rule() == Rule::property_access {
155 let prop = child.into_inner().next().unwrap().as_str().to_string();
156 result = Expression::PropertyAccess(Box::new(result), prop);
157 } else if child.as_rule() == Rule::expression {
158 let idx = parse_expression(child)?;
165 let one = Expression::Constant(Constant::Integer(1));
166 result = Expression::FunctionCall(
167 "list_extract".to_string(),
168 vec![
169 result,
170 Expression::BinaryOp(BinaryOp::Add, Box::new(idx), Box::new(one)),
171 ],
172 );
173 }
174 }
175 Ok(result)
176 }
177 Rule::exists_subquery => {
178 for c in children {
180 if c.as_rule() == Rule::query_statement {
181 let query = parse_query_pairs(c)?;
182 return Ok(Expression::ExistsSubquery(Box::new(query)));
183 }
184 }
185 Err("EXISTS subquery requires a query statement".into())
186 }
187 Rule::list_predicate => {
188 let children: Vec<_> = pair.clone().into_inner().collect();
192 if children.len() < 3 {
193 return Err(format!("Invalid list predicate syntax: {} children", children.len()));
194 }
195 let full_text = pair.as_str();
197 let quantifier_str = full_text.split('(').next().unwrap_or("").to_uppercase();
198 let quantifier = match quantifier_str.as_str() {
199 "ANY" => Quantifier::Any,
200 "ALL" => Quantifier::All,
201 "NONE" => Quantifier::None,
202 "SINGLE" => Quantifier::Single,
203 _ => return Err(format!("Unknown quantifier: {}", quantifier_str)),
204 };
205 let var_name = children[0].as_str().to_string();
206 let list = parse_expression(children[1].clone())?;
207 let predicate = parse_expression(children[2].clone())?;
208 Ok(Expression::ListPredicate {
209 quantifier,
210 list: Box::new(list),
211 var_name,
212 predicate: Box::new(predicate),
213 })
214 }
215 Rule::lambda_expr => {
216 let mut children = pair.clone().into_inner();
217 let var_name = children.next().ok_or("Lambda missing variable")?.as_str().to_string();
218 let body = parse_expression(children.next().ok_or("Lambda missing body")?)?;
219 Ok(Expression::Lambda {
220 var_name,
221 body: Box::new(body),
222 })
223 }
224 Rule::function_args => {
225 if children.is_empty() {
229 return Ok(Expression::Constant(Constant::Null));
230 }
231 let name = pair.as_str().split('(').next().unwrap_or("").to_string();
233 let args = children
234 .into_iter()
235 .filter(|c| c.as_rule() == Rule::expression)
236 .map(parse_expression)
237 .collect::<Result<Vec<_>, _>>()?;
238 Ok(Expression::FunctionCall(name, args))
239 }
240 Rule::property_access => Err("property_access should be handled within postfix_expr".into()),
241 _ => {
242 if let Some(child) = children.into_iter().next() {
244 parse_expression(child)
245 } else {
246 Err(format!("Cannot parse: {:?}", rule))
247 }
248 }
249 }
250}
251
252pub fn parse_comparison_suffix(pair: pest::iterators::Pair<Rule>, left: Expression) -> Result<Expression, String> {
254 fn get_rhs(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
256 let rhs_pair = pair
257 .into_inner()
258 .find(|p| p.as_rule() == Rule::additive_expr)
259 .ok_or_else(|| "Operator missing right-hand expression".to_string())?;
260 parse_expression(rhs_pair)
261 }
262
263 match pair.as_rule() {
264 Rule::is_check_op => {
265 let text = pair.as_str();
266 if text.contains("NOT") {
267 Ok(Expression::UnaryOp(UnaryOp::IsNotNull, Box::new(left)))
268 } else {
269 Ok(Expression::UnaryOp(UnaryOp::IsNull, Box::new(left)))
270 }
271 }
272 Rule::in_op => {
273 let right = get_rhs(pair)?;
274 Ok(Expression::BinaryOp(BinaryOp::In, Box::new(left), Box::new(right)))
275 }
276 Rule::not_in_op => {
277 let right = get_rhs(pair)?;
278 Ok(Expression::BinaryOp(BinaryOp::NotIn, Box::new(left), Box::new(right)))
279 }
280 Rule::starts_with_op => {
281 let right = get_rhs(pair)?;
282 Ok(Expression::BinaryOp(
283 BinaryOp::StartsWith,
284 Box::new(left),
285 Box::new(right),
286 ))
287 }
288 Rule::not_starts_with_op => {
289 let right = get_rhs(pair)?;
290 let inner = Expression::BinaryOp(BinaryOp::StartsWith, Box::new(left), Box::new(right));
291 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
292 }
293 Rule::ends_with_op => {
294 let right = get_rhs(pair)?;
295 Ok(Expression::BinaryOp(
296 BinaryOp::EndsWith,
297 Box::new(left),
298 Box::new(right),
299 ))
300 }
301 Rule::not_ends_with_op => {
302 let right = get_rhs(pair)?;
303 let inner = Expression::BinaryOp(BinaryOp::EndsWith, Box::new(left), Box::new(right));
304 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
305 }
306 Rule::contains_op => {
307 let right = get_rhs(pair)?;
308 Ok(Expression::BinaryOp(
309 BinaryOp::Contains,
310 Box::new(left),
311 Box::new(right),
312 ))
313 }
314 Rule::not_contains_op => {
315 let right = get_rhs(pair)?;
316 let inner = Expression::BinaryOp(BinaryOp::Contains, Box::new(left), Box::new(right));
317 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
318 }
319 Rule::like_op => {
320 let right = get_rhs(pair)?;
321 Ok(Expression::BinaryOp(BinaryOp::Like, Box::new(left), Box::new(right)))
322 }
323 Rule::between_op => {
324 let mut children = pair.into_inner();
325 let lower_pair = children
326 .find(|p| p.as_rule() == Rule::additive_expr)
327 .ok_or_else(|| "BETWEEN missing lower bound expression".to_string())?;
328 let upper_pair = children
329 .find(|p| p.as_rule() == Rule::additive_expr)
330 .ok_or_else(|| "BETWEEN missing upper bound expression".to_string())?;
331 let lower_expr = parse_expression(lower_pair)?;
332 let upper_expr = parse_expression(upper_pair)?;
333 let ge = Expression::BinaryOp(
334 BinaryOp::GreaterThanOrEqual,
335 Box::new(left.clone()),
336 Box::new(lower_expr),
337 );
338 let le = Expression::BinaryOp(BinaryOp::LessThanOrEqual, Box::new(left), Box::new(upper_expr));
339 Ok(Expression::BinaryOp(BinaryOp::And, Box::new(ge), Box::new(le)))
340 }
341 r => Err(format!("Unknown comparison suffix: {:?}", r)),
342 }
343}
344
345pub fn parse_case_expr(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
347 let mut subject: Option<Expression> = None;
348 let mut alternatives: Vec<CaseAlternative> = Vec::new();
349 let mut else_expr: Option<Expression> = None;
350
351 for child in pair.into_inner() {
352 match child.as_rule() {
353 Rule::case_subject => {
354 if let Some(expr_pair) = child.into_inner().next() {
356 subject = Some(parse_expression(expr_pair)?);
357 }
358 }
359 Rule::case_when => {
360 let mut exprs = child
362 .into_inner()
363 .filter(|p| p.as_rule() == Rule::expression)
364 .map(parse_expression)
365 .collect::<Result<Vec<_>, _>>()?;
366 if exprs.len() < 2 {
367 return Err("CASE WHEN clause requires both WHEN and THEN expressions".into());
368 }
369 let then = exprs.remove(1);
370 let when = exprs.remove(0);
371 alternatives.push(CaseAlternative { when, then });
372 }
373 Rule::case_else => {
374 if let Some(expr_pair) = child.into_inner().find(|p| p.as_rule() == Rule::expression) {
375 else_expr = Some(parse_expression(expr_pair)?);
376 }
377 }
378 _ => {} }
380 }
381
382 if alternatives.is_empty() {
383 return Err("CASE expression requires at least one WHEN clause".into());
384 }
385
386 Ok(Expression::Case(CaseExpr {
387 subject: subject.map(Box::new),
388 alternatives,
389 else_expr: else_expr.map(Box::new),
390 }))
391}
392
393pub fn parse_literal(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
395 match pair.as_rule() {
396 Rule::string => Ok(Expression::Constant(Constant::String(unescape_string(pair.as_str())))),
397 Rule::integer => {
398 let s = pair.as_str();
399 Ok(Expression::Constant(Constant::Integer(
400 s.trim().parse().map_err(|e| format!("Int: {e} (for string '{s}')"))?,
401 )))
402 }
403 Rule::float => {
404 let s = pair.as_str();
405 Ok(Expression::Constant(Constant::Float(
406 s.trim().parse().map_err(|e| format!("Float: {e} (for string '{s}')"))?,
407 )))
408 }
409 Rule::boolean_literal => Ok(Expression::Constant(Constant::Bool(
410 pair.as_str().to_uppercase() == "TRUE",
411 ))),
412 Rule::null_literal => Ok(Expression::Constant(Constant::Null)),
413 _ => Err(format!("Unknown literal: {:?}", pair.as_rule())),
414 }
415}
416
417pub fn unescape_string(s: &str) -> String {
419 let s = s.trim_matches(|c| c == '"' || c == '\'');
420 let mut r = String::with_capacity(s.len());
421 let mut chars = s.chars();
422 while let Some(c) = chars.next() {
423 if c == '\\' {
424 match chars.next() {
425 Some('n') => r.push('\n'),
426 Some('t') => r.push('\t'),
427 Some('r') => r.push('\r'),
428 Some('\\') => r.push('\\'),
429 Some('"') => r.push('"'),
430 Some('\'') => r.push('\''),
431 Some(o) => {
432 r.push('\\');
433 r.push(o);
434 }
435 None => r.push('\\'),
436 }
437 } else {
438 r.push(c);
439 }
440 }
441 r
442}