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(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
75 let mut left = self.parse_multiplicative_expression()?;
76
77 loop {
78 let op = match self.peek() {
79 Token::Symbol('+') => vibesql_ast::BinaryOperator::Plus,
80 Token::Symbol('-') => vibesql_ast::BinaryOperator::Minus,
81 Token::Operator(crate::token::MultiCharOperator::Concat) => {
82 vibesql_ast::BinaryOperator::Concat
83 }
84 _ => break,
85 };
86 self.advance();
87
88 let right = self.parse_multiplicative_expression()?;
89 left = vibesql_ast::Expression::BinaryOp { op, left: Box::new(left), right: Box::new(right) };
90 }
91
92 Ok(left)
93 }
94
95 pub(super) fn parse_multiplicative_expression(
97 &mut self,
98 ) -> Result<vibesql_ast::Expression, ParseError> {
99 let mut left = self.parse_unary_expression()?;
100
101 loop {
102 let op = match self.peek() {
103 Token::Symbol('*') => vibesql_ast::BinaryOperator::Multiply,
104 Token::Symbol('/') => vibesql_ast::BinaryOperator::Divide,
105 Token::Symbol('%') => vibesql_ast::BinaryOperator::Modulo,
106 Token::Keyword(Keyword::Div) => vibesql_ast::BinaryOperator::IntegerDivide,
107 _ => break,
108 };
109 self.advance();
110
111 let right = self.parse_unary_expression()?;
112 left = vibesql_ast::Expression::BinaryOp { op, left: Box::new(left), right: Box::new(right) };
113 }
114
115 Ok(left)
116 }
117
118 pub(super) fn parse_comparison_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
121 let mut left = self.parse_additive_expression()?;
122
123 if self.peek_keyword(Keyword::Not) {
125 let saved_pos = self.position;
127 self.advance(); if self.peek_keyword(Keyword::In) {
130 self.consume_keyword(Keyword::In)?;
132
133 self.expect_token(Token::LParen)?;
135
136 if self.peek_keyword(Keyword::Select) {
138 let subquery = self.parse_select_statement()?;
140 self.expect_token(Token::RParen)?;
141
142 return Ok(vibesql_ast::Expression::In {
143 expr: Box::new(left),
144 subquery: Box::new(subquery),
145 negated: true,
146 });
147 } else {
148 let values = self.parse_expression_list()?;
150 self.expect_token(Token::RParen)?;
151
152 return Ok(vibesql_ast::Expression::InList {
154 expr: Box::new(left),
155 values,
156 negated: true,
157 });
158 }
159 } else if self.peek_keyword(Keyword::Between) {
160 self.consume_keyword(Keyword::Between)?;
162
163 let symmetric = if self.peek_keyword(Keyword::Symmetric) {
165 self.consume_keyword(Keyword::Symmetric)?;
166 true
167 } else {
168 if self.peek_keyword(Keyword::Asymmetric) {
170 self.consume_keyword(Keyword::Asymmetric)?;
171 }
172 false
173 };
174
175 let low = self.parse_additive_expression()?;
177 self.consume_keyword(Keyword::And)?;
178 let high = self.parse_additive_expression()?;
179
180 return Ok(vibesql_ast::Expression::Between {
181 expr: Box::new(left),
182 low: Box::new(low),
183 high: Box::new(high),
184 negated: true,
185 symmetric,
186 });
187 } else if self.peek_keyword(Keyword::Like) {
188 self.consume_keyword(Keyword::Like)?;
190
191 let pattern = self.parse_additive_expression()?;
193
194 return Ok(vibesql_ast::Expression::Like {
195 expr: Box::new(left),
196 pattern: Box::new(pattern),
197 negated: true,
198 });
199 } else {
200 self.position = saved_pos;
203 }
204 } else if self.peek_keyword(Keyword::In) {
205 self.consume_keyword(Keyword::In)?;
207
208 self.expect_token(Token::LParen)?;
210
211 if self.peek_keyword(Keyword::Select) {
213 let subquery = self.parse_select_statement()?;
215 self.expect_token(Token::RParen)?;
216
217 return Ok(vibesql_ast::Expression::In {
218 expr: Box::new(left),
219 subquery: Box::new(subquery),
220 negated: false,
221 });
222 } else {
223 let values = self.parse_expression_list()?;
225 self.expect_token(Token::RParen)?;
226
227 return Ok(vibesql_ast::Expression::InList {
229 expr: Box::new(left),
230 values,
231 negated: false,
232 });
233 }
234 } else if self.peek_keyword(Keyword::Between) {
235 self.consume_keyword(Keyword::Between)?;
237
238 let symmetric = if self.peek_keyword(Keyword::Symmetric) {
240 self.consume_keyword(Keyword::Symmetric)?;
241 true
242 } else {
243 if self.peek_keyword(Keyword::Asymmetric) {
245 self.consume_keyword(Keyword::Asymmetric)?;
246 }
247 false
248 };
249
250 let low = self.parse_additive_expression()?;
252 self.consume_keyword(Keyword::And)?;
253 let high = self.parse_additive_expression()?;
254
255 return Ok(vibesql_ast::Expression::Between {
256 expr: Box::new(left),
257 low: Box::new(low),
258 high: Box::new(high),
259 negated: false,
260 symmetric,
261 });
262 } else if self.peek_keyword(Keyword::Like) {
263 self.consume_keyword(Keyword::Like)?;
265
266 let pattern = self.parse_additive_expression()?;
268
269 return Ok(vibesql_ast::Expression::Like {
270 expr: Box::new(left),
271 pattern: Box::new(pattern),
272 negated: false,
273 });
274 }
275
276 let is_comparison = match self.peek() {
279 Token::Symbol('=') | Token::Symbol('<') | Token::Symbol('>') => true,
280 Token::Operator(op) => !matches!(op, crate::token::MultiCharOperator::Concat),
281 _ => false,
282 };
283
284 if is_comparison {
285 let op = match self.peek() {
286 Token::Symbol('=') => vibesql_ast::BinaryOperator::Equal,
287 Token::Symbol('<') => vibesql_ast::BinaryOperator::LessThan,
288 Token::Symbol('>') => vibesql_ast::BinaryOperator::GreaterThan,
289 Token::Operator(op) => {
290 use crate::token::MultiCharOperator;
291 match op {
292 MultiCharOperator::LessEqual => vibesql_ast::BinaryOperator::LessThanOrEqual,
293 MultiCharOperator::GreaterEqual => {
294 vibesql_ast::BinaryOperator::GreaterThanOrEqual
295 }
296 MultiCharOperator::NotEqual | MultiCharOperator::NotEqualAlt => {
297 vibesql_ast::BinaryOperator::NotEqual
298 }
299 MultiCharOperator::Concat => {
300 return Err(ParseError {
301 message: format!("Unexpected operator: {}", op),
302 })
303 }
304 }
305 }
306 _ => unreachable!(),
307 };
308 self.advance();
309
310 if self.peek_keyword(Keyword::All)
312 || self.peek_keyword(Keyword::Any)
313 || self.peek_keyword(Keyword::Some)
314 {
315 let quantifier = if self.peek_keyword(Keyword::All) {
316 self.consume_keyword(Keyword::All)?;
317 vibesql_ast::Quantifier::All
318 } else if self.peek_keyword(Keyword::Any) {
319 self.consume_keyword(Keyword::Any)?;
320 vibesql_ast::Quantifier::Any
321 } else {
322 self.consume_keyword(Keyword::Some)?;
323 vibesql_ast::Quantifier::Some
324 };
325
326 self.expect_token(Token::LParen)?;
328
329 let subquery = self.parse_select_statement()?;
331
332 self.expect_token(Token::RParen)?;
334
335 return Ok(vibesql_ast::Expression::QuantifiedComparison {
336 expr: Box::new(left),
337 op,
338 quantifier,
339 subquery: Box::new(subquery),
340 });
341 }
342
343 let right = self.parse_additive_expression()?;
344 left = vibesql_ast::Expression::BinaryOp { op, left: Box::new(left), right: Box::new(right) };
345 }
346
347 if self.peek_keyword(Keyword::Is) {
349 self.consume_keyword(Keyword::Is)?;
350
351 let negated = if self.peek_keyword(Keyword::Not) {
353 self.consume_keyword(Keyword::Not)?;
354 true
355 } else {
356 false
357 };
358
359 self.expect_keyword(Keyword::Null)?;
361
362 left = vibesql_ast::Expression::IsNull { expr: Box::new(left), negated };
363 }
364
365 Ok(left)
366 }
367
368 pub(super) fn parse_unary_expression(&mut self) -> Result<vibesql_ast::Expression, ParseError> {
370 match self.peek() {
372 Token::Symbol('+') => {
373 self.advance();
374 let expr = self.parse_unary_expression()?;
375 Ok(vibesql_ast::Expression::UnaryOp { op: vibesql_ast::UnaryOperator::Plus, expr: Box::new(expr) })
376 }
377 Token::Symbol('-') => {
378 self.advance();
379 let expr = self.parse_unary_expression()?;
380 Ok(vibesql_ast::Expression::UnaryOp { op: vibesql_ast::UnaryOperator::Minus, expr: Box::new(expr) })
381 }
382 _ => self.parse_primary_expression(),
383 }
384 }
385
386 pub fn parse_expression_list(&mut self) -> Result<Vec<vibesql_ast::Expression>, ParseError> {
390 let mut expressions = Vec::new();
391
392 if matches!(self.peek(), Token::RParen) {
394 return Ok(expressions);
395 }
396
397 expressions.push(self.parse_expression()?);
399
400 while matches!(self.peek(), Token::Comma) {
402 self.advance(); expressions.push(self.parse_expression()?);
404 }
405
406 Ok(expressions)
407 }
408}