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 }
158 }
159 Ok(result)
160 }
161 Rule::exists_subquery => {
162 for c in children {
164 if c.as_rule() == Rule::query_statement {
165 let query = parse_query_pairs(c)?;
166 return Ok(Expression::ExistsSubquery(Box::new(query)));
167 }
168 }
169 Err("EXISTS subquery requires a query statement".into())
170 }
171 Rule::list_predicate => {
172 let children: Vec<_> = pair.clone().into_inner().collect();
176 if children.len() < 3 {
177 return Err(format!("Invalid list predicate syntax: {} children", children.len()));
178 }
179 let full_text = pair.as_str();
181 let quantifier_str = full_text.split('(').next().unwrap_or("").to_uppercase();
182 let quantifier = match quantifier_str.as_str() {
183 "ANY" => Quantifier::Any,
184 "ALL" => Quantifier::All,
185 "NONE" => Quantifier::None,
186 "SINGLE" => Quantifier::Single,
187 _ => return Err(format!("Unknown quantifier: {}", quantifier_str)),
188 };
189 let var_name = children[0].as_str().to_string();
190 let list = parse_expression(children[1].clone())?;
191 let predicate = parse_expression(children[2].clone())?;
192 Ok(Expression::ListPredicate {
193 quantifier,
194 list: Box::new(list),
195 var_name,
196 predicate: Box::new(predicate),
197 })
198 }
199 Rule::lambda_expr => {
200 let mut children = pair.clone().into_inner();
201 let var_name = children.next().ok_or("Lambda missing variable")?.as_str().to_string();
202 let body = parse_expression(children.next().ok_or("Lambda missing body")?)?;
203 Ok(Expression::Lambda {
204 var_name,
205 body: Box::new(body),
206 })
207 }
208 Rule::function_args => {
209 if children.is_empty() {
213 return Ok(Expression::Constant(Constant::Null));
214 }
215 let name = pair.as_str().split('(').next().unwrap_or("").to_string();
217 let args = children
218 .into_iter()
219 .filter(|c| c.as_rule() == Rule::expression)
220 .map(parse_expression)
221 .collect::<Result<Vec<_>, _>>()?;
222 Ok(Expression::FunctionCall(name, args))
223 }
224 Rule::property_access => Err("property_access should be handled within postfix_expr".into()),
225 _ => {
226 if let Some(child) = children.into_iter().next() {
228 parse_expression(child)
229 } else {
230 Err(format!("Cannot parse: {:?}", rule))
231 }
232 }
233 }
234}
235
236pub fn parse_comparison_suffix(pair: pest::iterators::Pair<Rule>, left: Expression) -> Result<Expression, String> {
238 fn get_rhs(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
240 let rhs_pair = pair
241 .into_inner()
242 .find(|p| p.as_rule() == Rule::additive_expr)
243 .ok_or_else(|| "Operator missing right-hand expression".to_string())?;
244 parse_expression(rhs_pair)
245 }
246
247 match pair.as_rule() {
248 Rule::is_check_op => {
249 let text = pair.as_str();
250 if text.contains("NOT") {
251 Ok(Expression::UnaryOp(UnaryOp::IsNotNull, Box::new(left)))
252 } else {
253 Ok(Expression::UnaryOp(UnaryOp::IsNull, Box::new(left)))
254 }
255 }
256 Rule::in_op => {
257 let right = get_rhs(pair)?;
258 Ok(Expression::BinaryOp(BinaryOp::In, Box::new(left), Box::new(right)))
259 }
260 Rule::not_in_op => {
261 let right = get_rhs(pair)?;
262 Ok(Expression::BinaryOp(BinaryOp::NotIn, Box::new(left), Box::new(right)))
263 }
264 Rule::starts_with_op => {
265 let right = get_rhs(pair)?;
266 Ok(Expression::BinaryOp(
267 BinaryOp::StartsWith,
268 Box::new(left),
269 Box::new(right),
270 ))
271 }
272 Rule::not_starts_with_op => {
273 let right = get_rhs(pair)?;
274 let inner = Expression::BinaryOp(BinaryOp::StartsWith, Box::new(left), Box::new(right));
275 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
276 }
277 Rule::ends_with_op => {
278 let right = get_rhs(pair)?;
279 Ok(Expression::BinaryOp(
280 BinaryOp::EndsWith,
281 Box::new(left),
282 Box::new(right),
283 ))
284 }
285 Rule::not_ends_with_op => {
286 let right = get_rhs(pair)?;
287 let inner = Expression::BinaryOp(BinaryOp::EndsWith, Box::new(left), Box::new(right));
288 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
289 }
290 Rule::contains_op => {
291 let right = get_rhs(pair)?;
292 Ok(Expression::BinaryOp(
293 BinaryOp::Contains,
294 Box::new(left),
295 Box::new(right),
296 ))
297 }
298 Rule::not_contains_op => {
299 let right = get_rhs(pair)?;
300 let inner = Expression::BinaryOp(BinaryOp::Contains, Box::new(left), Box::new(right));
301 Ok(Expression::UnaryOp(UnaryOp::Not, Box::new(inner)))
302 }
303 Rule::like_op => {
304 let right = get_rhs(pair)?;
305 Ok(Expression::BinaryOp(BinaryOp::Like, Box::new(left), Box::new(right)))
306 }
307 Rule::between_op => {
308 let mut children = pair.into_inner();
309 let lower_pair = children
310 .find(|p| p.as_rule() == Rule::additive_expr)
311 .ok_or_else(|| "BETWEEN missing lower bound expression".to_string())?;
312 let upper_pair = children
313 .find(|p| p.as_rule() == Rule::additive_expr)
314 .ok_or_else(|| "BETWEEN missing upper bound expression".to_string())?;
315 let lower_expr = parse_expression(lower_pair)?;
316 let upper_expr = parse_expression(upper_pair)?;
317 let ge = Expression::BinaryOp(
318 BinaryOp::GreaterThanOrEqual,
319 Box::new(left.clone()),
320 Box::new(lower_expr),
321 );
322 let le = Expression::BinaryOp(BinaryOp::LessThanOrEqual, Box::new(left), Box::new(upper_expr));
323 Ok(Expression::BinaryOp(BinaryOp::And, Box::new(ge), Box::new(le)))
324 }
325 r => Err(format!("Unknown comparison suffix: {:?}", r)),
326 }
327}
328
329pub fn parse_case_expr(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
331 let mut subject: Option<Expression> = None;
332 let mut alternatives: Vec<CaseAlternative> = Vec::new();
333 let mut else_expr: Option<Expression> = None;
334
335 for child in pair.into_inner() {
336 match child.as_rule() {
337 Rule::case_subject => {
338 if let Some(expr_pair) = child.into_inner().next() {
340 subject = Some(parse_expression(expr_pair)?);
341 }
342 }
343 Rule::case_when => {
344 let mut exprs = child
346 .into_inner()
347 .filter(|p| p.as_rule() == Rule::expression)
348 .map(parse_expression)
349 .collect::<Result<Vec<_>, _>>()?;
350 if exprs.len() < 2 {
351 return Err("CASE WHEN clause requires both WHEN and THEN expressions".into());
352 }
353 let then = exprs.remove(1);
354 let when = exprs.remove(0);
355 alternatives.push(CaseAlternative { when, then });
356 }
357 Rule::case_else => {
358 if let Some(expr_pair) = child.into_inner().find(|p| p.as_rule() == Rule::expression) {
359 else_expr = Some(parse_expression(expr_pair)?);
360 }
361 }
362 _ => {} }
364 }
365
366 if alternatives.is_empty() {
367 return Err("CASE expression requires at least one WHEN clause".into());
368 }
369
370 Ok(Expression::Case(CaseExpr {
371 subject: subject.map(Box::new),
372 alternatives,
373 else_expr: else_expr.map(Box::new),
374 }))
375}
376
377pub fn parse_literal(pair: pest::iterators::Pair<Rule>) -> Result<Expression, String> {
379 match pair.as_rule() {
380 Rule::string => Ok(Expression::Constant(Constant::String(unescape_string(pair.as_str())))),
381 Rule::integer => {
382 let s = pair.as_str();
383 Ok(Expression::Constant(Constant::Integer(
384 s.trim().parse().map_err(|e| format!("Int: {e} (for string '{s}')"))?,
385 )))
386 }
387 Rule::float => {
388 let s = pair.as_str();
389 Ok(Expression::Constant(Constant::Float(
390 s.trim().parse().map_err(|e| format!("Float: {e} (for string '{s}')"))?,
391 )))
392 }
393 Rule::boolean_literal => Ok(Expression::Constant(Constant::Bool(
394 pair.as_str().to_uppercase() == "TRUE",
395 ))),
396 Rule::null_literal => Ok(Expression::Constant(Constant::Null)),
397 _ => Err(format!("Unknown literal: {:?}", pair.as_rule())),
398 }
399}
400
401pub fn unescape_string(s: &str) -> String {
403 let s = s.trim_matches(|c| c == '"' || c == '\'');
404 let mut r = String::with_capacity(s.len());
405 let mut chars = s.chars();
406 while let Some(c) = chars.next() {
407 if c == '\\' {
408 match chars.next() {
409 Some('n') => r.push('\n'),
410 Some('t') => r.push('\t'),
411 Some('r') => r.push('\r'),
412 Some('\\') => r.push('\\'),
413 Some('"') => r.push('"'),
414 Some('\'') => r.push('\''),
415 Some(o) => {
416 r.push('\\');
417 r.push(o);
418 }
419 None => r.push('\\'),
420 }
421 } else {
422 r.push(c);
423 }
424 }
425 r
426}