sql_cli/sql/parser/expressions/
arithmetic.rs1use crate::sql::parser::ast::SqlExpression;
6use crate::sql::parser::lexer::Token;
7use tracing::debug;
8
9use super::{log_parse_decision, trace_parse_entry, trace_parse_exit};
10
11pub fn parse_additive<P>(parser: &mut P) -> Result<SqlExpression, String>
14where
15 P: ParseArithmetic + ?Sized,
16{
17 trace_parse_entry("parse_additive", parser.current_token());
18
19 let mut left = parser.parse_multiplicative()?;
20
21 while matches!(parser.current_token(), Token::Plus | Token::Minus) {
22 let op = match parser.current_token() {
23 Token::Plus => "+",
24 Token::Minus => "-",
25 _ => unreachable!(),
26 };
27
28 log_parse_decision(
29 "parse_additive",
30 parser.current_token(),
31 &format!("Binary operator '{}' found, parsing right operand", op),
32 );
33
34 parser.advance();
35 let right = parser.parse_multiplicative()?;
36
37 debug!(operator = op, "Creating additive binary operation");
38
39 left = SqlExpression::BinaryOp {
40 left: Box::new(left),
41 op: op.to_string(),
42 right: Box::new(right),
43 };
44 }
45
46 let result = Ok(left);
47 trace_parse_exit("parse_additive", &result);
48 result
49}
50
51pub fn parse_multiplicative<P>(parser: &mut P) -> Result<SqlExpression, String>
55where
56 P: ParseArithmetic + ?Sized,
57{
58 trace_parse_entry("parse_multiplicative", parser.current_token());
59
60 let mut left = parser.parse_primary()?;
61
62 while matches!(parser.current_token(), Token::Dot) {
65 debug!("Found dot operator");
66 parser.advance();
67
68 if let Token::Identifier(name) = parser.current_token() {
69 let name_str = name.clone();
70 parser.advance();
71
72 if matches!(parser.current_token(), Token::LeftParen) {
73 log_parse_decision(
75 "parse_multiplicative",
76 parser.current_token(),
77 &format!("Method call '{}' detected", name_str),
78 );
79
80 parser.advance();
81 let args = parser.parse_method_args()?;
82 parser.consume(Token::RightParen)?;
83
84 left = match left {
86 SqlExpression::Column(obj) => {
87 debug!(
89 column = %obj,
90 method = %name_str,
91 "Creating method call on column"
92 );
93 SqlExpression::MethodCall {
94 object: obj,
95 method: name_str,
96 args,
97 }
98 }
99 SqlExpression::MethodCall { .. } | SqlExpression::ChainedMethodCall { .. } => {
100 debug!(
102 method = %name_str,
103 "Creating chained method call"
104 );
105 SqlExpression::ChainedMethodCall {
106 base: Box::new(left),
107 method: name_str,
108 args,
109 }
110 }
111 _ => {
112 debug!(
114 method = %name_str,
115 "Creating method call on expression"
116 );
117 SqlExpression::ChainedMethodCall {
118 base: Box::new(left),
119 method: name_str,
120 args,
121 }
122 }
123 };
124 } else {
125 left = match left {
128 SqlExpression::Column(table_or_alias) => {
129 debug!(
130 table = %table_or_alias,
131 column = %name_str,
132 "Creating qualified column reference"
133 );
134 SqlExpression::Column(format!("{}.{}", table_or_alias, name_str))
135 }
136 _ => {
137 return Err(format!(
139 "Invalid qualified column reference with expression"
140 ));
141 }
142 };
143 }
144 } else {
145 return Err("Expected identifier after '.'".to_string());
146 }
147 }
148
149 while matches!(
151 parser.current_token(),
152 Token::Star | Token::Divide | Token::Modulo
153 ) {
154 let op = match parser.current_token() {
155 Token::Star => "*",
156 Token::Divide => "/",
157 Token::Modulo => "%",
158 _ => unreachable!(),
159 };
160
161 log_parse_decision(
162 "parse_multiplicative",
163 parser.current_token(),
164 &format!("Binary operator '{}' found, parsing right operand", op),
165 );
166
167 parser.advance();
168 let right = parser.parse_primary()?;
169
170 debug!(operator = op, "Creating multiplicative binary operation");
171
172 left = SqlExpression::BinaryOp {
173 left: Box::new(left),
174 op: op.to_string(),
175 right: Box::new(right),
176 };
177 }
178
179 let result = Ok(left);
180 trace_parse_exit("parse_multiplicative", &result);
181 result
182}
183
184pub trait ParseArithmetic {
186 fn current_token(&self) -> &Token;
187 fn advance(&mut self);
188 fn consume(&mut self, expected: Token) -> Result<(), String>;
189
190 fn parse_primary(&mut self) -> Result<SqlExpression, String>;
192 fn parse_multiplicative(&mut self) -> Result<SqlExpression, String>;
193 fn parse_method_args(&mut self) -> Result<Vec<SqlExpression>, String>;
194}