1use super::*;
2
3impl Parser {
4 pub(super) fn parse_or_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
6 let mut left = self.parse_and_expression()?;
7
8 while self.peek_keyword(Keyword::Or) {
9 self.consume_keyword(Keyword::Or)?;
10 let right = self.parse_and_expression()?;
11 left = vibesql_ast::Expression::BinaryOp {
12 op: vibesql_ast::BinaryOperator::Or,
13 left: Box::new(left),
14 right: Box::new(right),
15 };
16 }
17
18 Ok(left)
19 }
20
21 pub(super) fn parse_and_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
23 let mut left = self.parse_not_expression()?;
24
25 while self.peek_keyword(Keyword::And) {
26 self.consume_keyword(Keyword::And)?;
27 let right = self.parse_not_expression()?;
28 left = vibesql_ast::Expression::BinaryOp {
29 op: vibesql_ast::BinaryOperator::And,
30 left: Box::new(left),
31 right: Box::new(right),
32 };
33 }
34
35 Ok(left)
36 }
37
38 pub(super) fn parse_not_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
42 if self.peek_keyword(Keyword::Not) {
45 let saved_pos = self.position;
47 self.advance(); if self.peek_keyword(Keyword::In)
51 || self.peek_keyword(Keyword::Between)
52 || self.peek_keyword(Keyword::Like)
53 || self.peek_keyword(Keyword::Glob)
54 || self.peek_keyword(Keyword::Exists)
55 {
56 self.position = saved_pos;
58 return self.parse_bitwise_or_expression();
59 }
60
61 let expr = self.parse_not_expression()?;
64
65 Ok(vibesql_ast::Expression::UnaryOp {
66 op: vibesql_ast::UnaryOperator::Not,
67 expr: Box::new(expr),
68 })
69 } else {
70 self.parse_bitwise_or_expression()
71 }
72 }
73
74 pub(super) fn parse_bitwise_or_expression(
77 &mut self,
78 ) -> Result<vibesql_ast::Expression, ParseError> {
79 let mut left = self.parse_bitwise_and_expression()?;
80
81 while self.peek() == &Token::Symbol('|') {
82 self.advance();
83 let right = self.parse_bitwise_and_expression()?;
84 left = vibesql_ast::Expression::BinaryOp {
85 op: vibesql_ast::BinaryOperator::BitwiseOr,
86 left: Box::new(left),
87 right: Box::new(right),
88 };
89 }
90
91 Ok(left)
92 }
93
94 pub(super) fn parse_bitwise_and_expression(
97 &mut self,
98 ) -> Result<vibesql_ast::Expression, ParseError> {
99 let mut left = self.parse_comparison_expression()?;
100
101 while self.peek() == &Token::Symbol('&') {
102 self.advance();
103 let right = self.parse_comparison_expression()?;
104 left = vibesql_ast::Expression::BinaryOp {
105 op: vibesql_ast::BinaryOperator::BitwiseAnd,
106 left: Box::new(left),
107 right: Box::new(right),
108 };
109 }
110
111 Ok(left)
112 }
113
114 pub(super) fn parse_shift_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
117 let mut left = self.parse_additive_expression()?;
118
119 loop {
120 let op = match self.peek() {
121 Token::Operator(crate::token::MultiCharOperator::LeftShift) => {
122 vibesql_ast::BinaryOperator::LeftShift
123 }
124 Token::Operator(crate::token::MultiCharOperator::RightShift) => {
125 vibesql_ast::BinaryOperator::RightShift
126 }
127 _ => break,
128 };
129 self.advance();
130
131 let right = self.parse_additive_expression()?;
132 left = vibesql_ast::Expression::BinaryOp {
133 op,
134 left: Box::new(left),
135 right: Box::new(right),
136 };
137 }
138
139 Ok(left)
140 }
141
142 pub(super) fn parse_additive_expression(
145 &mut self,
146 ) -> Result<vibesql_ast::Expression, ParseError> {
147 let mut left = self.parse_concat_expression()?;
148
149 loop {
150 let op = match self.peek() {
151 Token::Symbol('+') => vibesql_ast::BinaryOperator::Plus,
152 Token::Symbol('-') => vibesql_ast::BinaryOperator::Minus,
153 _ => break,
154 };
155 self.advance();
156
157 let right = self.parse_concat_expression()?;
158 left = vibesql_ast::Expression::BinaryOp {
159 op,
160 left: Box::new(left),
161 right: Box::new(right),
162 };
163 }
164
165 Ok(left)
166 }
167
168 pub(super) fn parse_concat_expression(
171 &mut self,
172 ) -> Result<vibesql_ast::Expression, ParseError> {
173 let mut left = self.parse_multiplicative_expression()?;
174
175 while self.peek() == &Token::Operator(crate::token::MultiCharOperator::Concat) {
176 self.advance();
177 let right = self.parse_multiplicative_expression()?;
178 left = vibesql_ast::Expression::BinaryOp {
179 op: vibesql_ast::BinaryOperator::Concat,
180 left: Box::new(left),
181 right: Box::new(right),
182 };
183 }
184
185 Ok(left)
186 }
187
188 pub(super) fn parse_multiplicative_expression(
190 &mut self,
191 ) -> Result<vibesql_ast::Expression, ParseError> {
192 let mut left = self.parse_unary_expression()?;
193
194 loop {
195 let op = match self.peek() {
196 Token::Symbol('*') => vibesql_ast::BinaryOperator::Multiply,
197 Token::Symbol('/') => vibesql_ast::BinaryOperator::Divide,
198 Token::Symbol('%') => vibesql_ast::BinaryOperator::Modulo,
199 Token::Keyword { keyword: Keyword::Div, .. } => {
200 vibesql_ast::BinaryOperator::IntegerDivide
201 }
202 _ => break,
203 };
204 self.advance();
205
206 let right = self.parse_unary_expression()?;
207 left = vibesql_ast::Expression::BinaryOp {
208 op,
209 left: Box::new(left),
210 right: Box::new(right),
211 };
212 }
213
214 Ok(left)
215 }
216
217 pub(super) fn parse_comparison_expression(
220 &mut self,
221 ) -> Result<vibesql_ast::Expression, ParseError> {
222 let mut left = self.parse_shift_expression()?;
223
224 if self.peek_keyword(Keyword::Not) {
226 let saved_pos = self.position;
228 self.advance(); if self.peek_keyword(Keyword::In) {
231 self.consume_keyword(Keyword::In)?;
233
234 if self.peek() != &Token::LParen {
236 let table_ref = self.parse_table_ref()?;
240 let table_name = table_ref.full_name();
241 let quoted = table_ref.is_any_quoted();
242
243 let subquery = vibesql_ast::SelectStmt {
245 with_clause: None,
246 distinct: false,
247 select_list: vec![vibesql_ast::SelectItem::Wildcard { alias: None }],
248 into_table: None,
249 into_variables: None,
250 from: Some(vibesql_ast::FromClause::Table {
251 name: table_name,
252 alias: None,
253 column_aliases: None,
254 quoted,
255 }),
256 where_clause: None,
257 group_by: None,
258 having: None,
259 order_by: None,
260 limit: None,
261 offset: None,
262 set_operation: None,
263 values: None,
264 };
265
266 left = vibesql_ast::Expression::In {
267 expr: Box::new(left),
268 subquery: Box::new(subquery),
269 negated: true,
270 };
271 } else {
272 self.expect_token(Token::LParen)?;
274
275 let (is_subquery_through_parens, extra_paren_depth) =
278 self.peek_select_through_parens();
279
280 if self.peek_keyword(Keyword::Select)
281 || self.peek_keyword(Keyword::Values)
282 || is_subquery_through_parens
283 {
284 for _ in 0..extra_paren_depth {
287 self.expect_token(Token::LParen)?;
288 }
289
290 let subquery = self.parse_select_statement()?;
291
292 for _ in 0..extra_paren_depth {
294 self.expect_token(Token::RParen)?;
295 }
296 self.expect_token(Token::RParen)?;
297
298 left = vibesql_ast::Expression::In {
300 expr: Box::new(left),
301 subquery: Box::new(subquery),
302 negated: true,
303 };
304 } else {
305 let values = self.parse_expression_list()?;
307 self.expect_token(Token::RParen)?;
308
309 left = vibesql_ast::Expression::InList {
312 expr: Box::new(left),
313 values,
314 negated: true,
315 };
316 }
317 }
318 } else if self.peek_keyword(Keyword::Between) {
319 self.consume_keyword(Keyword::Between)?;
321
322 let symmetric = if self.peek_keyword(Keyword::Symmetric) {
324 self.consume_keyword(Keyword::Symmetric)?;
325 true
326 } else {
327 if self.peek_keyword(Keyword::Asymmetric) {
329 self.consume_keyword(Keyword::Asymmetric)?;
330 }
331 false
332 };
333
334 let low = self.parse_shift_expression()?;
336 self.consume_keyword(Keyword::And)?;
337 let high = self.parse_shift_expression()?;
338
339 left = vibesql_ast::Expression::Between {
341 expr: Box::new(left),
342 low: Box::new(low),
343 high: Box::new(high),
344 negated: true,
345 symmetric,
346 };
347 } else if self.peek_keyword(Keyword::Like) {
348 self.consume_keyword(Keyword::Like)?;
350
351 let pattern = self.parse_shift_expression()?;
353
354 let escape = if self.peek_keyword(Keyword::Escape) {
356 self.consume_keyword(Keyword::Escape)?;
357 Some(Box::new(self.parse_shift_expression()?))
358 } else {
359 None
360 };
361
362 left = vibesql_ast::Expression::Like {
364 expr: Box::new(left),
365 pattern: Box::new(pattern),
366 negated: true,
367 escape,
368 };
369 } else if self.peek_keyword(Keyword::Glob) {
370 self.consume_keyword(Keyword::Glob)?;
372
373 let pattern = self.parse_shift_expression()?;
375
376 let escape = if self.peek_keyword(Keyword::Escape) {
378 self.consume_keyword(Keyword::Escape)?;
379 Some(Box::new(self.parse_shift_expression()?))
380 } else {
381 None
382 };
383
384 left = vibesql_ast::Expression::Glob {
386 expr: Box::new(left),
387 pattern: Box::new(pattern),
388 negated: true,
389 escape,
390 };
391 } else if self.peek_keyword(Keyword::Null) {
392 self.consume_keyword(Keyword::Null)?;
403
404 let left_is_literal = matches!(&left, vibesql_ast::Expression::Literal(_));
407
408 let next_could_be_column_constraint = match self.peek() {
410 Token::Comma | Token::RParen => true,
411 Token::Keyword { keyword: kw, .. } => matches!(
412 kw,
413 Keyword::Check
415 | Keyword::Unique
416 | Keyword::Primary
417 | Keyword::References
418 | Keyword::Collate
419 | Keyword::Default
420 | Keyword::On
421 | Keyword::Generated
422 | Keyword::AutoIncrement
423 | Keyword::Constraint
424 ),
425 Token::Semicolon | Token::Eof => false, _ => false,
427 };
428
429 if left_is_literal && next_could_be_column_constraint {
430 self.position = saved_pos;
433 } else {
434 return Ok(vibesql_ast::Expression::IsNull {
436 expr: Box::new(left),
437 negated: true,
438 });
439 }
440 } else {
441 self.position = saved_pos;
445 }
446 } else if self.peek_keyword(Keyword::In) {
447 self.consume_keyword(Keyword::In)?;
449
450 if self.peek() != &Token::LParen {
452 let table_ref = self.parse_table_ref()?;
455 let table_name = table_ref.full_name();
456 let quoted = table_ref.is_any_quoted();
457
458 let subquery = vibesql_ast::SelectStmt {
460 with_clause: None,
461 distinct: false,
462 select_list: vec![vibesql_ast::SelectItem::Wildcard { alias: None }],
463 into_table: None,
464 into_variables: None,
465 from: Some(vibesql_ast::FromClause::Table {
466 name: table_name,
467 alias: None,
468 column_aliases: None,
469 quoted,
470 }),
471 where_clause: None,
472 group_by: None,
473 having: None,
474 order_by: None,
475 limit: None,
476 offset: None,
477 set_operation: None,
478 values: None,
479 };
480
481 left = vibesql_ast::Expression::In {
482 expr: Box::new(left),
483 subquery: Box::new(subquery),
484 negated: false,
485 };
486 } else {
487 self.expect_token(Token::LParen)?;
489
490 let (is_subquery_through_parens, extra_paren_depth) =
493 self.peek_select_through_parens();
494
495 if self.peek_keyword(Keyword::Select)
496 || self.peek_keyword(Keyword::Values)
497 || is_subquery_through_parens
498 {
499 for _ in 0..extra_paren_depth {
502 self.expect_token(Token::LParen)?;
503 }
504
505 let subquery = self.parse_select_statement()?;
506
507 for _ in 0..extra_paren_depth {
509 self.expect_token(Token::RParen)?;
510 }
511 self.expect_token(Token::RParen)?;
512
513 left = vibesql_ast::Expression::In {
515 expr: Box::new(left),
516 subquery: Box::new(subquery),
517 negated: false,
518 };
519 } else {
520 let values = self.parse_expression_list()?;
522 self.expect_token(Token::RParen)?;
523
524 left = vibesql_ast::Expression::InList {
527 expr: Box::new(left),
528 values,
529 negated: false,
530 };
531 }
532 }
533 } else if self.peek_keyword(Keyword::Between) {
534 self.consume_keyword(Keyword::Between)?;
536
537 let symmetric = if self.peek_keyword(Keyword::Symmetric) {
539 self.consume_keyword(Keyword::Symmetric)?;
540 true
541 } else {
542 if self.peek_keyword(Keyword::Asymmetric) {
544 self.consume_keyword(Keyword::Asymmetric)?;
545 }
546 false
547 };
548
549 let low = self.parse_additive_expression()?;
551 self.consume_keyword(Keyword::And)?;
552 let high = self.parse_additive_expression()?;
553
554 left = vibesql_ast::Expression::Between {
556 expr: Box::new(left),
557 low: Box::new(low),
558 high: Box::new(high),
559 negated: false,
560 symmetric,
561 };
562 } else if self.peek_keyword(Keyword::Like) {
563 self.consume_keyword(Keyword::Like)?;
565
566 let pattern = self.parse_additive_expression()?;
568
569 let escape = if self.peek_keyword(Keyword::Escape) {
571 self.consume_keyword(Keyword::Escape)?;
572 Some(Box::new(self.parse_additive_expression()?))
573 } else {
574 None
575 };
576
577 left = vibesql_ast::Expression::Like {
579 expr: Box::new(left),
580 pattern: Box::new(pattern),
581 negated: false,
582 escape,
583 };
584 } else if self.peek_keyword(Keyword::Glob) {
585 self.consume_keyword(Keyword::Glob)?;
587
588 let pattern = self.parse_additive_expression()?;
590
591 let escape = if self.peek_keyword(Keyword::Escape) {
593 self.consume_keyword(Keyword::Escape)?;
594 Some(Box::new(self.parse_additive_expression()?))
595 } else {
596 None
597 };
598
599 left = vibesql_ast::Expression::Glob {
601 expr: Box::new(left),
602 pattern: Box::new(pattern),
603 negated: false,
604 escape,
605 };
606 }
607
608 let is_comparison = match self.peek() {
611 Token::Symbol('=') | Token::Symbol('<') | Token::Symbol('>') => true,
612 Token::Operator(op) => !matches!(op, crate::token::MultiCharOperator::Concat),
613 _ => false,
614 };
615
616 if is_comparison {
617 let op = match self.peek() {
618 Token::Symbol('=') => vibesql_ast::BinaryOperator::Equal,
619 Token::Symbol('<') => vibesql_ast::BinaryOperator::LessThan,
620 Token::Symbol('>') => vibesql_ast::BinaryOperator::GreaterThan,
621 Token::Operator(op) => {
622 use crate::token::MultiCharOperator;
623 match op {
624 MultiCharOperator::LessEqual => {
625 vibesql_ast::BinaryOperator::LessThanOrEqual
626 }
627 MultiCharOperator::GreaterEqual => {
628 vibesql_ast::BinaryOperator::GreaterThanOrEqual
629 }
630 MultiCharOperator::NotEqual | MultiCharOperator::NotEqualAlt => {
631 vibesql_ast::BinaryOperator::NotEqual
632 }
633 MultiCharOperator::DoubleEqual => vibesql_ast::BinaryOperator::Equal,
635 MultiCharOperator::CosineDistance => {
637 vibesql_ast::BinaryOperator::CosineDistance
638 }
639 MultiCharOperator::NegativeInnerProduct => {
640 vibesql_ast::BinaryOperator::NegativeInnerProduct
641 }
642 MultiCharOperator::L2Distance => vibesql_ast::BinaryOperator::L2Distance,
643 MultiCharOperator::Concat
644 | MultiCharOperator::LeftShift
645 | MultiCharOperator::RightShift
646 | MultiCharOperator::JsonExtract
647 | MultiCharOperator::JsonExtractText => {
648 return Err(ParseError {
649 message: format!("Unexpected operator: {}", op),
650 })
651 }
652 }
653 }
654 _ => unreachable!(),
655 };
656 self.advance();
657
658 if self.peek_keyword(Keyword::All)
660 || self.peek_keyword(Keyword::Any)
661 || self.peek_keyword(Keyword::Some)
662 {
663 let quantifier = if self.peek_keyword(Keyword::All) {
664 self.consume_keyword(Keyword::All)?;
665 vibesql_ast::Quantifier::All
666 } else if self.peek_keyword(Keyword::Any) {
667 self.consume_keyword(Keyword::Any)?;
668 vibesql_ast::Quantifier::Any
669 } else {
670 self.consume_keyword(Keyword::Some)?;
671 vibesql_ast::Quantifier::Some
672 };
673
674 self.expect_token(Token::LParen)?;
676
677 let subquery = self.parse_select_statement()?;
679
680 self.expect_token(Token::RParen)?;
682
683 return Ok(vibesql_ast::Expression::QuantifiedComparison {
684 expr: Box::new(left),
685 op,
686 quantifier,
687 subquery: Box::new(subquery),
688 });
689 }
690
691 let right = self.parse_shift_expression()?;
692 left = vibesql_ast::Expression::BinaryOp {
693 op,
694 left: Box::new(left),
695 right: Box::new(right),
696 };
697 }
698
699 if self.peek_keyword(Keyword::Is) {
701 self.consume_keyword(Keyword::Is)?;
702
703 let negated = if self.peek_keyword(Keyword::Not) {
705 self.consume_keyword(Keyword::Not)?;
706 true
707 } else {
708 false
709 };
710
711 if self.peek_keyword(Keyword::Distinct) {
713 self.consume_keyword(Keyword::Distinct)?;
714 self.expect_keyword(Keyword::From)?;
715 let right = self.parse_shift_expression()?;
716 left = vibesql_ast::Expression::IsDistinctFrom {
717 left: Box::new(left),
718 right: Box::new(right),
719 negated,
720 };
721 } else if self.peek_keyword(Keyword::True) {
722 self.consume_keyword(Keyword::True)?;
723 left = vibesql_ast::Expression::IsTruthValue {
724 expr: Box::new(left),
725 truth_value: vibesql_ast::TruthValue::True,
726 negated,
727 };
728 } else if self.peek_keyword(Keyword::False) {
729 self.consume_keyword(Keyword::False)?;
730 left = vibesql_ast::Expression::IsTruthValue {
731 expr: Box::new(left),
732 truth_value: vibesql_ast::TruthValue::False,
733 negated,
734 };
735 } else if self.peek_keyword(Keyword::Unknown) {
736 self.consume_keyword(Keyword::Unknown)?;
737 left = vibesql_ast::Expression::IsTruthValue {
738 expr: Box::new(left),
739 truth_value: vibesql_ast::TruthValue::Unknown,
740 negated,
741 };
742 } else if self.peek_keyword(Keyword::Null) {
743 self.consume_keyword(Keyword::Null)?;
745 left = vibesql_ast::Expression::IsNull { expr: Box::new(left), negated };
746 } else {
747 let right = self.parse_shift_expression()?;
750 left = vibesql_ast::Expression::IsDistinctFrom {
751 left: Box::new(left),
752 right: Box::new(right),
753 negated: !negated,
756 };
757 }
758 }
759
760 loop {
764 if self.peek_keyword(Keyword::Isnull) {
765 self.consume_keyword(Keyword::Isnull)?;
766 left = vibesql_ast::Expression::IsNull { expr: Box::new(left), negated: false };
767 } else if self.peek_keyword(Keyword::Notnull) {
768 self.consume_keyword(Keyword::Notnull)?;
769 left = vibesql_ast::Expression::IsNull { expr: Box::new(left), negated: true };
770 } else {
771 break;
772 }
773 }
774
775 Ok(left)
776 }
777
778 pub(super) fn parse_unary_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
780 match self.peek() {
782 Token::Symbol('+') => {
783 self.advance();
784 let expr = self.parse_unary_expression()?;
785 Ok(vibesql_ast::Expression::UnaryOp {
786 op: vibesql_ast::UnaryOperator::Plus,
787 expr: Box::new(expr),
788 })
789 }
790 Token::Symbol('-') => {
791 self.advance();
792 if let Token::Number(n) = self.peek() {
797 if n == "9223372036854775808" {
798 self.advance();
800 return Ok(vibesql_ast::Expression::Literal(
801 vibesql_types::SqlValue::Integer(i64::MIN),
802 ));
803 }
804 }
805 let expr = self.parse_unary_expression()?;
806 Ok(vibesql_ast::Expression::UnaryOp {
807 op: vibesql_ast::UnaryOperator::Minus,
808 expr: Box::new(expr),
809 })
810 }
811 Token::Symbol('~') => {
812 self.advance();
813 let expr = self.parse_unary_expression()?;
814 Ok(vibesql_ast::Expression::UnaryOp {
815 op: vibesql_ast::UnaryOperator::BitwiseNot,
816 expr: Box::new(expr),
817 })
818 }
819 _ => self.parse_postfix_expression(),
820 }
821 }
822
823 pub(super) fn parse_postfix_expression(
826 &mut self,
827 ) -> Result<vibesql_ast::Expression, ParseError> {
828 let mut expr = self.parse_primary_expression()?;
829
830 loop {
832 let op = match self.peek() {
833 Token::Operator(crate::token::MultiCharOperator::JsonExtract) => {
834 vibesql_ast::BinaryOperator::JsonExtract
835 }
836 Token::Operator(crate::token::MultiCharOperator::JsonExtractText) => {
837 vibesql_ast::BinaryOperator::JsonExtractText
838 }
839 _ => break,
840 };
841 self.advance();
842
843 let right = self.parse_primary_expression()?;
845 expr = vibesql_ast::Expression::BinaryOp {
846 op,
847 left: Box::new(expr),
848 right: Box::new(right),
849 };
850 }
851
852 while self.peek_keyword(Keyword::Collate) {
854 self.consume_keyword(Keyword::Collate)?;
855 let collation = match self.peek() {
857 Token::Identifier(name) | Token::DelimitedIdentifier(name) => {
858 let name = name.clone();
859 self.advance();
860 name
861 }
862 Token::Keyword { keyword: kw, .. } => {
863 let name = kw.to_string();
865 self.advance();
866 name
867 }
868 _ => {
869 return Err(ParseError {
870 message: "Expected collation name after COLLATE".to_string(),
871 })
872 }
873 };
874 expr = vibesql_ast::Expression::Collate { expr: Box::new(expr), collation };
875 }
876
877 Ok(expr)
878 }
879
880 pub fn parse_expression_list(&mut self) -> Result<Vec<vibesql_ast::Expression>, ParseError> {
884 let mut expressions = Vec::new();
885
886 if matches!(self.peek(), Token::RParen) {
888 return Ok(expressions);
889 }
890
891 expressions.push(self.parse_expression()?);
893
894 while matches!(self.peek(), Token::Comma) {
896 self.advance(); expressions.push(self.parse_expression()?);
898 }
899
900 Ok(expressions)
901 }
902}