use crate::sql::parser::ast::SqlExpression;
use crate::sql::parser::lexer::Token;
use tracing::debug;
use super::{log_parse_decision, trace_parse_entry, trace_parse_exit};
pub fn parse_logical_or<P>(parser: &mut P) -> Result<SqlExpression, String>
where
P: ParseLogical + ?Sized,
{
trace_parse_entry("parse_logical_or", parser.current_token());
let mut left = parser.parse_logical_and()?;
while matches!(parser.current_token(), Token::Or) {
log_parse_decision(
"parse_logical_or",
parser.current_token(),
"OR operator found, parsing right operand",
);
debug!("Processing logical OR operator");
parser.advance();
let right = parser.parse_logical_and()?;
left = SqlExpression::BinaryOp {
left: Box::new(left),
op: "OR".to_string(),
right: Box::new(right),
};
debug!("Created OR expression");
}
let result = Ok(left);
trace_parse_exit("parse_logical_or", &result);
result
}
pub fn parse_logical_and<P>(parser: &mut P) -> Result<SqlExpression, String>
where
P: ParseLogical + ?Sized,
{
trace_parse_entry("parse_logical_and", parser.current_token());
let mut left = parser.parse_base_logical_expression()?;
while matches!(parser.current_token(), Token::And) {
log_parse_decision(
"parse_logical_and",
parser.current_token(),
"AND operator found, parsing right operand",
);
debug!("Processing logical AND operator");
parser.advance();
let right = parser.parse_base_logical_expression()?;
left = SqlExpression::BinaryOp {
left: Box::new(left),
op: "AND".to_string(),
right: Box::new(right),
};
debug!("Created AND expression");
}
let result = Ok(left);
trace_parse_exit("parse_logical_and", &result);
result
}
pub fn parse_not_expression<P>(parser: &mut P) -> Result<SqlExpression, String>
where
P: ParseLogical + ?Sized,
{
trace_parse_entry("parse_not_expression", parser.current_token());
if !matches!(parser.current_token(), Token::Not) {
return Err("Expected NOT token".to_string());
}
log_parse_decision(
"parse_not_expression",
parser.current_token(),
"NOT operator found, parsing operand",
);
debug!("Processing NOT operator");
parser.advance();
let inner_expr = parser.parse_comparison()?;
if matches!(parser.current_token(), Token::In) {
debug!("NOT IN expression detected");
parser.advance(); parser.consume(Token::LeftParen)?;
let values = parser.parse_expression_list()?;
parser.consume(Token::RightParen)?;
let result = Ok(SqlExpression::NotInList {
expr: Box::new(inner_expr),
values,
});
trace_parse_exit("parse_not_expression", &result);
result
} else {
debug!("Creating NOT expression");
let result = Ok(SqlExpression::Not {
expr: Box::new(inner_expr),
});
trace_parse_exit("parse_not_expression", &result);
result
}
}
pub trait ParseLogical {
fn current_token(&self) -> &Token;
fn advance(&mut self);
fn consume(&mut self, expected: Token) -> Result<(), String>;
fn parse_logical_and(&mut self) -> Result<SqlExpression, String>;
fn parse_base_logical_expression(&mut self) -> Result<SqlExpression, String>;
fn parse_comparison(&mut self) -> Result<SqlExpression, String>;
fn parse_expression_list(&mut self) -> Result<Vec<SqlExpression>, String>;
}