polyspec_crudui_validator/expr/
parser.rs1use super::ast::{LiteralValue, Node, PathSegment};
20use super::error::ParseError;
21use super::token::{Literal, Token, TokenType};
22
23pub const MAX_EXPRESSION_DEPTH: usize = 64;
26
27pub struct Parser {
29 tokens: Vec<Token>,
30 current: usize,
31 open: usize,
33 height: usize,
35}
36
37impl Parser {
38 pub fn new(tokens: Vec<Token>) -> Self {
40 Parser {
41 tokens,
42 current: 0,
43 open: 0,
44 height: 0,
45 }
46 }
47
48 pub fn parse(&mut self) -> Result<Node, ParseError> {
50 let expression = self.parse_ternary_expression()?;
51
52 if !self.is_at_end() {
53 return Err(ParseError::new(format!(
54 "Unexpected token after expression: {}",
55 self.peek().value
56 )));
57 }
58
59 Ok(expression)
60 }
61
62 fn parse_ternary_expression(&mut self) -> Result<Node, ParseError> {
64 let condition = self.parse_or_expression()?;
65
66 if self.match_type(TokenType::Question) {
67 let condition_height = self.height;
68 self.enter()?;
69 let true_value = self.parse_ternary_expression()?;
70 let true_height = self.height;
71
72 if !self.match_type(TokenType::Colon) {
73 return Err(ParseError::new("Missing colon in ternary expression"));
74 }
75
76 let false_value = self.parse_ternary_expression()?;
77 self.open -= 1;
78
79 self.node(condition_height.max(true_height).max(self.height))?;
80 return Ok(Node::Ternary {
81 condition: Box::new(condition),
82 true_value: Box::new(true_value),
83 false_value: Box::new(false_value),
84 });
85 }
86
87 Ok(condition)
88 }
89
90 fn parse_or_expression(&mut self) -> Result<Node, ParseError> {
92 let mut left = self.parse_and_expression()?;
93 let mut height = self.height;
94
95 while self.match_type(TokenType::Or) {
96 let right = self.parse_and_expression()?;
97 height = self.node(height.max(self.height))?;
98 left = Node::Binary {
99 operator: "||".to_string(),
100 left: Box::new(left),
101 right: Box::new(right),
102 };
103 }
104
105 Ok(left)
106 }
107
108 fn parse_and_expression(&mut self) -> Result<Node, ParseError> {
110 let mut left = self.parse_not_expression()?;
111 let mut height = self.height;
112
113 while self.match_type(TokenType::And) {
114 let right = self.parse_not_expression()?;
115 height = self.node(height.max(self.height))?;
116 left = Node::Binary {
117 operator: "&&".to_string(),
118 left: Box::new(left),
119 right: Box::new(right),
120 };
121 }
122
123 Ok(left)
124 }
125
126 fn parse_not_expression(&mut self) -> Result<Node, ParseError> {
128 if self.match_type(TokenType::Not) {
129 self.enter()?;
130 let operand = self.parse_not_expression()?;
131 self.open -= 1;
132 self.node(self.height)?;
133 return Ok(Node::Unary {
134 operator: "!".to_string(),
135 operand: Box::new(operand),
136 });
137 }
138
139 self.parse_comparison()
140 }
141
142 fn parse_comparison(&mut self) -> Result<Node, ParseError> {
144 let left = self.parse_primary()?;
145 let left_height = self.height;
146
147 if self.match_any(&[TokenType::In, TokenType::NotIn]) {
148 let negated = self.previous().token_type == TokenType::NotIn;
149 let list = self.parse_value_list()?;
150 self.node(left_height)?;
151 return Ok(Node::In {
152 negated,
153 value: Box::new(left),
154 list,
155 });
156 }
157
158 if self.match_any(&[
159 TokenType::Eq,
160 TokenType::Ne,
161 TokenType::Gt,
162 TokenType::Ge,
163 TokenType::Lt,
164 TokenType::Le,
165 ]) {
166 let operator = self.previous().value.clone();
167 let right = self.parse_comparison_value()?;
168 self.node(left_height.max(self.height))?;
169 return Ok(Node::Binary {
170 operator,
171 left: Box::new(left),
172 right: Box::new(right),
173 });
174 }
175
176 Ok(left)
177 }
178
179 fn parse_value_list(&mut self) -> Result<Vec<Node>, ParseError> {
181 let mut values = Vec::new();
182
183 let has_brackets = self.match_type(TokenType::LBracket);
184
185 values.push(self.parse_value_list_item()?);
186
187 while self.match_type(TokenType::Comma) {
188 values.push(self.parse_value_list_item()?);
189 }
190
191 if has_brackets && !self.match_type(TokenType::RBracket) {
192 return Err(ParseError::new("Missing closing bracket in value list"));
193 }
194
195 Ok(values)
196 }
197
198 fn parse_value_list_item(&mut self) -> Result<Node, ParseError> {
199 if self.match_type(TokenType::Identifier) {
201 return Ok(Node::Literal(LiteralValue::Str(
202 self.previous().value.clone(),
203 )));
204 }
205
206 if self.match_type(TokenType::Number) {
207 return Ok(Node::Literal(number_literal(&self.previous().literal)));
208 }
209
210 if self.match_type(TokenType::String) {
211 return Ok(Node::Literal(LiteralValue::Str(string_literal(
212 &self.previous().literal,
213 ))));
214 }
215
216 Err(ParseError::new(format!(
217 "Invalid value in list: {}",
218 self.peek().value
219 )))
220 }
221
222 fn parse_comparison_value(&mut self) -> Result<Node, ParseError> {
226 if self.check(TokenType::Identifier) {
227 let saved = self.current;
228 self.advance(); if !self.check(TokenType::Dot) {
231 self.height = 1;
232 return Ok(Node::Literal(LiteralValue::Str(
233 self.previous().value.clone(),
234 )));
235 }
236
237 self.current = saved;
239 }
240
241 self.parse_primary()
242 }
243
244 fn parse_primary(&mut self) -> Result<Node, ParseError> {
246 if self.match_type(TokenType::LParen) {
247 self.enter()?;
248 let expression = self.parse_or_expression()?;
249 self.open -= 1;
250 if !self.match_type(TokenType::RParen) {
251 return Err(ParseError::new("Missing closing parenthesis"));
252 }
253 self.node(self.height)?;
254 return Ok(Node::Group(Box::new(expression)));
255 }
256
257 self.height = 1;
259
260 if self.check(TokenType::Dot)
261 || self.check(TokenType::DotDot)
262 || self.check(TokenType::Identifier)
263 {
264 return self.parse_path();
265 }
266
267 if self.match_type(TokenType::String) {
268 return Ok(Node::Literal(LiteralValue::Str(string_literal(
269 &self.previous().literal,
270 ))));
271 }
272
273 if self.match_type(TokenType::Number) {
274 return Ok(Node::Literal(number_literal(&self.previous().literal)));
275 }
276
277 if self.match_type(TokenType::Boolean) {
278 let b = matches!(self.previous().literal, Literal::Bool(true));
279 return Ok(Node::Literal(LiteralValue::Bool(b)));
280 }
281
282 if self.match_type(TokenType::Null) {
283 return Ok(Node::Literal(LiteralValue::Null));
284 }
285
286 Err(ParseError::new(format!(
287 "Unexpected token in expression: {}",
288 self.peek().value
289 )))
290 }
291
292 fn parse_path(&mut self) -> Result<Node, ParseError> {
294 let mut relative = false;
295 let mut levels_up: i64 = 0;
296 let mut segments: Vec<PathSegment> = Vec::new();
297
298 if self.match_type(TokenType::DotDot) {
299 relative = true;
300 let dots = match self.previous().literal {
301 Literal::DotCount(n) => n,
302 _ => 0,
303 };
304 levels_up = dots - 1;
305 } else if self.match_type(TokenType::Dot) {
306 relative = true;
307 levels_up = 0;
308 }
309
310 if self.match_type(TokenType::Identifier) {
311 segments.push(PathSegment::Identifier(self.previous().value.clone()));
312 } else if relative {
313 return Err(ParseError::new("Missing field name after dot prefix"));
314 }
315
316 while self.match_type(TokenType::Dot) {
317 if self.match_type(TokenType::Asterisk) {
318 segments.push(PathSegment::Wildcard);
319 } else if self.match_type(TokenType::Number) {
320 let idx = match &self.previous().literal {
321 Literal::Int(n) => *n,
322 Literal::Float(f) => *f as i64,
323 _ => 0,
324 };
325 segments.push(PathSegment::Index(idx));
326 } else if self.match_type(TokenType::Identifier) {
327 segments.push(PathSegment::Identifier(self.previous().value.clone()));
328 } else {
329 return Err(ParseError::new(format!(
330 "Invalid path segment after dot: {}",
331 self.peek().value
332 )));
333 }
334 }
335
336 Ok(Node::Path {
337 relative,
338 levels_up,
339 segments,
340 })
341 }
342
343 fn enter(&mut self) -> Result<(), ParseError> {
346 self.open += 1;
347 if self.open >= MAX_EXPRESSION_DEPTH {
348 return Err(too_deep());
349 }
350 Ok(())
351 }
352
353 fn node(&mut self, child_height: usize) -> Result<usize, ParseError> {
356 self.height = child_height + 1;
357 if self.height > MAX_EXPRESSION_DEPTH {
358 return Err(too_deep());
359 }
360 Ok(self.height)
361 }
362
363 fn match_type(&mut self, t: TokenType) -> bool {
364 if self.check(t) {
365 self.advance();
366 return true;
367 }
368 false
369 }
370
371 fn match_any(&mut self, types: &[TokenType]) -> bool {
372 for &t in types {
373 if self.check(t) {
374 self.advance();
375 return true;
376 }
377 }
378 false
379 }
380
381 fn check(&self, t: TokenType) -> bool {
382 if self.is_at_end() {
383 return false;
384 }
385 self.peek().token_type == t
386 }
387
388 fn advance(&mut self) -> &Token {
389 if !self.is_at_end() {
390 self.current += 1;
391 }
392 self.previous()
393 }
394
395 fn is_at_end(&self) -> bool {
396 self.peek().token_type == TokenType::Eof
397 }
398
399 fn peek(&self) -> &Token {
400 &self.tokens[self.current]
401 }
402
403 fn previous(&self) -> &Token {
404 &self.tokens[self.current - 1]
405 }
406}
407
408fn too_deep() -> ParseError {
409 ParseError::new(format!(
410 "Expression is nested more than {MAX_EXPRESSION_DEPTH} levels deep"
411 ))
412}
413
414fn number_literal(lit: &Literal) -> LiteralValue {
415 match lit {
416 Literal::Int(n) => LiteralValue::Int(*n),
417 Literal::Float(f) => LiteralValue::Float(*f),
418 _ => LiteralValue::Int(0),
419 }
420}
421
422fn string_literal(lit: &Literal) -> String {
423 match lit {
424 Literal::Str(s) => s.clone(),
425 _ => String::new(),
426 }
427}