use crate::sql::parser::ast::{SimpleWhenBranch, SqlExpression, WhenBranch};
use crate::sql::parser::lexer::Token;
use tracing::debug;
use super::{log_parse_decision, trace_parse_entry, trace_parse_exit};
pub fn parse_case_expression<P>(parser: &mut P) -> Result<SqlExpression, String>
where
P: ParseCase + ?Sized,
{
trace_parse_entry("parse_case_expression", parser.current_token());
parser.consume(Token::Case)?;
debug!("Starting CASE expression parsing");
if !matches!(parser.current_token(), Token::When) {
debug!("Detected simple CASE syntax");
return parse_simple_case_expression(parser);
}
let mut when_branches = Vec::new();
while matches!(parser.current_token(), Token::When) {
log_parse_decision(
"parse_case_expression",
parser.current_token(),
"WHEN clause found, parsing condition and result",
);
parser.advance();
debug!("Parsing WHEN condition");
let condition = parser.parse_expression()?;
parser.consume(Token::Then)?;
debug!("Parsing THEN result");
let result = parser.parse_expression()?;
when_branches.push(WhenBranch {
condition: Box::new(condition),
result: Box::new(result),
});
debug!("Added WHEN branch #{}", when_branches.len());
}
if when_branches.is_empty() {
return Err("CASE expression must have at least one WHEN clause".to_string());
}
let else_branch = if matches!(parser.current_token(), Token::Else) {
log_parse_decision(
"parse_case_expression",
parser.current_token(),
"ELSE clause found, parsing default result",
);
parser.advance(); debug!("Parsing ELSE branch");
Some(Box::new(parser.parse_expression()?))
} else {
debug!("No ELSE branch");
None
};
parser.consume(Token::End)?;
debug!(
"Completed CASE expression with {} WHEN branches{}",
when_branches.len(),
if else_branch.is_some() {
" and ELSE"
} else {
""
}
);
let result = Ok(SqlExpression::CaseExpression {
when_branches,
else_branch,
});
trace_parse_exit("parse_case_expression", &result);
result
}
fn parse_simple_case_expression<P>(parser: &mut P) -> Result<SqlExpression, String>
where
P: ParseCase + ?Sized,
{
trace_parse_entry("parse_simple_case_expression", parser.current_token());
debug!("Parsing CASE expression value");
let expr = parser.parse_expression()?;
let mut when_branches = Vec::new();
while matches!(parser.current_token(), Token::When) {
log_parse_decision(
"parse_simple_case_expression",
parser.current_token(),
"WHEN clause found, parsing value and result",
);
parser.advance();
debug!("Parsing WHEN value");
let value = parser.parse_expression()?;
parser.consume(Token::Then)?;
debug!("Parsing THEN result");
let result = parser.parse_expression()?;
when_branches.push(SimpleWhenBranch {
value: Box::new(value),
result: Box::new(result),
});
debug!("Added simple WHEN branch #{}", when_branches.len());
}
if when_branches.is_empty() {
return Err("Simple CASE expression must have at least one WHEN clause".to_string());
}
let else_branch = if matches!(parser.current_token(), Token::Else) {
log_parse_decision(
"parse_simple_case_expression",
parser.current_token(),
"ELSE clause found, parsing default result",
);
parser.advance(); debug!("Parsing ELSE branch");
Some(Box::new(parser.parse_expression()?))
} else {
debug!("No ELSE branch");
None
};
parser.consume(Token::End)?;
debug!(
"Completed simple CASE expression with {} WHEN branches{}",
when_branches.len(),
if else_branch.is_some() {
" and ELSE"
} else {
""
}
);
let result = Ok(SqlExpression::SimpleCaseExpression {
expr: Box::new(expr),
when_branches,
else_branch,
});
trace_parse_exit("parse_simple_case_expression", &result);
result
}
pub trait ParseCase {
fn current_token(&self) -> &Token;
fn advance(&mut self);
fn consume(&mut self, expected: Token) -> Result<(), String>;
fn parse_expression(&mut self) -> Result<SqlExpression, String>;
}