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