1use super::enter_query_recursion;
3use super::mac::unexpected;
4use crate::compat::types::PublicDuration;
5use crate::upstream::sql::operator::{
6 BindingPower, BooleanOperator, MatchesOperator, NearestNeighbor,
7};
8use crate::upstream::sql::{BinaryOperator, Expr, Literal, Part, PostfixOperator, PrefixOperator};
9use crate::upstream::syn::error::bail;
10use crate::upstream::syn::lexer::compound::Numeric;
11use crate::upstream::syn::parser::mac::expected;
12use crate::upstream::syn::parser::{ParseResult, Parser};
13use crate::upstream::syn::token::{Span, Token, TokenKind, t};
14use reblessive::Stk;
15use surrealdb_types::ToSql;
16impl Parser<'_> {
17 pub async fn parse_expr_start(&mut self, stk: &mut Stk) -> ParseResult<Expr> {
23 self.table_as_field = true;
24 self.pratt_parse_expr(stk, BindingPower::Base).await
25 }
26 pub async fn parse_expr_table(&mut self, stk: &mut Stk) -> ParseResult<Expr> {
33 let old = self.table_as_field;
34 self.table_as_field = false;
35 let res = enter_query_recursion!(
36 this = self => { this.pratt_parse_expr(stk, BindingPower::Base). await }
37 );
38 self.table_as_field = old;
39 res
40 }
41 pub async fn parse_expr_field(&mut self, stk: &mut Stk) -> ParseResult<Expr> {
48 let old = self.table_as_field;
49 self.table_as_field = true;
50 let res = enter_query_recursion!(
51 this = self => { this.pratt_parse_expr(stk, BindingPower::Base). await }
52 );
53 self.table_as_field = old;
54 res
55 }
56 pub(super) async fn parse_expr_inherit(&mut self, stk: &mut Stk) -> ParseResult<Expr> {
60 enter_query_recursion!(
61 this = self => { this.pratt_parse_expr(stk, BindingPower::Base). await }
62 )
63 }
64 fn infix_binding_power(&mut self, token: TokenKind) -> Option<BindingPower> {
74 match token {
75 t!("||") | t!("OR") => Some(BindingPower::Or),
76 t!("&&") | t!("AND") => Some(BindingPower::And),
77 t!("=") | t!("IS") | t!("==") | t!("!=") | t!("*=") | t!("?=") | t!("@") => {
78 Some(BindingPower::Equality)
79 }
80 t!("<") => {
81 if let Some(peek) = self.peek_whitespace1()
82 && let t!("-") | t!("~") | t!("->") | t!("..") = peek.kind
83 {
84 return None;
85 }
86 Some(BindingPower::Relation)
87 }
88 t!(">") => {
89 if let Some(t!("..")) = self.peek_whitespace1().map(|x| x.kind) {
90 return Some(BindingPower::Range);
91 }
92 Some(BindingPower::Relation)
93 }
94 t!("..") => Some(BindingPower::Range),
95 t!("<=")
96 | t!(">=")
97 | t!("∋")
98 | t!("CONTAINS")
99 | t!("∌")
100 | t!("CONTAINSNOT")
101 | t!("∈")
102 | t!("INSIDE")
103 | t!("∉")
104 | t!("NOTINSIDE")
105 | t!("⊇")
106 | t!("CONTAINSALL")
107 | t!("⊃")
108 | t!("CONTAINSANY")
109 | t!("⊅")
110 | t!("CONTAINSNONE")
111 | t!("⊆")
112 | t!("ALLINSIDE")
113 | t!("⊂")
114 | t!("ANYINSIDE")
115 | t!("⊄")
116 | t!("NONEINSIDE")
117 | t!("OUTSIDE")
118 | t!("INTERSECTS")
119 | t!("NOT")
120 | t!("IN")
121 | t!("<|") => Some(BindingPower::Relation),
122 t!("+") | t!("-") => Some(BindingPower::AddSub),
123 t!("*") | t!("×") | t!("/") | t!("÷") | t!("%") => Some(BindingPower::MulDiv),
124 t!("**") => Some(BindingPower::Power),
125 t!("?:") | t!("?") => Some(BindingPower::Nullish),
126 _ => None,
127 }
128 }
129 fn prefix_binding_power(&mut self, token: TokenKind) -> Option<BindingPower> {
130 match token {
131 t!("!") | t!("+") | t!("-") => Some(BindingPower::Prefix),
132 t!("..") => Some(BindingPower::Range),
133 t!("<") => {
134 if let Some(peek) = self.peek_whitespace1() {
135 if peek.kind == t!("-") {
136 let recover = self.last_span();
137 if self.peek2().kind == TokenKind::Digits {
138 self.backup_after(recover);
139 return Some(BindingPower::Prefix);
140 }
141 return None;
142 }
143 if let t!("~") | t!("->") = peek.kind {
144 return None;
145 }
146 }
147 Some(BindingPower::Prefix)
148 }
149 _ => None,
150 }
151 }
152 fn postfix_binding_power(&mut self, token: TokenKind) -> Option<BindingPower> {
153 match token {
154 t!(">") => {
155 if let Some(peek) = self.peek_whitespace1()
156 && let t!("..") = peek.kind
157 {
158 if let Some(peek) = self.peek_whitespace2()
159 && (t!("=") == peek.kind || Self::kind_starts_expression(peek.kind))
160 {
161 return None;
162 } else {
163 return Some(BindingPower::Range);
164 }
165 }
166 None
167 }
168 t!("..") => match self.peek_whitespace1().map(|x| x.kind) {
169 Some(t!("=")) => None,
170 Some(x) if Self::kind_starts_expression(x) => None,
171 _ => Some(BindingPower::Range),
172 },
173 t!("(") => Some(BindingPower::Call),
174 _ => None,
175 }
176 }
177 async fn parse_prefix_op(&mut self, stk: &mut Stk, min_bp: BindingPower) -> ParseResult<Expr> {
178 let token = self.peek();
179 let operator = match token.kind {
180 t!("+") => {
181 if let Some(TokenKind::Digits) = self.peek_whitespace1().map(|x| x.kind) {
182 self.pop_peek();
183 let expr = match self.next_token_value::<Numeric>()? {
184 Numeric::Float(f) => Expr::Literal(Literal::Float(f)),
185 Numeric::Integer(i) => {
186 Expr::Literal(Literal::Integer(i.into_int(self.recent_span())?))
187 }
188 Numeric::Decimal(d) => Expr::Literal(Literal::Decimal(d)),
189 Numeric::Duration(d) => Expr::Prefix {
190 op: PrefixOperator::Positive,
191 expr: Box::new(Expr::Literal(Literal::Duration(PublicDuration::from(
192 d,
193 )))),
194 },
195 };
196 if self.peek_continues_idiom() {
197 return self
198 .parse_remaining_value_idiom(stk, vec![Part::Start(expr)])
199 .await;
200 } else {
201 return Ok(expr);
202 }
203 }
204 self.pop_peek();
205 PrefixOperator::Positive
206 }
207 t!("-") => {
208 if let Some(TokenKind::Digits) = self.peek_whitespace1().map(|x| x.kind) {
209 self.pop_peek();
210 let expr = match self.next_token_value::<Numeric>()? {
211 Numeric::Float(f) => Expr::Literal(Literal::Float(-f)),
212 Numeric::Integer(i) => {
213 Expr::Literal(Literal::Integer(i.into_neg_int(self.recent_span())?))
214 }
215 Numeric::Decimal(d) => Expr::Literal(Literal::Decimal(-d)),
216 Numeric::Duration(d) => Expr::Prefix {
217 op: PrefixOperator::Negate,
218 expr: Box::new(Expr::Literal(Literal::Duration(PublicDuration::from(
219 d,
220 )))),
221 },
222 };
223 if self.peek_continues_idiom() {
224 return self
225 .parse_remaining_value_idiom(stk, vec![Part::Start(expr)])
226 .await;
227 } else {
228 return Ok(expr);
229 }
230 }
231 self.pop_peek();
232 PrefixOperator::Negate
233 }
234 t!("!") => {
235 self.pop_peek();
236 PrefixOperator::Not
237 }
238 t!("<") => {
239 self.pop_peek();
240 let kind = self.parse_kind(stk, token.span).await?;
241 PrefixOperator::Cast(kind)
242 }
243 t!("..") => {
244 self.pop_peek();
245 if let Some(x) = self.peek_whitespace() {
246 if let t!("=") = x.kind {
247 self.pop_peek();
248 PrefixOperator::RangeInclusive
249 } else if !Self::kind_starts_prime_value(x.kind) {
250 return Ok(Expr::Literal(Literal::UnboundedRange));
251 } else {
252 PrefixOperator::Range
253 }
254 } else {
255 return Ok(Expr::Literal(Literal::UnboundedRange));
256 }
257 }
258 _ => unreachable!(),
259 };
260 let v = stk.run(|stk| self.pratt_parse_expr(stk, min_bp)).await?;
261 Ok(Expr::Prefix {
262 op: operator,
263 expr: Box::new(v),
264 })
265 }
266 pub(super) fn parse_nearest_neighbor(&mut self, token: Token) -> ParseResult<NearestNeighbor> {
267 let amount = self.next_token_value()?;
268 let res = if self.eat(t!(",")) {
269 let token = self.peek();
270 match token.kind {
271 TokenKind::Distance(_) => {
272 let d = self.parse_distance()?;
273 NearestNeighbor::K(amount, d)
274 }
275 TokenKind::Digits => {
276 let ef = self.next_token_value()?;
277 NearestNeighbor::Approximate(amount, ef)
278 }
279 _ => {
280 bail!(
281 "Unexpected token {} expected a distance of an integer", token
282 .kind, @ token.span =>
283 "The NN operator accepts either a distance or an EF value (integer)"
284 )
285 }
286 }
287 } else {
288 NearestNeighbor::KTree(amount)
289 };
290 if !self.eat(t!("|")) || !self.eat_whitespace(t!(">")) {
291 bail!(
292 "Unexpected token `{}` expected delimiter `|>`", self.peek().kind, @ self
293 .recent_span(), @ token.span => "expected this delimiter to close"
294 );
295 }
296 Ok(res)
297 }
298 fn operator_has_associativity(operator: &BinaryOperator) -> bool {
302 !matches!(
303 operator,
304 BinaryOperator::Equal
305 | BinaryOperator::NotEqual
306 | BinaryOperator::AllEqual
307 | BinaryOperator::AnyEqual
308 | BinaryOperator::LessThan
309 | BinaryOperator::LessThanEqual
310 | BinaryOperator::MoreThan
311 | BinaryOperator::MoreThanEqual
312 | BinaryOperator::Matches(_)
313 | BinaryOperator::Contain
314 | BinaryOperator::NotContain
315 | BinaryOperator::ContainAll
316 | BinaryOperator::ContainAny
317 | BinaryOperator::ContainNone
318 | BinaryOperator::Inside
319 | BinaryOperator::NotInside
320 | BinaryOperator::AllInside
321 | BinaryOperator::AnyInside
322 | BinaryOperator::NoneInside
323 | BinaryOperator::Outside
324 | BinaryOperator::Intersects
325 | BinaryOperator::NearestNeighbor(_)
326 )
327 }
328 fn expr_is_range(expr: &Expr) -> bool {
329 match expr {
330 Expr::Binary { op, .. } => {
331 matches!(
332 op,
333 BinaryOperator::Range
334 | BinaryOperator::RangeSkipInclusive
335 | BinaryOperator::RangeSkip
336 | BinaryOperator::RangeInclusive
337 )
338 }
339 Expr::Prefix { op, .. } => {
340 matches!(op, PrefixOperator::Range | PrefixOperator::RangeInclusive)
341 }
342 Expr::Postfix { op, .. } => {
343 matches!(op, PostfixOperator::Range | PostfixOperator::RangeSkip)
344 }
345 _ => false,
346 }
347 }
348 async fn parse_infix_op(
349 &mut self,
350 stk: &mut Stk,
351 min_bp: BindingPower,
352 lhs: Expr,
353 lhs_prime: bool,
354 ) -> ParseResult<Expr> {
355 let token = self.next();
356 let operator = match token.kind {
357 t!("||") | t!("OR") => BinaryOperator::Or,
358 t!("&&") | t!("AND") => BinaryOperator::And,
359 t!("?:") => BinaryOperator::TenaryCondition,
360 t!("?") => {
361 if !self.eat_whitespace(t!("?")) {
362 unexpected!(self, token, "`??`")
363 }
364 BinaryOperator::NullCoalescing
365 }
366 t!("==") => BinaryOperator::ExactEqual,
367 t!("!=") => BinaryOperator::NotEqual,
368 t!("*=") => BinaryOperator::AllEqual,
369 t!("?=") => BinaryOperator::AnyEqual,
370 t!("=") => BinaryOperator::Equal,
371 t!("@") => {
372 let op = self.parse_matches()?;
373 BinaryOperator::Matches(op)
374 }
375 t!("<=") => BinaryOperator::LessThanEqual,
376 t!("<") => BinaryOperator::LessThan,
377 t!(">=") => BinaryOperator::MoreThanEqual,
378 t!("**") => BinaryOperator::Power,
379 t!("+") => BinaryOperator::Add,
380 t!("-") => BinaryOperator::Subtract,
381 t!("*") | t!("×") => BinaryOperator::Multiply,
382 t!("/") | t!("÷") => BinaryOperator::Divide,
383 t!("%") => BinaryOperator::Remainder,
384 t!("∋") | t!("CONTAINS") => BinaryOperator::Contain,
385 t!("∌") | t!("CONTAINSNOT") => BinaryOperator::NotContain,
386 t!("∈") | t!("INSIDE") => BinaryOperator::Inside,
387 t!("∉") | t!("NOTINSIDE") => BinaryOperator::NotInside,
388 t!("⊇") | t!("CONTAINSALL") => BinaryOperator::ContainAll,
389 t!("⊃") | t!("CONTAINSANY") => BinaryOperator::ContainAny,
390 t!("⊅") | t!("CONTAINSNONE") => BinaryOperator::ContainNone,
391 t!("⊆") | t!("ALLINSIDE") => BinaryOperator::AllInside,
392 t!("⊂") | t!("ANYINSIDE") => BinaryOperator::AnyInside,
393 t!("⊄") | t!("NONEINSIDE") => BinaryOperator::NoneInside,
394 t!("IS") => {
395 if self.eat(t!("NOT")) {
396 BinaryOperator::NotEqual
397 } else {
398 BinaryOperator::Equal
399 }
400 }
401 t!("OUTSIDE") => BinaryOperator::Outside,
402 t!("INTERSECTS") => BinaryOperator::Intersects,
403 t!("NOT") => {
404 expected!(self, t!("IN"));
405 BinaryOperator::NotInside
406 }
407 t!("IN") => BinaryOperator::Inside,
408 t!("<|") => {
409 BinaryOperator::NearestNeighbor(Box::new(self.parse_nearest_neighbor(token)?))
410 }
411 t!(">") => {
412 if let Some(t!("..")) = self.peek_whitespace().map(|x| x.kind) {
413 self.pop_peek();
414 if let Some(t!("=")) = self.peek_whitespace().map(|x| x.kind) {
415 self.pop_peek();
416 BinaryOperator::RangeSkipInclusive
417 } else {
418 BinaryOperator::RangeSkip
419 }
420 } else {
421 BinaryOperator::MoreThan
422 }
423 }
424 t!("..") => {
425 if let Some(t!("=")) = self.peek_whitespace().map(|x| x.kind) {
426 self.pop_peek();
427 BinaryOperator::RangeInclusive
428 } else {
429 BinaryOperator::Range
430 }
431 }
432 x => unreachable!("found non-operator token {x:?}"),
433 };
434 let rhs_covered = self.peek().kind == t!("(");
435 let rhs = stk.run(|ctx| self.pratt_parse_expr(ctx, min_bp)).await?;
436 let has_associatitivity = Self::operator_has_associativity(&operator);
437 if !lhs_prime
438 && !has_associatitivity
439 && BindingPower::for_expr(&lhs) == BindingPower::for_binary_operator(&operator)
440 {
441 let span = token.span.covers(self.recent_span());
442 if matches!(
443 operator,
444 BinaryOperator::Range
445 | BinaryOperator::RangeSkipInclusive
446 | BinaryOperator::RangeSkip
447 | BinaryOperator::RangeInclusive
448 ) {
449 bail!(
450 "Chained range operators has no specified associativity", @ span =>
451 "use parens, '()', to specify which operator must be evaluated first"
452 )
453 } else {
454 bail!(
455 "Chained relational operators have no defined associativity.", @ span
456 =>
457 "Use parens, '()', to specify which operator must be evaluated first"
458 )
459 }
460 }
461 if !rhs_covered
462 && !has_associatitivity
463 && BindingPower::for_expr(&rhs) == BindingPower::for_binary_operator(&operator)
464 {
465 let span = token.span.covers(self.recent_span());
466 if matches!(
467 operator,
468 BinaryOperator::Range
469 | BinaryOperator::RangeSkipInclusive
470 | BinaryOperator::RangeSkip
471 | BinaryOperator::RangeInclusive
472 ) {
473 bail!(
474 "Chained range operators have no defined associativity.", @ span =>
475 "Use parens, '()', to specify which operator must be evaluated first"
476 )
477 } else {
478 bail!(
479 "Chained relational operators have no defined associativity.", @ span
480 =>
481 "Use parens, '()', to specify which operator must be evaluated first"
482 )
483 }
484 }
485 Ok(Expr::Binary {
486 left: Box::new(lhs),
487 op: operator,
488 right: Box::new(rhs),
489 })
490 }
491 fn parse_matches(&mut self) -> ParseResult<MatchesOperator> {
492 let peek = self.peek();
493 match peek.kind {
494 TokenKind::Digits => {
495 let number = self.next_token_value()?;
496 let op = if self.eat(t!(",")) {
497 let peek = self.next();
498 let op = match peek.kind {
499 t!("AND") => BooleanOperator::And,
500 t!("OR") => BooleanOperator::Or,
501 _ => unexpected!(self, peek, "either `AND` or `OR`"),
502 };
503 Some(op)
504 } else {
505 None
506 };
507 expected!(self, t!("@"));
508 Ok(MatchesOperator {
509 operator: op,
510 rf: Some(number),
511 })
512 }
513 t!("AND") => {
514 self.pop_peek();
515 expected!(self, t!("@"));
516 Ok(MatchesOperator {
517 operator: Some(BooleanOperator::And),
518 rf: None,
519 })
520 }
521 t!("OR") => {
522 self.pop_peek();
523 expected!(self, t!("@"));
524 Ok(MatchesOperator {
525 operator: Some(BooleanOperator::Or),
526 rf: None,
527 })
528 }
529 t!("@") => {
530 self.pop_peek();
531 Ok(MatchesOperator {
532 operator: None,
533 rf: None,
534 })
535 }
536 _ => unexpected!(self, peek, "a match reference, operator or `@`"),
537 }
538 }
539 async fn parse_postfix(
540 &mut self,
541 stk: &mut Stk,
542 lhs: Expr,
543 lhs_prime: bool,
544 ) -> ParseResult<Expr> {
545 let token = self.next();
546 let op = match token.kind {
547 t!(">") => {
548 assert!(self.eat_whitespace(t!("..")));
549 if !lhs_prime && Self::expr_is_range(&lhs) {
550 bail!(
551 "Chaining range operators has no specified associativity", @
552 token.span =>
553 "use parens, '()', to specify which operator must be evaluated first"
554 )
555 }
556 PostfixOperator::RangeSkip
557 }
558 t!("..") => {
559 if !lhs_prime && Self::expr_is_range(&lhs) {
560 bail!(
561 "Chaining range operators has no specified associativity", @
562 token.span =>
563 "use parens, '()', to specify which operator must be evaluated first"
564 )
565 }
566 PostfixOperator::Range
567 }
568 t!("(") => {
569 let mut args = Vec::new();
570 loop {
571 if self.eat(t!(")")) {
572 break;
573 }
574 let arg = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
575 args.push(arg);
576 if !self.eat(t!(",")) {
577 self.expect_closing_delimiter(t!(")"), token.span)?;
578 break;
579 }
580 }
581 PostfixOperator::Call(args)
582 }
583 t!(".") => {
584 let name = self.parse_ident()?;
585 expected!(self, t!("("));
586 let mut args = Vec::new();
587 loop {
588 if self.eat(t!(")")) {
589 break;
590 }
591 let arg = stk.run(|ctx| self.parse_expr_inherit(ctx)).await?;
592 args.push(arg);
593 if !self.eat(t!(",")) {
594 self.expect_closing_delimiter(t!(")"), token.span)?;
595 break;
596 }
597 }
598 PostfixOperator::MethodCall(name, args)
599 }
600 x => unreachable!("found non-operator token {x:?}"),
601 };
602 Ok(Expr::Postfix {
603 expr: Box::new(lhs),
604 op,
605 })
606 }
607 async fn pratt_parse_expr(&mut self, stk: &mut Stk, min_bp: BindingPower) -> ParseResult<Expr> {
610 let peek = self.peek();
611 let (mut lhs, mut lhs_prime) = if let Some(bp) = self.prefix_binding_power(peek.kind) {
612 (self.parse_prefix_op(stk, bp).await?, false)
613 } else {
614 (self.parse_prime_expr(stk).await?, true)
615 };
616 loop {
617 let token = self.peek();
618 if let Some(bp) = self.postfix_binding_power(token.kind) {
619 if bp <= min_bp {
620 break;
621 }
622 lhs = self.parse_postfix(stk, lhs, lhs_prime).await?;
623 lhs_prime = false;
624 continue;
625 }
626 if let t!("+=") | t!("-=") | t!("+?=") = token.kind {
627 unexpected!(
628 self, token, "an operator", =>
629 "assignment operators are only allowed in SET and DUPLICATE KEY UPDATE clauses"
630 )
631 }
632 let Some(bp) = self.infix_binding_power(token.kind) else {
633 break;
634 };
635 if bp <= min_bp {
636 break;
637 }
638 lhs = self.parse_infix_op(stk, bp, lhs, lhs_prime).await?;
639 lhs_prime = false;
640 }
641 Ok(lhs)
642 }
643 pub fn reject_letless_let(expr: &Expr, span: Span) -> ParseResult<()> {
644 let Expr::Binary { left, op, .. } = expr else {
645 return Ok(());
646 };
647 let Expr::Param(p) = &**left else {
648 return Ok(());
649 };
650 let BinaryOperator::Equal = op else {
651 return Ok(());
652 };
653 bail!(
654 "Parameter declarations without `let` are deprecated.", @ span =>
655 "Replace with `let {} = ...` to keep the previous behavior.", p.to_sql()
656 )
657 }
658}