use crate::error::{DbError, DbResult};
use crate::sdbql::ast::{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(),
_ => {
return Err(DbError::ParseError(format!(
"Expected function name after |>, got {:?}",
self.current_token()
)));
}
};
self.advance();
Ok(name)
}
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()?;
while let Some(op) = self.parse_comparison_operator()? {
let right = self.parse_range_expression()?;
left = Expression::BinaryOp {
left: Box::new(left),
op,
right: Box::new(right),
};
}
Ok(left)
}
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> {
match self.current_token() {
Token::Not => {
self.advance();
let operand = self.parse_unary_expression()?;
Ok(Expression::UnaryOp {
op: UnaryOperator::Not,
operand: Box::new(operand),
})
}
Token::Minus => {
self.advance();
let operand = self.parse_unary_expression()?;
Ok(Expression::UnaryOp {
op: UnaryOperator::Negate,
operand: Box::new(operand),
})
}
Token::Tilde => {
self.advance();
let operand = self.parse_unary_expression()?;
Ok(Expression::UnaryOp {
op: UnaryOperator::BitwiseNot,
operand: Box::new(operand),
})
}
_ => self.parse_postfix_expression(),
}
}
}