vibesql_parser/parser/expressions/
operators.rs1use 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::Exists)
54 {
55 self.position = saved_pos;
57 return self.parse_comparison_expression();
58 }
59
60 let expr = self.parse_not_expression()?;
63
64 Ok(vibesql_ast::Expression::UnaryOp {
65 op: vibesql_ast::UnaryOperator::Not,
66 expr: Box::new(expr),
67 })
68 } else {
69 self.parse_comparison_expression()
70 }
71 }
72
73 pub(super) fn parse_additive_expression(
75 &mut self,
76 ) -> Result<vibesql_ast::Expression, ParseError> {
77 let mut left = self.parse_multiplicative_expression()?;
78
79 loop {
80 let op = match self.peek() {
81 Token::Symbol('+') => vibesql_ast::BinaryOperator::Plus,
82 Token::Symbol('-') => vibesql_ast::BinaryOperator::Minus,
83 Token::Operator(crate::token::MultiCharOperator::Concat) => {
84 vibesql_ast::BinaryOperator::Concat
85 }
86 _ => break,
87 };
88 self.advance();
89
90 let right = self.parse_multiplicative_expression()?;
91 left = vibesql_ast::Expression::BinaryOp {
92 op,
93 left: Box::new(left),
94 right: Box::new(right),
95 };
96 }
97
98 Ok(left)
99 }
100
101 pub(super) fn parse_multiplicative_expression(
103 &mut self,
104 ) -> Result<vibesql_ast::Expression, ParseError> {
105 let mut left = self.parse_unary_expression()?;
106
107 loop {
108 let op = match self.peek() {
109 Token::Symbol('*') => vibesql_ast::BinaryOperator::Multiply,
110 Token::Symbol('/') => vibesql_ast::BinaryOperator::Divide,
111 Token::Symbol('%') => vibesql_ast::BinaryOperator::Modulo,
112 Token::Keyword(Keyword::Div) => vibesql_ast::BinaryOperator::IntegerDivide,
113 _ => break,
114 };
115 self.advance();
116
117 let right = self.parse_unary_expression()?;
118 left = vibesql_ast::Expression::BinaryOp {
119 op,
120 left: Box::new(left),
121 right: Box::new(right),
122 };
123 }
124
125 Ok(left)
126 }
127
128 pub(super) fn parse_comparison_expression(
131 &mut self,
132 ) -> Result<vibesql_ast::Expression, ParseError> {
133 let mut left = self.parse_additive_expression()?;
134
135 if self.peek_keyword(Keyword::Not) {
137 let saved_pos = self.position;
139 self.advance(); if self.peek_keyword(Keyword::In) {
142 self.consume_keyword(Keyword::In)?;
144
145 self.expect_token(Token::LParen)?;
147
148 if self.peek_keyword(Keyword::Select) {
150 let subquery = self.parse_select_statement()?;
152 self.expect_token(Token::RParen)?;
153
154 return Ok(vibesql_ast::Expression::In {
155 expr: Box::new(left),
156 subquery: Box::new(subquery),
157 negated: true,
158 });
159 } else {
160 let values = self.parse_expression_list()?;
162 self.expect_token(Token::RParen)?;
163
164 return Ok(vibesql_ast::Expression::InList {
166 expr: Box::new(left),
167 values,
168 negated: true,
169 });
170 }
171 } else if self.peek_keyword(Keyword::Between) {
172 self.consume_keyword(Keyword::Between)?;
174
175 let symmetric = if self.peek_keyword(Keyword::Symmetric) {
177 self.consume_keyword(Keyword::Symmetric)?;
178 true
179 } else {
180 if self.peek_keyword(Keyword::Asymmetric) {
182 self.consume_keyword(Keyword::Asymmetric)?;
183 }
184 false
185 };
186
187 let low = self.parse_additive_expression()?;
189 self.consume_keyword(Keyword::And)?;
190 let high = self.parse_additive_expression()?;
191
192 return Ok(vibesql_ast::Expression::Between {
193 expr: Box::new(left),
194 low: Box::new(low),
195 high: Box::new(high),
196 negated: true,
197 symmetric,
198 });
199 } else if self.peek_keyword(Keyword::Like) {
200 self.consume_keyword(Keyword::Like)?;
202
203 let pattern = self.parse_additive_expression()?;
205
206 return Ok(vibesql_ast::Expression::Like {
207 expr: Box::new(left),
208 pattern: Box::new(pattern),
209 negated: true,
210 });
211 } else {
212 self.position = saved_pos;
215 }
216 } else if self.peek_keyword(Keyword::In) {
217 self.consume_keyword(Keyword::In)?;
219
220 self.expect_token(Token::LParen)?;
222
223 if self.peek_keyword(Keyword::Select) {
225 let subquery = self.parse_select_statement()?;
227 self.expect_token(Token::RParen)?;
228
229 return Ok(vibesql_ast::Expression::In {
230 expr: Box::new(left),
231 subquery: Box::new(subquery),
232 negated: false,
233 });
234 } else {
235 let values = self.parse_expression_list()?;
237 self.expect_token(Token::RParen)?;
238
239 return Ok(vibesql_ast::Expression::InList {
241 expr: Box::new(left),
242 values,
243 negated: false,
244 });
245 }
246 } else if self.peek_keyword(Keyword::Between) {
247 self.consume_keyword(Keyword::Between)?;
249
250 let symmetric = if self.peek_keyword(Keyword::Symmetric) {
252 self.consume_keyword(Keyword::Symmetric)?;
253 true
254 } else {
255 if self.peek_keyword(Keyword::Asymmetric) {
257 self.consume_keyword(Keyword::Asymmetric)?;
258 }
259 false
260 };
261
262 let low = self.parse_additive_expression()?;
264 self.consume_keyword(Keyword::And)?;
265 let high = self.parse_additive_expression()?;
266
267 return Ok(vibesql_ast::Expression::Between {
268 expr: Box::new(left),
269 low: Box::new(low),
270 high: Box::new(high),
271 negated: false,
272 symmetric,
273 });
274 } else if self.peek_keyword(Keyword::Like) {
275 self.consume_keyword(Keyword::Like)?;
277
278 let pattern = self.parse_additive_expression()?;
280
281 return Ok(vibesql_ast::Expression::Like {
282 expr: Box::new(left),
283 pattern: Box::new(pattern),
284 negated: false,
285 });
286 }
287
288 let is_comparison = match self.peek() {
291 Token::Symbol('=') | Token::Symbol('<') | Token::Symbol('>') => true,
292 Token::Operator(op) => !matches!(op, crate::token::MultiCharOperator::Concat),
293 _ => false,
294 };
295
296 if is_comparison {
297 let op = match self.peek() {
298 Token::Symbol('=') => vibesql_ast::BinaryOperator::Equal,
299 Token::Symbol('<') => vibesql_ast::BinaryOperator::LessThan,
300 Token::Symbol('>') => vibesql_ast::BinaryOperator::GreaterThan,
301 Token::Operator(op) => {
302 use crate::token::MultiCharOperator;
303 match op {
304 MultiCharOperator::LessEqual => {
305 vibesql_ast::BinaryOperator::LessThanOrEqual
306 }
307 MultiCharOperator::GreaterEqual => {
308 vibesql_ast::BinaryOperator::GreaterThanOrEqual
309 }
310 MultiCharOperator::NotEqual | MultiCharOperator::NotEqualAlt => {
311 vibesql_ast::BinaryOperator::NotEqual
312 }
313 MultiCharOperator::CosineDistance => {
315 vibesql_ast::BinaryOperator::CosineDistance
316 }
317 MultiCharOperator::NegativeInnerProduct => {
318 vibesql_ast::BinaryOperator::NegativeInnerProduct
319 }
320 MultiCharOperator::L2Distance => vibesql_ast::BinaryOperator::L2Distance,
321 MultiCharOperator::Concat => {
322 return Err(ParseError {
323 message: format!("Unexpected operator: {}", op),
324 })
325 }
326 }
327 }
328 _ => unreachable!(),
329 };
330 self.advance();
331
332 if self.peek_keyword(Keyword::All)
334 || self.peek_keyword(Keyword::Any)
335 || self.peek_keyword(Keyword::Some)
336 {
337 let quantifier = if self.peek_keyword(Keyword::All) {
338 self.consume_keyword(Keyword::All)?;
339 vibesql_ast::Quantifier::All
340 } else if self.peek_keyword(Keyword::Any) {
341 self.consume_keyword(Keyword::Any)?;
342 vibesql_ast::Quantifier::Any
343 } else {
344 self.consume_keyword(Keyword::Some)?;
345 vibesql_ast::Quantifier::Some
346 };
347
348 self.expect_token(Token::LParen)?;
350
351 let subquery = self.parse_select_statement()?;
353
354 self.expect_token(Token::RParen)?;
356
357 return Ok(vibesql_ast::Expression::QuantifiedComparison {
358 expr: Box::new(left),
359 op,
360 quantifier,
361 subquery: Box::new(subquery),
362 });
363 }
364
365 let right = self.parse_additive_expression()?;
366 left = vibesql_ast::Expression::BinaryOp {
367 op,
368 left: Box::new(left),
369 right: Box::new(right),
370 };
371 }
372
373 if self.peek_keyword(Keyword::Is) {
375 self.consume_keyword(Keyword::Is)?;
376
377 let negated = if self.peek_keyword(Keyword::Not) {
379 self.consume_keyword(Keyword::Not)?;
380 true
381 } else {
382 false
383 };
384
385 self.expect_keyword(Keyword::Null)?;
387
388 left = vibesql_ast::Expression::IsNull { expr: Box::new(left), negated };
389 }
390
391 Ok(left)
392 }
393
394 pub(super) fn parse_unary_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
396 match self.peek() {
398 Token::Symbol('+') => {
399 self.advance();
400 let expr = self.parse_unary_expression()?;
401 Ok(vibesql_ast::Expression::UnaryOp {
402 op: vibesql_ast::UnaryOperator::Plus,
403 expr: Box::new(expr),
404 })
405 }
406 Token::Symbol('-') => {
407 self.advance();
408 let expr = self.parse_unary_expression()?;
409 Ok(vibesql_ast::Expression::UnaryOp {
410 op: vibesql_ast::UnaryOperator::Minus,
411 expr: Box::new(expr),
412 })
413 }
414 _ => self.parse_primary_expression(),
415 }
416 }
417
418 pub fn parse_expression_list(&mut self) -> Result<Vec<vibesql_ast::Expression>, ParseError> {
422 let mut expressions = Vec::new();
423
424 if matches!(self.peek(), Token::RParen) {
426 return Ok(expressions);
427 }
428
429 expressions.push(self.parse_expression()?);
431
432 while matches!(self.peek(), Token::Comma) {
434 self.advance(); expressions.push(self.parse_expression()?);
436 }
437
438 Ok(expressions)
439 }
440}