1use crate::ast::{BinaryOp, Expr, ExprKind, Literal, Spanned, UnaryOp};
2use crate::error::{ParserError, Result};
3use crate::tokenizer::keyword::Keyword;
4use crate::tokenizer::token::{Token, Word};
5
6use super::Parser;
7use super::precedence::{PREC_UNKNOWN, Precedence};
8
9impl<'a> Parser<'a> {
10 pub(crate) fn parse_subexpr(&mut self, precedence: u8) -> Result<Expr> {
11 let _guard = self.recursion.try_decrease()?;
12
13 let mut expr = self.parse_prefix()?;
14
15 loop {
16 let next_prec = self.next_precedence();
17 if precedence >= next_prec || next_prec == PREC_UNKNOWN {
18 break;
19 }
20 expr = self.parse_infix(expr, next_prec)?;
21 }
22
23 Ok(expr)
24 }
25
26 fn parse_prefix(&mut self) -> Result<Expr> {
27 if let Some(res) = self.dialect.parse_prefix(self) {
28 return res;
29 }
30
31 let token = self.peek().clone();
32 match &token.token {
33 Token::Number(n) => {
34 self.advance();
35 Ok(Expr::new(
36 ExprKind::Literal(Literal::Number(n.clone())),
37 token.span,
38 ))
39 }
40 Token::SingleQuotedString(s) => {
41 self.advance();
42 Ok(Expr::new(
43 ExprKind::Literal(Literal::String(s.clone())),
44 token.span,
45 ))
46 }
47 Token::Word(Word { keyword, value, .. }) => match keyword {
48 Keyword::TRUE => {
49 self.advance();
50 Ok(Expr::new(
51 ExprKind::Literal(Literal::Boolean(true)),
52 token.span,
53 ))
54 }
55 Keyword::FALSE => {
56 self.advance();
57 Ok(Expr::new(
58 ExprKind::Literal(Literal::Boolean(false)),
59 token.span,
60 ))
61 }
62 Keyword::NULL => {
63 self.advance();
64 Ok(Expr::new(ExprKind::Literal(Literal::Null), token.span))
65 }
66 Keyword::NOT => {
67 self.advance();
68 let operand =
69 self.parse_subexpr(self.dialect.prec_value(Precedence::UnaryNot))?;
70 let span = token.span.union(&operand.span());
71 Ok(Expr::new(
72 ExprKind::UnaryOp {
73 op: UnaryOp::Not,
74 operand: Box::new(operand),
75 },
76 span,
77 ))
78 }
79 Keyword::NoKeyword => {
80 self.advance();
82 let ident_span = token.span;
83 if let Token::LParen = self.peek().token {
84 self.advance(); let mut args = Vec::new();
86 if !matches!(self.peek().token, Token::RParen) {
87 loop {
88 args.push(self.parse_subexpr(PREC_UNKNOWN)?);
89 if matches!(self.peek().token, Token::Comma) {
90 self.advance();
91 continue;
92 }
93 break;
94 }
95 }
96 self.expect_token("')'", |t| matches!(t, Token::RParen))?;
97 let end_span = self.prev().map(|t| t.span).unwrap_or(ident_span);
98 Ok(Expr::new(
99 ExprKind::FunctionCall {
100 name: value.clone(),
101 args,
102 },
103 ident_span.union(&end_span),
104 ))
105 } else if matches!(self.peek().token, Token::Period) {
106 self.advance(); let second = self.expect_token("identifier", |t| {
108 matches!(
109 t,
110 Token::Word(Word {
111 keyword: Keyword::NoKeyword,
112 ..
113 })
114 )
115 })?;
116 let end_span = second.span;
117 let col = match second.token {
118 Token::Word(Word { value, .. }) => value,
119 _ => unreachable!(),
120 };
121 Ok(Expr::new(
122 ExprKind::ColumnRef {
123 table: Some(value.clone()),
124 column: col,
125 },
126 ident_span.union(&end_span),
127 ))
128 } else {
129 Ok(Expr::new(
130 ExprKind::ColumnRef {
131 table: None,
132 column: value.clone(),
133 },
134 ident_span,
135 ))
136 }
137 }
138 _ => Err(ParserError::UnexpectedToken {
139 line: token.span.start.line,
140 column: token.span.start.column,
141 expected: "identifier or literal".into(),
142 found: format!("{:?}", token.token),
143 }),
144 },
145 Token::LParen => {
146 self.advance();
147 let expr = self.parse_subexpr(PREC_UNKNOWN)?;
148 self.expect_token("')'", |t| matches!(t, Token::RParen))?;
149 let end_span = self.prev().map(|t| t.span).unwrap_or(expr.span());
150 Ok(Expr::new(expr.kind.clone(), expr.span().union(&end_span)))
151 }
152 Token::Minus => {
153 self.advance();
154 let operand = self.parse_subexpr(self.dialect.prec_value(Precedence::UnaryNot))?;
155 let span = token.span.union(&operand.span());
156 Ok(Expr::new(
157 ExprKind::UnaryOp {
158 op: UnaryOp::Minus,
159 operand: Box::new(operand),
160 },
161 span,
162 ))
163 }
164 _ => Err(ParserError::UnexpectedToken {
165 line: token.span.start.line,
166 column: token.span.start.column,
167 expected: "expression".into(),
168 found: format!("{:?}", token.token),
169 }),
170 }
171 }
172
173 pub(crate) fn parse_vector_literal(&mut self) -> Result<Expr> {
174 let start = self.peek().span;
175 self.advance(); let mut values = Vec::new();
178 if matches!(self.peek().token, Token::RBracket) {
179 return Err(ParserError::InvalidVector {
180 line: start.start.line,
181 column: start.start.column,
182 });
183 }
184 loop {
185 let sign = if matches!(self.peek().token, Token::Minus) {
186 self.advance();
187 -1.0
188 } else {
189 1.0
190 };
191
192 let tok = self.expect_token("number", |t| matches!(t, Token::Number(_)))?;
193 let num = match tok.token {
194 Token::Number(n) => n.parse::<f64>().map_err(|_| ParserError::InvalidVector {
195 line: tok.span.start.line,
196 column: tok.span.start.column,
197 })?,
198 _ => unreachable!(),
199 } * sign;
200 values.push(num);
201 if matches!(self.peek().token, Token::Comma) {
202 self.advance();
203 continue;
204 }
205 break;
206 }
207 let end = self
208 .expect_token("']'", |t| matches!(t, Token::RBracket))?
209 .span;
210
211 Ok(Expr::new(
212 ExprKind::VectorLiteral(values),
213 start.union(&end),
214 ))
215 }
216
217 fn parse_infix(&mut self, left: Expr, precedence: u8) -> Result<Expr> {
218 let op_token = self.peek().clone();
219 match &op_token.token {
220 Token::Plus
221 | Token::Minus
222 | Token::Mul
223 | Token::Div
224 | Token::Mod
225 | Token::StringConcat => {
226 self.advance();
227 let op = match op_token.token {
228 Token::Plus => BinaryOp::Add,
229 Token::Minus => BinaryOp::Sub,
230 Token::Mul => BinaryOp::Mul,
231 Token::Div => BinaryOp::Div,
232 Token::Mod => BinaryOp::Mod,
233 Token::StringConcat => BinaryOp::StringConcat,
234 _ => unreachable!(),
235 };
236 let right = self.parse_subexpr(precedence)?;
237 let span = left.span().union(&right.span());
238 Ok(Expr::new(
239 ExprKind::BinaryOp {
240 left: Box::new(left),
241 op,
242 right: Box::new(right),
243 },
244 span,
245 ))
246 }
247 Token::Eq | Token::Neq | Token::Lt | Token::Gt | Token::LtEq | Token::GtEq => {
248 self.advance();
249 let op = match op_token.token {
250 Token::Eq => BinaryOp::Eq,
251 Token::Neq => BinaryOp::Neq,
252 Token::Lt => BinaryOp::Lt,
253 Token::Gt => BinaryOp::Gt,
254 Token::LtEq => BinaryOp::LtEq,
255 Token::GtEq => BinaryOp::GtEq,
256 _ => unreachable!(),
257 };
258 let right = self.parse_subexpr(precedence)?;
259 let span = left.span().union(&right.span());
260 Ok(Expr::new(
261 ExprKind::BinaryOp {
262 left: Box::new(left),
263 op,
264 right: Box::new(right),
265 },
266 span,
267 ))
268 }
269 Token::Word(Word { keyword, .. }) => match keyword {
270 Keyword::AND | Keyword::OR => {
271 self.advance();
272 let op = if *keyword == Keyword::AND {
273 BinaryOp::And
274 } else {
275 BinaryOp::Or
276 };
277 let right = self.parse_subexpr(precedence)?;
278 let span = left.span().union(&right.span());
279 Ok(Expr::new(
280 ExprKind::BinaryOp {
281 left: Box::new(left),
282 op,
283 right: Box::new(right),
284 },
285 span,
286 ))
287 }
288 Keyword::BETWEEN => {
289 self.advance();
290 let low = self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
291 self.expect_keyword("AND", Keyword::AND)?;
292 let high = self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
293 let span = left.span().union(&high.span());
294 Ok(Expr::new(
295 ExprKind::Between {
296 expr: Box::new(left),
297 low: Box::new(low),
298 high: Box::new(high),
299 negated: false,
300 },
301 span,
302 ))
303 }
304 Keyword::LIKE => {
305 self.advance();
306 let pattern = self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?;
307 let escape = if self.consume_keyword(Keyword::ESCAPE) {
308 Some(Box::new(
309 self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?,
310 ))
311 } else {
312 None
313 };
314 let span = left.span().union(&pattern.span());
315 let span = if let Some(ref esc) = escape {
316 span.union(&esc.span())
317 } else {
318 span
319 };
320 Ok(Expr::new(
321 ExprKind::Like {
322 expr: Box::new(left),
323 pattern: Box::new(pattern),
324 escape,
325 negated: false,
326 },
327 span,
328 ))
329 }
330 Keyword::IN => {
331 self.advance();
332 self.expect_token("'('", |t| matches!(t, Token::LParen))?;
333 let mut list = Vec::new();
334 if !matches!(self.peek().token, Token::RParen) {
335 loop {
336 list.push(self.parse_subexpr(PREC_UNKNOWN)?);
337 if matches!(self.peek().token, Token::Comma) {
338 self.advance();
339 continue;
340 }
341 break;
342 }
343 }
344 let end_span = self
345 .expect_token("')'", |t| matches!(t, Token::RParen))?
346 .span;
347 let span = left.span().union(&end_span);
348 Ok(Expr::new(
349 ExprKind::InList {
350 expr: Box::new(left),
351 list,
352 negated: false,
353 },
354 span,
355 ))
356 }
357 Keyword::IS => {
358 self.advance();
359 let negated = self.consume_keyword(Keyword::NOT);
360 self.expect_keyword("NULL", Keyword::NULL)?;
361 let span = left.span().union(&self.prev().unwrap().span);
362 Ok(Expr::new(
363 ExprKind::IsNull {
364 expr: Box::new(left),
365 negated,
366 },
367 span,
368 ))
369 }
370 Keyword::NOT => {
371 if let Some(next_kw) = self.peek_keyword_ahead(1) {
373 match next_kw {
374 Keyword::BETWEEN => {
375 self.advance(); self.advance(); let low = self
378 .parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
379 self.expect_keyword("AND", Keyword::AND)?;
380 let high = self
381 .parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
382 let span = left.span().union(&high.span());
383 return Ok(Expr::new(
384 ExprKind::Between {
385 expr: Box::new(left),
386 low: Box::new(low),
387 high: Box::new(high),
388 negated: true,
389 },
390 span,
391 ));
392 }
393 Keyword::LIKE => {
394 self.advance(); self.advance(); let pattern =
397 self.parse_subexpr(self.dialect.prec_value(Precedence::Like))?;
398 let escape = if self.consume_keyword(Keyword::ESCAPE) {
399 Some(Box::new(self.parse_subexpr(
400 self.dialect.prec_value(Precedence::Like),
401 )?))
402 } else {
403 None
404 };
405 let span = left.span().union(&pattern.span());
406 let span = if let Some(ref esc) = escape {
407 span.union(&esc.span())
408 } else {
409 span
410 };
411 return Ok(Expr::new(
412 ExprKind::Like {
413 expr: Box::new(left),
414 pattern: Box::new(pattern),
415 escape,
416 negated: true,
417 },
418 span,
419 ));
420 }
421 Keyword::IN => {
422 self.advance(); self.advance(); self.expect_token("'('", |t| matches!(t, Token::LParen))?;
425 let mut list = Vec::new();
426 if !matches!(self.peek().token, Token::RParen) {
427 loop {
428 list.push(self.parse_subexpr(PREC_UNKNOWN)?);
429 if matches!(self.peek().token, Token::Comma) {
430 self.advance();
431 continue;
432 }
433 break;
434 }
435 }
436 let end_span = self
437 .expect_token("')'", |t| matches!(t, Token::RParen))?
438 .span;
439 let span = left.span().union(&end_span);
440 return Ok(Expr::new(
441 ExprKind::InList {
442 expr: Box::new(left),
443 list,
444 negated: true,
445 },
446 span,
447 ));
448 }
449 _ => {}
450 }
451 }
452 Err(ParserError::UnexpectedToken {
453 line: op_token.span.start.line,
454 column: op_token.span.start.column,
455 expected: "BETWEEN, LIKE, IN".into(),
456 found: "NOT".into(),
457 })
458 }
459 _ => Err(ParserError::UnexpectedToken {
460 line: op_token.span.start.line,
461 column: op_token.span.start.column,
462 expected: "operator".into(),
463 found: format!("{:?}", op_token.token),
464 }),
465 },
466 _ => Err(ParserError::UnexpectedToken {
467 line: op_token.span.start.line,
468 column: op_token.span.start.column,
469 expected: "operator".into(),
470 found: format!("{:?}", op_token.token),
471 }),
472 }
473 }
474}