use crate::error::{DbError, DbResult};
use crate::sdbql::ast::{ArrayQuantifier, BinaryOperator, Expression, UnaryOperator};
use crate::sdbql::lexer::Token;
use crate::sdbql::parser::Parser;
impl Parser {
pub(super) fn parse_ternary_expression(&mut self) -> DbResult<Expression> {
let condition = self.parse_null_coalesce_expression()?;
if matches!(self.current_token(), Token::Question) {
self.advance(); let true_expr = self.parse_ternary_expression()?; self.expect(Token::Colon)?;
let false_expr = self.parse_ternary_expression()?;
Ok(Expression::Ternary {
condition: Box::new(condition),
true_expr: Box::new(true_expr),
false_expr: Box::new(false_expr),
})
} else {
Ok(condition)
}
}
fn parse_null_coalesce_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_logical_or_expression()?;
while matches!(self.current_token(), Token::NullCoalesce) {
self.advance(); let right = self.parse_logical_or_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::NullCoalesce,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_logical_or_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_pipeline_expression()?;
while matches!(self.current_token(), Token::DoublePipe) {
self.advance(); let right = self.parse_pipeline_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::LogicalOr,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_pipeline_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_or_expression()?;
while matches!(self.current_token(), Token::PipeRight) {
self.advance();
let func_name = self.parse_pipeline_function_name()?;
self.expect(Token::LeftParen)?;
let args = self.parse_function_call_args()?;
let right = Expression::FunctionCall {
name: func_name,
args,
};
left = Expression::Pipeline {
left: Box::new(left),
right: Box::new(right),
};
}
Ok(left)
}
fn parse_pipeline_function_name(&mut self) -> DbResult<String> {
let name = match self.current_token() {
Token::Identifier(name) => name.clone(),
Token::Filter => "FILTER".to_string(),
Token::Sort => "SORT".to_string(),
Token::Count => "COUNT".to_string(),
Token::Any => "ANY".to_string(),
Token::Return => "RETURN".to_string(),
Token::In => "IN".to_string(),
Token::Replace => "REPLACE".to_string(),
Token::Like => "LIKE".to_string(),
Token::Left => "LEFT".to_string(),
Token::Right => "RIGHT".to_string(),
Token::Join => "JOIN".to_string(),
_ => {
return Err(DbError::ParseError(format!(
"Expected function name after |>, got {:?}",
self.current_token()
)));
}
};
self.advance();
Ok(name.to_uppercase())
}
pub(super) fn parse_or_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_and_expression()?;
while matches!(self.current_token(), Token::Or) {
self.advance();
let right = self.parse_and_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::Or,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_and_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_bitwise_or_expression()?;
while matches!(self.current_token(), Token::And) {
self.advance();
let right = self.parse_bitwise_or_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::And,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_bitwise_or_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_bitwise_xor_expression()?;
while matches!(self.current_token(), Token::Pipe) {
self.advance();
let right = self.parse_bitwise_xor_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::BitwiseOr,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_bitwise_xor_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_bitwise_and_expression()?;
while matches!(self.current_token(), Token::Caret) {
self.advance();
let right = self.parse_bitwise_and_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::BitwiseXor,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_bitwise_and_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_comparison_expression()?;
while matches!(self.current_token(), Token::Ampersand) {
self.advance();
let right = self.parse_comparison_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op: BinaryOperator::BitwiseAnd,
right: Box::new(right),
};
}
Ok(left)
}
pub(super) fn parse_comparison_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_range_expression()?;
loop {
if let Some(quantifier) = self.parse_array_quantifier()? {
let Some(op) = self.parse_comparison_operator()? else {
return Err(DbError::ParseError(format!(
"Expected a comparison operator after the array quantifier, found {:?}",
self.current_token()
)));
};
if !matches!(
op,
BinaryOperator::Equal
| BinaryOperator::NotEqual
| BinaryOperator::LessThan
| BinaryOperator::LessThanOrEqual
| BinaryOperator::GreaterThan
| BinaryOperator::GreaterThanOrEqual
| BinaryOperator::In
| BinaryOperator::NotIn
) {
return Err(DbError::ParseError(format!(
"Array comparison supports ==, !=, <, <=, >, >=, IN and NOT IN, not {:?}",
op
)));
}
let right = self.parse_range_expression()?;
left = Expression::ArrayComparison {
quantifier,
left: Box::new(left),
op,
right: Box::new(right),
};
continue;
}
let Some(op) = self.parse_comparison_operator()? else {
break;
};
let right = self.parse_range_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_array_quantifier(&mut self) -> DbResult<Option<ArrayQuantifier>> {
let simple = match self.current_token() {
Token::Any => Some(ArrayQuantifier::Any),
Token::Identifier(n) if n.eq_ignore_ascii_case("ALL") => Some(ArrayQuantifier::All),
Token::Identifier(n) if n.eq_ignore_ascii_case("NONE") => Some(ArrayQuantifier::None),
_ => None,
};
if let Some(quantifier) = simple {
if self.comparison_operator_at(1) {
self.advance();
return Ok(Some(quantifier));
}
return Ok(None);
}
if self.ident_eq("AT")
&& matches!(self.peek_token(1), Token::Identifier(n) if n.eq_ignore_ascii_case("LEAST"))
{
self.advance(); self.advance(); self.expect(Token::LeftParen)?;
let count = self.with_in_allowed(|p| p.parse_expression())?;
self.expect(Token::RightParen)?;
return Ok(Some(ArrayQuantifier::AtLeast(Box::new(count))));
}
Ok(None)
}
fn comparison_operator_at(&self, offset: usize) -> bool {
match self.peek_token(offset) {
Token::Equal
| Token::NotEqual
| Token::LessThan
| Token::LessThanEq
| Token::GreaterThan
| Token::GreaterThanEq => true,
Token::In => self.allow_in_operator,
Token::Not => {
self.allow_in_operator && matches!(self.peek_token(offset + 1), Token::In)
}
_ => false,
}
}
pub(super) fn parse_range_expression(&mut self) -> DbResult<Expression> {
let left = self.parse_shift_expression()?;
if matches!(self.current_token(), Token::DotDot) {
self.advance(); let right = self.parse_shift_expression()?;
Ok(Expression::Range(Box::new(left), Box::new(right)))
} else {
Ok(left)
}
}
fn parse_shift_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_additive_expression()?;
while matches!(self.current_token(), Token::LeftShift | Token::RightShift) {
let op = match self.current_token() {
Token::LeftShift => BinaryOperator::LeftShift,
Token::RightShift => BinaryOperator::RightShift,
_ => unreachable!(),
};
self.advance();
let right = self.parse_additive_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_additive_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_multiplicative_expression()?;
while matches!(self.current_token(), Token::Plus | Token::Minus) {
let op = match self.current_token() {
Token::Plus => BinaryOperator::Add,
Token::Minus => BinaryOperator::Subtract,
_ => unreachable!(),
};
self.advance();
let right = self.parse_multiplicative_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op,
right: Box::new(right),
};
}
Ok(left)
}
fn parse_multiplicative_expression(&mut self) -> DbResult<Expression> {
let mut left = self.parse_unary_expression()?;
while matches!(
self.current_token(),
Token::Star | Token::Slash | Token::Percent
) {
let op = match self.current_token() {
Token::Star => BinaryOperator::Multiply,
Token::Slash => BinaryOperator::Divide,
Token::Percent => BinaryOperator::Modulus,
_ => unreachable!(),
};
self.advance();
let right = self.parse_unary_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op,
right: Box::new(right),
};
}
Ok(left)
}
pub(super) fn parse_unary_expression(&mut self) -> DbResult<Expression> {
let op = match self.current_token() {
Token::Not => UnaryOperator::Not,
Token::Minus => UnaryOperator::Negate,
Token::Tilde => UnaryOperator::BitwiseNot,
_ => return self.parse_postfix_expression(),
};
self.advance();
self.check_depth()?;
let operand = self.parse_unary_expression();
self.leave_depth();
Ok(Expression::UnaryOp {
op,
operand: Box::new(operand?),
})
}
}