/home/noah/src/ruchy/src/frontend/parser/expressions.rs
Line | Count | Source |
1 | | //! Basic expression parsing - minimal version with only used functions |
2 | | |
3 | | use super::{ParserState, *}; |
4 | | |
5 | 1.35k | pub fn parse_prefix(state: &mut ParserState) -> Result<Expr> { |
6 | 1.35k | let Some((token1.34k , span1.34k )) = state.tokens.peek() else { |
7 | 15 | bail!("Unexpected end of input - expected expression"); |
8 | | }; |
9 | | |
10 | 1.34k | let token_clone = token.clone(); |
11 | 1.34k | let span_clone = *span; |
12 | | |
13 | 1.34k | match token_clone { |
14 | | // Literal tokens - delegated to focused helper |
15 | | Token::Integer(_) | Token::Float(_) | Token::String(_) | |
16 | | Token::FString(_) | Token::Char(_) | Token::Bool(_) => { |
17 | 527 | parse_literal_token(state, token_clone, span_clone) |
18 | | } |
19 | | // Identifier tokens - delegated to focused helper |
20 | | Token::Identifier(_) | Token::Underscore => { |
21 | 354 | parse_identifier_token(state, token_clone, span_clone) |
22 | | } |
23 | | // Unary operator tokens - delegated to focused helper |
24 | | Token::Minus | Token::Bang => { |
25 | 91 | parse_unary_operator_token(state, token_clone, span_clone) |
26 | | } |
27 | | // Function/block tokens - delegated to focused helper |
28 | | Token::Fun | Token::Fn | Token::LeftBrace => { |
29 | 136 | parse_function_block_token(state, token_clone) |
30 | | } |
31 | | // Variable declaration tokens - delegated to focused helper |
32 | | Token::Let | Token::Var => { |
33 | 64 | parse_variable_declaration_token(state, token_clone) |
34 | | } |
35 | | // Control flow tokens - delegated to focused helper |
36 | | Token::If | Token::Match | Token::While | Token::For => { |
37 | 30 | parse_control_flow_token(state, token_clone) |
38 | | } |
39 | | // Lambda expression tokens - delegated to focused helper |
40 | | Token::Pipe | Token::OrOr => { |
41 | 23 | parse_lambda_token(state, token_clone) |
42 | | } |
43 | | // Parentheses tokens - delegated to focused helper (unit, grouping, tuples, lambdas) |
44 | | Token::LeftParen => { |
45 | 22 | parse_parentheses_token(state, span_clone) |
46 | | } |
47 | | // Data structure definition tokens - delegated to focused helper |
48 | | Token::Struct | Token::Trait | Token::Impl => { |
49 | 8 | parse_data_structure_token(state, token_clone) |
50 | | } |
51 | | // Import/module tokens - delegated to focused helper |
52 | | Token::Import | Token::Use => { |
53 | 3 | parse_import_token(state, token_clone) |
54 | | } |
55 | | // Special definition tokens - delegated to focused helper |
56 | | Token::DataFrame | Token::Actor => { |
57 | 6 | parse_special_definition_token(state, token_clone) |
58 | | } |
59 | | // Control statement tokens - delegated to focused helper |
60 | | Token::Pub | Token::Break | Token::Continue | Token::Return => { |
61 | 5 | parse_control_statement_token(state, token_clone, span_clone) |
62 | | } |
63 | | // Collection/enum definition tokens - delegated to focused helper |
64 | | Token::LeftBracket | Token::Enum => { |
65 | 48 | parse_collection_enum_token(state, token_clone) |
66 | | } |
67 | | // Constructor tokens - delegated to focused helper |
68 | | Token::Some | Token::None | Token::Ok | Token::Err | Token::Result | Token::Option => { |
69 | 0 | parse_constructor_token(state, token_clone, span_clone) |
70 | | } |
71 | 23 | _ => bail!("Unexpected token: {:?}", token_clone), |
72 | | } |
73 | 1.35k | } |
74 | | |
75 | | /// Parse literal tokens (Integer, Float, String, Char, Bool, `FString`) |
76 | | /// Extracted from `parse_prefix` to reduce complexity |
77 | 527 | fn parse_literal_token(state: &mut ParserState, token: Token, span: Span) -> Result<Expr> { |
78 | 527 | match token { |
79 | 368 | Token::Integer(value) => { |
80 | 368 | state.tokens.advance(); |
81 | 368 | Ok(Expr::new(ExprKind::Literal(Literal::Integer(value)), span)) |
82 | | } |
83 | 14 | Token::Float(value) => { |
84 | 14 | state.tokens.advance(); |
85 | 14 | Ok(Expr::new(ExprKind::Literal(Literal::Float(value)), span)) |
86 | | } |
87 | 100 | Token::String(value) => { |
88 | 100 | state.tokens.advance(); |
89 | 100 | Ok(Expr::new(ExprKind::Literal(Literal::String(value)), span)) |
90 | | } |
91 | 4 | Token::FString(template) => { |
92 | 4 | state.tokens.advance(); |
93 | | // Parse f-string template into parts |
94 | | // For now, treat it as a simple string with placeholders |
95 | 4 | let parts = vec![StringPart::Text(template)]; |
96 | 4 | Ok(Expr::new(ExprKind::StringInterpolation { parts }, span)) |
97 | | } |
98 | 0 | Token::Char(value) => { |
99 | 0 | state.tokens.advance(); |
100 | 0 | Ok(Expr::new(ExprKind::Literal(Literal::Char(value)), span)) |
101 | | } |
102 | 41 | Token::Bool(value) => { |
103 | 41 | state.tokens.advance(); |
104 | 41 | Ok(Expr::new(ExprKind::Literal(Literal::Bool(value)), span)) |
105 | | } |
106 | 0 | _ => bail!("Expected literal token, got: {:?}", token), |
107 | | } |
108 | 527 | } |
109 | | |
110 | | /// Parse identifier tokens (Identifier, Underscore, fat arrow lambdas) |
111 | | /// Extracted from `parse_prefix` to reduce complexity |
112 | 354 | fn parse_identifier_token(state: &mut ParserState, token: Token, span: Span) -> Result<Expr> { |
113 | 354 | match token { |
114 | 354 | Token::Identifier(name) => { |
115 | 354 | state.tokens.advance(); |
116 | | // Check for fat arrow lambda: x => x * 2 |
117 | 354 | if matches!353 (state.tokens.peek(), Some((Token::FatArrow, _))) { |
118 | 1 | state.tokens.advance(); // consume => |
119 | 1 | let body = Box::new(super::parse_expr_recursive(state)?0 ); |
120 | 1 | let params = vec![Param { |
121 | 1 | pattern: Pattern::Identifier(name), |
122 | 1 | ty: Type { |
123 | 1 | kind: TypeKind::Named("_".to_string()), |
124 | 1 | span, |
125 | 1 | }, |
126 | 1 | default_value: None, |
127 | 1 | is_mutable: false, |
128 | 1 | span, |
129 | 1 | }]; |
130 | 1 | Ok(Expr::new(ExprKind::Lambda { params, body }, span)) |
131 | | } else { |
132 | 353 | Ok(Expr::new(ExprKind::Identifier(name), span)) |
133 | | } |
134 | | } |
135 | | Token::Underscore => { |
136 | 0 | state.tokens.advance(); |
137 | 0 | Ok(Expr::new(ExprKind::Identifier("_".to_string()), span)) |
138 | | } |
139 | 0 | _ => bail!("Expected identifier token, got: {:?}", token), |
140 | | } |
141 | 354 | } |
142 | | |
143 | | /// Parse unary operator tokens (Minus, Bang) |
144 | | /// Extracted from `parse_prefix` to reduce complexity |
145 | 91 | fn parse_unary_operator_token(state: &mut ParserState, token: Token, span: Span) -> Result<Expr> { |
146 | 91 | match token { |
147 | | Token::Minus => { |
148 | 4 | state.tokens.advance(); |
149 | 4 | let expr = super::parse_expr_with_precedence_recursive(state, 13)?0 ; // High precedence for unary |
150 | 4 | Ok(Expr::new(ExprKind::Unary { |
151 | 4 | op: UnaryOp::Negate, |
152 | 4 | operand: Box::new(expr) |
153 | 4 | }, span)) |
154 | | } |
155 | | Token::Bang => { |
156 | 87 | state.tokens.advance(); |
157 | 87 | let expr22 = super::parse_expr_with_precedence_recursive(state, 13)?65 ; |
158 | 22 | Ok(Expr::new(ExprKind::Unary { |
159 | 22 | op: UnaryOp::Not, |
160 | 22 | operand: Box::new(expr) |
161 | 22 | }, span)) |
162 | | } |
163 | 0 | _ => bail!("Expected unary operator token, got: {:?}", token), |
164 | | } |
165 | 91 | } |
166 | | |
167 | | /// Parse parentheses tokens - either unit type (), grouped expression (expr), or tuple (a, b, c) |
168 | | /// Extracted from `parse_prefix` to reduce complexity |
169 | 22 | fn parse_parentheses_token(state: &mut ParserState, span: Span) -> Result<Expr> { |
170 | 22 | state.tokens.advance(); |
171 | | // Check for unit type () |
172 | 22 | if matches!19 (state.tokens.peek(), Some((Token::RightParen, _))) { |
173 | 3 | state.tokens.advance(); |
174 | 3 | Ok(Expr::new(ExprKind::Literal(Literal::Unit), span)) |
175 | | } else { |
176 | | // Parse first expression |
177 | 19 | let first_expr = super::parse_expr_recursive(state)?0 ; |
178 | | |
179 | | // Check if we have a comma (tuple) or just closing paren (grouped expr) |
180 | 19 | if matches!18 (state.tokens.peek(), Some((Token::Comma, _))) { |
181 | | // This is a tuple, parse remaining elements |
182 | 1 | let mut elements = vec![first_expr]; |
183 | | |
184 | 2 | while matches!1 (state.tokens.peek(), Some((Token::Comma, _))) { |
185 | 1 | state.tokens.advance(); // consume comma |
186 | | |
187 | | // Check for trailing comma before closing paren |
188 | 1 | if matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
189 | 0 | break; |
190 | 1 | } |
191 | | |
192 | 1 | elements.push(super::parse_expr_recursive(state)?0 ); |
193 | | } |
194 | | |
195 | 1 | state.tokens.expect(&Token::RightParen)?0 ; |
196 | 1 | Ok(Expr::new(ExprKind::Tuple(elements), span)) |
197 | | } else { |
198 | | // Just a grouped expression |
199 | 18 | state.tokens.expect(&Token::RightParen)?0 ; |
200 | | |
201 | | // Check if this is a lambda: (x) => expr |
202 | 18 | if matches!16 (state.tokens.peek(), Some((Token::FatArrow, _))) { |
203 | 2 | parse_lambda_from_expr(state, first_expr, span) |
204 | | } else { |
205 | 16 | Ok(first_expr) |
206 | | } |
207 | | } |
208 | | } |
209 | 22 | } |
210 | | |
211 | | /// Parse pub token - handles public declarations for functions, structs, traits, impl blocks |
212 | | /// Extracted from `parse_prefix` to reduce complexity |
213 | 5 | fn parse_pub_token(state: &mut ParserState) -> Result<Expr> { |
214 | 5 | state.tokens.advance(); |
215 | | // Get the next token to determine what follows pub |
216 | 5 | let mut expr = parse_prefix(state)?0 ; |
217 | | // Mark the expression as public if it supports it |
218 | 5 | match &mut expr.kind { |
219 | 5 | ExprKind::Function { is_pub, .. } => *is_pub = true, |
220 | 0 | ExprKind::Struct { is_pub, .. } => *is_pub = true, |
221 | 0 | ExprKind::Trait { is_pub, .. } => *is_pub = true, |
222 | 0 | ExprKind::Impl { is_pub, .. } => *is_pub = true, |
223 | 0 | _ => {} // Other expressions don't have is_pub |
224 | | } |
225 | 5 | Ok(expr) |
226 | 5 | } |
227 | | |
228 | | /// Parse break token with optional label |
229 | | /// Extracted from `parse_prefix` to reduce complexity |
230 | 0 | fn parse_break_token(state: &mut ParserState, span: Span) -> Result<Expr> { |
231 | 0 | state.tokens.advance(); |
232 | | // Optional label |
233 | 0 | let label = if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
234 | 0 | let label = Some(name.clone()); |
235 | 0 | state.tokens.advance(); |
236 | 0 | label |
237 | | } else { |
238 | 0 | None |
239 | | }; |
240 | 0 | Ok(Expr::new(ExprKind::Break { label }, span)) |
241 | 0 | } |
242 | | |
243 | | /// Parse continue token with optional label |
244 | | /// Extracted from `parse_prefix` to reduce complexity |
245 | 0 | fn parse_continue_token(state: &mut ParserState, span: Span) -> Result<Expr> { |
246 | 0 | state.tokens.advance(); |
247 | | // Optional label |
248 | 0 | let label = if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
249 | 0 | let label = Some(name.clone()); |
250 | 0 | state.tokens.advance(); |
251 | 0 | label |
252 | | } else { |
253 | 0 | None |
254 | | }; |
255 | 0 | Ok(Expr::new(ExprKind::Continue { label }, span)) |
256 | 0 | } |
257 | | |
258 | | /// Parse return token with optional expression |
259 | | /// Extracted from `parse_prefix` to reduce complexity |
260 | 0 | fn parse_return_token(state: &mut ParserState, span: Span) -> Result<Expr> { |
261 | 0 | state.tokens.advance(); |
262 | | // Check if there's an expression to return |
263 | 0 | let value = if matches!(state.tokens.peek(), Some((Token::Semicolon, _))) |
264 | 0 | || state.tokens.peek().is_none() { |
265 | | // No expression, just return |
266 | 0 | None |
267 | | } else { |
268 | | // Parse the return expression |
269 | 0 | Some(Box::new(super::parse_expr_recursive(state)?)) |
270 | | }; |
271 | 0 | Ok(Expr::new(ExprKind::Return { value }, span)) |
272 | 0 | } |
273 | | |
274 | | /// Parse constructor tokens (Some, None, Ok, Err, Result, Option) |
275 | | /// Extracted from `parse_prefix` to reduce complexity |
276 | 0 | fn parse_constructor_token(state: &mut ParserState, token: Token, span: Span) -> Result<Expr> { |
277 | 0 | let constructor_name = match token { |
278 | 0 | Token::Some => "Some", |
279 | 0 | Token::None => "None", |
280 | 0 | Token::Ok => "Ok", |
281 | 0 | Token::Err => "Err", |
282 | 0 | Token::Result => "Result", |
283 | 0 | Token::Option => "Option", |
284 | 0 | _ => bail!("Expected constructor token, got: {:?}", token), |
285 | | }; |
286 | | |
287 | 0 | state.tokens.advance(); |
288 | 0 | Ok(Expr::new(ExprKind::Identifier(constructor_name.to_string()), span)) |
289 | 0 | } |
290 | | |
291 | | /// Parse control flow tokens (If, Match, While, For) |
292 | | /// Extracted from `parse_prefix` to reduce complexity |
293 | 30 | fn parse_control_flow_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
294 | 30 | match token { |
295 | 19 | Token::If => parse_if_expression(state), |
296 | 7 | Token::Match => parse_match_expression(state), |
297 | 2 | Token::While => parse_while_loop(state), |
298 | 2 | Token::For => parse_for_loop(state), |
299 | 0 | _ => bail!("Expected control flow token, got: {:?}", token), |
300 | | } |
301 | 30 | } |
302 | | |
303 | | /// Parse data structure definition tokens (Struct, Trait, Impl) |
304 | | /// Extracted from `parse_prefix` to reduce complexity |
305 | 8 | fn parse_data_structure_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
306 | 8 | match token { |
307 | 6 | Token::Struct => parse_struct_definition(state), |
308 | 1 | Token::Trait => parse_trait_definition(state), |
309 | 1 | Token::Impl => parse_impl_block(state), |
310 | 0 | _ => bail!("Expected data structure token, got: {:?}", token), |
311 | | } |
312 | 8 | } |
313 | | |
314 | | /// Parse import/module tokens (Import, Use) |
315 | | /// Extracted from `parse_prefix` to reduce complexity |
316 | 3 | fn parse_import_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
317 | 3 | match token { |
318 | 1 | Token::Import => parse_import_statement(state), |
319 | 2 | Token::Use => parse_use_statement(state), |
320 | 0 | _ => bail!("Expected import token, got: {:?}", token), |
321 | | } |
322 | 3 | } |
323 | | |
324 | | /// Parse lambda expression tokens (Pipe, `OrOr`)\ |
325 | | /// Extracted from `parse_prefix` to reduce complexity |
326 | 23 | fn parse_lambda_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
327 | 23 | match token { |
328 | 22 | Token::Pipe => parse_lambda_expression(state), |
329 | 1 | Token::OrOr => parse_lambda_no_params(state), |
330 | 0 | _ => bail!("Expected lambda token, got: {:?}", token), |
331 | | } |
332 | 23 | } |
333 | | |
334 | | /// Parse function/block tokens (Fun, Fn, `LeftBrace`) |
335 | | /// Extracted from `parse_prefix` to reduce complexity |
336 | 136 | fn parse_function_block_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
337 | 136 | match token { |
338 | 47 | Token::Fun | Token::Fn => super::functions::parse_function(state), |
339 | 89 | Token::LeftBrace => super::collections::parse_block(state), |
340 | 0 | _ => bail!("Expected function/block token, got: {:?}", token), |
341 | | } |
342 | 136 | } |
343 | | |
344 | | /// Parse variable declaration tokens (Let, Var) |
345 | | /// Extracted from `parse_prefix` to reduce complexity |
346 | 64 | fn parse_variable_declaration_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
347 | 64 | match token { |
348 | 64 | Token::Let => parse_let_statement(state), |
349 | 0 | Token::Var => parse_var_statement(state), |
350 | 0 | _ => bail!("Expected variable declaration token, got: {:?}", token), |
351 | | } |
352 | 64 | } |
353 | | |
354 | | /// Parse special definition tokens (`DataFrame`, Actor) |
355 | | /// Extracted from `parse_prefix` to reduce complexity |
356 | 6 | fn parse_special_definition_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
357 | 6 | match token { |
358 | 5 | Token::DataFrame => parse_dataframe_literal(state), |
359 | 1 | Token::Actor => parse_actor_definition(state), |
360 | 0 | _ => bail!("Expected special definition token, got: {:?}", token), |
361 | | } |
362 | 6 | } |
363 | | |
364 | | /// Parse control statement tokens (Pub, Break, Continue, Return) |
365 | | /// Extracted from `parse_prefix` to reduce complexity |
366 | 5 | fn parse_control_statement_token(state: &mut ParserState, token: Token, span: Span) -> Result<Expr> { |
367 | 5 | match token { |
368 | 5 | Token::Pub => parse_pub_token(state), |
369 | 0 | Token::Break => parse_break_token(state, span), |
370 | 0 | Token::Continue => parse_continue_token(state, span), |
371 | 0 | Token::Return => parse_return_token(state, span), |
372 | 0 | _ => bail!("Expected control statement token, got: {:?}", token), |
373 | | } |
374 | 5 | } |
375 | | |
376 | | /// Parse collection/enum definition tokens (`LeftBracket`, Enum) |
377 | | /// Extracted from `parse_prefix` to reduce complexity |
378 | 48 | fn parse_collection_enum_token(state: &mut ParserState, token: Token) -> Result<Expr> { |
379 | 48 | match token { |
380 | 46 | Token::LeftBracket => parse_list_literal(state), |
381 | 2 | Token::Enum => parse_enum_definition(state), |
382 | 0 | _ => bail!("Expected collection/enum token, got: {:?}", token), |
383 | | } |
384 | 48 | } |
385 | | |
386 | | /// Parse let statement: let [mut] name [: type] = value [in body] |
387 | 64 | fn parse_let_statement(state: &mut ParserState) -> Result<Expr> { |
388 | 64 | let start_span = state.tokens.expect(&Token::Let)?0 ; |
389 | | |
390 | | // Check for optional 'mut' keyword |
391 | 64 | let is_mutable = parse_let_mutability(state); |
392 | | |
393 | | // Parse variable name or destructuring pattern |
394 | 64 | let pattern63 = parse_let_pattern(state, is_mutable)?1 ; |
395 | | |
396 | | // Parse optional type annotation |
397 | 63 | let type_annotation = parse_let_type_annotation(state)?0 ; |
398 | | |
399 | | // Parse '=' token |
400 | 63 | state.tokens.expect(&Token::Equal)?0 ; |
401 | | |
402 | | // Parse value expression |
403 | 63 | let value61 = Box::new61 (super::parse_expr_recursive(state)?2 ); |
404 | | |
405 | | // Parse optional 'in' clause for let expressions |
406 | 61 | let body = parse_let_in_clause(state, value.span)?0 ; |
407 | | |
408 | | // Create the appropriate expression based on pattern type |
409 | 61 | create_let_expression(pattern, type_annotation, value, body, is_mutable, start_span) |
410 | 64 | } |
411 | | |
412 | | /// Parse mutability for let statement |
413 | | /// Extracted from `parse_let_statement` to reduce complexity |
414 | 64 | fn parse_let_mutability(state: &mut ParserState) -> bool { |
415 | 64 | if matches!63 (state.tokens.peek(), Some((Token::Mut, _))) { |
416 | 1 | state.tokens.advance(); |
417 | 1 | true |
418 | | } else { |
419 | 63 | false |
420 | | } |
421 | 64 | } |
422 | | |
423 | | /// Parse pattern for let statement (identifier or destructuring) |
424 | | /// Extracted from `parse_let_statement` to reduce complexity |
425 | 64 | fn parse_let_pattern(state: &mut ParserState, is_mutable: bool) -> Result<Pattern> { |
426 | 64 | match state.tokens.peek() { |
427 | 63 | Some((Token::Identifier(name), _)) => { |
428 | 63 | let name = name.clone(); |
429 | 63 | state.tokens.advance(); |
430 | 63 | Ok(Pattern::Identifier(name)) |
431 | | } |
432 | | Some((Token::LeftParen, _)) => { |
433 | | // Parse tuple destructuring: (x, y) = (1, 2) |
434 | 0 | parse_tuple_pattern(state) |
435 | | } |
436 | | Some((Token::LeftBracket, _)) => { |
437 | | // Parse list destructuring: [a, b] = [1, 2] |
438 | 0 | parse_list_pattern(state) |
439 | | } |
440 | 1 | _ => bail!("Expected identifier or pattern after 'let{}'", |
441 | 1 | if is_mutable { " mut"0 } else { "" }) |
442 | | } |
443 | 64 | } |
444 | | |
445 | | /// Parse optional type annotation for let statement |
446 | | /// Extracted from `parse_let_statement` to reduce complexity |
447 | 63 | fn parse_let_type_annotation(state: &mut ParserState) -> Result<Option<Type>> { |
448 | 63 | if matches!(state.tokens.peek(), Some((Token::Colon, _))) { |
449 | 0 | state.tokens.advance(); // consume ':' |
450 | 0 | Ok(Some(super::utils::parse_type(state)?)) |
451 | | } else { |
452 | 63 | Ok(None) |
453 | | } |
454 | 63 | } |
455 | | |
456 | | /// Parse optional 'in' clause for let expressions |
457 | | /// Extracted from `parse_let_statement` to reduce complexity |
458 | 61 | fn parse_let_in_clause(state: &mut ParserState, value_span: Span) -> Result<Box<Expr>> { |
459 | 61 | if matches!42 (state.tokens.peek(), Some((Token::In, _))) { |
460 | 19 | state.tokens.advance(); // consume 'in' |
461 | 19 | Ok(Box::new(super::parse_expr_recursive(state)?0 )) |
462 | | } else { |
463 | | // For let statements (no 'in'), body is unit |
464 | 42 | Ok(Box::new(Expr::new(ExprKind::Literal(Literal::Unit), value_span))) |
465 | | } |
466 | 61 | } |
467 | | |
468 | | /// Create the appropriate let expression based on pattern type |
469 | | /// Extracted from `parse_let_statement` to reduce complexity |
470 | 61 | fn create_let_expression( |
471 | 61 | pattern: Pattern, |
472 | 61 | type_annotation: Option<Type>, |
473 | 61 | value: Box<Expr>, |
474 | 61 | body: Box<Expr>, |
475 | 61 | is_mutable: bool, |
476 | 61 | start_span: Span, |
477 | 61 | ) -> Result<Expr> { |
478 | 61 | let end_span = body.span; |
479 | | |
480 | 61 | match &pattern { |
481 | 61 | Pattern::Identifier(name) => { |
482 | 61 | Ok(Expr::new( |
483 | 61 | ExprKind::Let { |
484 | 61 | name: name.clone(), |
485 | 61 | type_annotation, |
486 | 61 | value, |
487 | 61 | body, |
488 | 61 | is_mutable, |
489 | 61 | }, |
490 | 61 | start_span.merge(end_span), |
491 | 61 | )) |
492 | | } |
493 | | Pattern::Tuple(_) | Pattern::List(_) => { |
494 | | // For destructuring patterns, use LetPattern variant |
495 | 0 | Ok(Expr::new( |
496 | 0 | ExprKind::LetPattern { |
497 | 0 | pattern, |
498 | 0 | type_annotation, |
499 | 0 | value, |
500 | 0 | body, |
501 | 0 | is_mutable, |
502 | 0 | }, |
503 | 0 | start_span.merge(end_span), |
504 | 0 | )) |
505 | | } |
506 | | Pattern::Wildcard | Pattern::Literal(_) | Pattern::QualifiedName(_) | Pattern::Struct { .. } |
507 | | | Pattern::Range { .. } | Pattern::Or(_) | Pattern::Rest | Pattern::RestNamed(_) |
508 | | | Pattern::Ok(_) | Pattern::Err(_) | Pattern::Some(_) | Pattern::None => { |
509 | | // For other pattern types, use LetPattern variant |
510 | 0 | Ok(Expr::new( |
511 | 0 | ExprKind::LetPattern { |
512 | 0 | pattern, |
513 | 0 | type_annotation, |
514 | 0 | value, |
515 | 0 | body, |
516 | 0 | is_mutable, |
517 | 0 | }, |
518 | 0 | start_span.merge(end_span), |
519 | 0 | )) |
520 | | } |
521 | | } |
522 | 61 | } |
523 | | |
524 | | /// Parse var statement: var name [: type] = value |
525 | | /// var is implicitly mutable (like let mut) |
526 | 0 | fn parse_var_statement(state: &mut ParserState) -> Result<Expr> { |
527 | 0 | let start_span = state.tokens.expect(&Token::Var)?; |
528 | | |
529 | | // var is always mutable |
530 | 0 | let is_mutable = true; |
531 | | |
532 | | // Parse variable name or destructuring pattern |
533 | 0 | let pattern = match state.tokens.peek() { |
534 | 0 | Some((Token::Identifier(name), _)) => { |
535 | 0 | let name = name.clone(); |
536 | 0 | state.tokens.advance(); |
537 | 0 | Pattern::Identifier(name) |
538 | | } |
539 | | Some((Token::LeftParen, _)) => { |
540 | | // Parse tuple destructuring: (x, y) = (1, 2) |
541 | 0 | parse_tuple_pattern(state)? |
542 | | } |
543 | | Some((Token::LeftBracket, _)) => { |
544 | | // Parse list destructuring: [a, b] = [1, 2] |
545 | 0 | parse_list_pattern(state)? |
546 | | } |
547 | 0 | _ => bail!("Expected identifier or pattern after 'var'") |
548 | | }; |
549 | | |
550 | | // Parse optional type annotation |
551 | 0 | let type_annotation = if matches!(state.tokens.peek(), Some((Token::Colon, _))) { |
552 | 0 | state.tokens.advance(); |
553 | 0 | Some(super::utils::parse_type(state)?) |
554 | | } else { |
555 | 0 | None |
556 | | }; |
557 | | |
558 | | // Parse '=' token |
559 | 0 | state.tokens.expect(&Token::Equal)?; |
560 | | |
561 | | // Parse value expression |
562 | 0 | let value = Box::new(super::parse_expr_recursive(state)?); |
563 | | |
564 | | // var doesn't support 'in' syntax, just creates a mutable binding |
565 | 0 | let body = Box::new(Expr::new(ExprKind::Literal(Literal::Unit), value.span)); |
566 | | |
567 | 0 | let end_span = value.span; |
568 | | |
569 | | // Handle different pattern types |
570 | 0 | match &pattern { |
571 | 0 | Pattern::Identifier(name) => { |
572 | | // Simple identifier binding |
573 | 0 | Ok(Expr::new( |
574 | 0 | ExprKind::Let { |
575 | 0 | name: name.clone(), |
576 | 0 | type_annotation, |
577 | 0 | value, |
578 | 0 | body, |
579 | 0 | is_mutable, |
580 | 0 | }, |
581 | 0 | start_span.merge(end_span), |
582 | 0 | )) |
583 | | } |
584 | | _ => { |
585 | | // For all other patterns (tuple, list, etc), use LetPattern variant |
586 | 0 | Ok(Expr::new( |
587 | 0 | ExprKind::LetPattern { |
588 | 0 | pattern, |
589 | 0 | type_annotation, |
590 | 0 | value, |
591 | 0 | body, |
592 | 0 | is_mutable, |
593 | 0 | }, |
594 | 0 | start_span.merge(end_span), |
595 | 0 | )) |
596 | | } |
597 | | } |
598 | 0 | } |
599 | | |
600 | 0 | fn parse_tuple_pattern(state: &mut ParserState) -> Result<Pattern> { |
601 | 0 | state.tokens.expect(&Token::LeftParen)?; |
602 | 0 | let mut patterns = Vec::new(); |
603 | | |
604 | 0 | while !matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
605 | 0 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
606 | 0 | patterns.push(Pattern::Identifier(name.clone())); |
607 | 0 | state.tokens.advance(); |
608 | 0 | } else { |
609 | 0 | bail!("Expected identifier in tuple pattern"); |
610 | | } |
611 | | |
612 | | // Only consume comma if not at end |
613 | 0 | if matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
614 | 0 | state.tokens.advance(); |
615 | | // If we hit RightParen after comma, break (trailing comma case) |
616 | 0 | if matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
617 | 0 | break; |
618 | 0 | } |
619 | 0 | } else if !matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
620 | 0 | bail!("Expected ',' or ')' in tuple pattern"); |
621 | 0 | } |
622 | | } |
623 | | |
624 | 0 | state.tokens.expect(&Token::RightParen)?; |
625 | 0 | Ok(Pattern::Tuple(patterns)) |
626 | 0 | } |
627 | | |
628 | 0 | fn parse_list_pattern(state: &mut ParserState) -> Result<Pattern> { |
629 | 0 | state.tokens.expect(&Token::LeftBracket)?; |
630 | 0 | let mut patterns = Vec::new(); |
631 | | |
632 | 0 | while !matches!(state.tokens.peek(), Some((Token::RightBracket, _))) { |
633 | 0 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
634 | 0 | patterns.push(Pattern::Identifier(name.clone())); |
635 | 0 | state.tokens.advance(); |
636 | 0 | } else { |
637 | 0 | bail!("Expected identifier in list pattern"); |
638 | | } |
639 | | |
640 | 0 | if matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
641 | 0 | state.tokens.advance(); |
642 | 0 | } |
643 | | } |
644 | | |
645 | 0 | state.tokens.expect(&Token::RightBracket)?; |
646 | 0 | Ok(Pattern::List(patterns)) |
647 | 0 | } |
648 | | |
649 | | /// Parse if expression: if condition { `then_branch` } [else { `else_branch` }] |
650 | 19 | fn parse_if_expression(state: &mut ParserState) -> Result<Expr> { |
651 | 19 | let start_span = state.tokens.expect(&Token::If)?0 ; |
652 | | |
653 | | // Parse condition with better error context |
654 | 19 | let condition17 = Box::new17 (super::parse_expr_recursive(state) |
655 | 19 | .map_err(|e| anyhow::anyhow!("Expected condition after 'if': {}"2 , e))?2 ); |
656 | | |
657 | | // Parse then branch (expect block) with better error context |
658 | 17 | let then_branch16 = Box::new16 (super::parse_expr_recursive(state) |
659 | 17 | .map_err(|e| anyhow::anyhow!("Expected body after if condition, typically {{ ... }}: {}"1 , e))?1 ); |
660 | | |
661 | | // Parse optional else branch |
662 | 16 | let else_branch = if matches!1 (state.tokens.peek(), Some((Token::Else, _))) { |
663 | 15 | state.tokens.advance(); // consume 'else' |
664 | 15 | Some(Box::new(super::parse_expr_recursive(state) |
665 | 15 | .map_err(|e| anyhow::anyhow!("Expected body after 'else', typically {{ ... }}: {}"0 , e))?0 )) |
666 | | } else { |
667 | 1 | None |
668 | | }; |
669 | | |
670 | 16 | Ok(Expr::new( |
671 | 16 | ExprKind::If { |
672 | 16 | condition, |
673 | 16 | then_branch, |
674 | 16 | else_branch, |
675 | 16 | }, |
676 | 16 | start_span, |
677 | 16 | )) |
678 | 19 | } |
679 | | |
680 | | /// Parse match expression: match expr { pattern => result, ... } |
681 | | /// Complexity target: <10 (using helper functions for TDG compliance) |
682 | 7 | fn parse_match_expression(state: &mut ParserState) -> Result<Expr> { |
683 | 7 | let start_span = state.tokens.expect(&Token::Match)?0 ; |
684 | | |
685 | | // Parse the expression to match on |
686 | 7 | let expr4 = Box::new4 (super::parse_expr_recursive(state) |
687 | 7 | .map_err(|e| anyhow::anyhow!("Expected expression after 'match': {}"3 , e))?3 ); |
688 | | |
689 | | // Expect opening brace for match arms |
690 | 4 | state.tokens.expect(&Token::LeftBrace) |
691 | 4 | .map_err(|_| anyhow::anyhow!("Expected '{{' after match expression"0 ))?0 ; |
692 | | |
693 | | // Parse match arms |
694 | 4 | let arms = parse_match_arms(state)?0 ; |
695 | | |
696 | | // Expect closing brace |
697 | 4 | state.tokens.expect(&Token::RightBrace) |
698 | 4 | .map_err(|_| anyhow::anyhow!("Expected '}}' after match arms"0 ))?0 ; |
699 | | |
700 | 4 | Ok(Expr::new( |
701 | 4 | ExprKind::Match { expr, arms }, |
702 | 4 | start_span, |
703 | 4 | )) |
704 | 7 | } |
705 | | |
706 | | /// Parse match arms with low complexity (helper function for TDG compliance) |
707 | 4 | fn parse_match_arms(state: &mut ParserState) -> Result<Vec<MatchArm>> { |
708 | 4 | let mut arms = Vec::new(); |
709 | | |
710 | 9 | while !matches!(state.tokens.peek(), Some((Token::RightBrace, _)) | None) { |
711 | | // Parse single arm |
712 | 9 | let arm = parse_single_match_arm(state)?0 ; |
713 | 9 | arms.push(arm); |
714 | | |
715 | | // Optional comma |
716 | 9 | if matches!4 (state.tokens.peek(), Some((Token::Comma, _))) { |
717 | 5 | state.tokens.advance(); |
718 | 5 | }4 |
719 | | |
720 | | // Check if we're done |
721 | 9 | if matches!5 (state.tokens.peek(), Some((Token::RightBrace, _))) { |
722 | 4 | break; |
723 | 5 | } |
724 | | } |
725 | | |
726 | 4 | if arms.is_empty() { |
727 | 0 | bail!("Match expression must have at least one arm"); |
728 | 4 | } |
729 | | |
730 | 4 | Ok(arms) |
731 | 4 | } |
732 | | |
733 | | /// Parse a single match arm: pattern [if guard] => expr |
734 | | /// Complexity: <5 (simple sequential parsing) |
735 | 9 | fn parse_single_match_arm(state: &mut ParserState) -> Result<MatchArm> { |
736 | 9 | let start_span = state.tokens.peek().map(|(_, s)| *s) |
737 | 9 | .unwrap_or_default(); |
738 | | |
739 | | // Parse pattern |
740 | 9 | let pattern = parse_match_pattern(state)?0 ; |
741 | | |
742 | | // Parse optional guard (if condition) |
743 | 9 | let guard = if matches!(state.tokens.peek(), Some((Token::If, _))) { |
744 | 0 | state.tokens.advance(); // consume 'if' |
745 | 0 | Some(Box::new(super::parse_expr_recursive(state)?)) |
746 | | } else { |
747 | 9 | None |
748 | | }; |
749 | | |
750 | | // Expect => token |
751 | 9 | state.tokens.expect(&Token::FatArrow) |
752 | 9 | .map_err(|_| anyhow::anyhow!("Expected '=>' in match arm"0 ))?0 ; |
753 | | |
754 | | // Parse result expression |
755 | 9 | let body = Box::new(super::parse_expr_recursive(state)?0 ); |
756 | | |
757 | 9 | let end_span = body.span; |
758 | | |
759 | 9 | Ok(MatchArm { |
760 | 9 | pattern, |
761 | 9 | guard, |
762 | 9 | body, |
763 | 9 | span: start_span.merge(end_span), |
764 | 9 | }) |
765 | 9 | } |
766 | | |
767 | | /// Parse match pattern with low complexity |
768 | | /// Complexity: <5 (simple pattern matching) |
769 | 9 | fn parse_match_pattern(state: &mut ParserState) -> Result<Pattern> { |
770 | 9 | if state.tokens.peek().is_none() { |
771 | 0 | bail!("Expected pattern in match arm"); |
772 | 9 | } |
773 | | |
774 | | // Delegate to focused helper functions |
775 | 9 | let pattern = parse_single_pattern(state)?0 ; |
776 | | |
777 | | // Handle multiple patterns with | (or) |
778 | 9 | if matches!(state.tokens.peek(), Some((Token::Pipe, _))) { |
779 | 0 | parse_or_pattern(state, pattern) |
780 | | } else { |
781 | 9 | Ok(pattern) |
782 | | } |
783 | 9 | } |
784 | | |
785 | | /// Parse a single pattern (delegates to specific pattern parsers) |
786 | | /// Complexity: <8 |
787 | 9 | fn parse_single_pattern(state: &mut ParserState) -> Result<Pattern> { |
788 | 9 | let Some((token, _span)) = state.tokens.peek() else { |
789 | 0 | bail!("Expected pattern"); |
790 | | }; |
791 | | |
792 | 9 | match token { |
793 | 4 | Token::Underscore => parse_wildcard_pattern(state), |
794 | | Token::Integer(_) | Token::Float(_) | Token::String(_) | |
795 | 5 | Token::Char(_) | Token::Bool(_) => parse_literal_pattern(state), |
796 | 0 | Token::Some | Token::None => parse_option_pattern(state), |
797 | 0 | Token::Identifier(_) => parse_identifier_or_constructor_pattern(state), |
798 | 0 | Token::LeftParen => parse_match_tuple_pattern(state), |
799 | 0 | Token::LeftBracket => parse_match_list_pattern(state), |
800 | 0 | _ => bail!("Unexpected token in pattern: {:?}", token) |
801 | | } |
802 | 9 | } |
803 | | |
804 | | /// Parse wildcard pattern: _ |
805 | | /// Complexity: 1 |
806 | 4 | fn parse_wildcard_pattern(state: &mut ParserState) -> Result<Pattern> { |
807 | 4 | state.tokens.advance(); |
808 | 4 | Ok(Pattern::Wildcard) |
809 | 4 | } |
810 | | |
811 | | /// Parse literal patterns: integers, floats, strings, chars, booleans |
812 | | /// Complexity: <5 |
813 | 5 | fn parse_literal_pattern(state: &mut ParserState) -> Result<Pattern> { |
814 | 5 | let Some((token, _span)) = state.tokens.peek() else { |
815 | 0 | bail!("Expected literal pattern"); |
816 | | }; |
817 | | |
818 | 5 | let pattern = match token { |
819 | 5 | Token::Integer(val) => { |
820 | 5 | let val = *val; |
821 | 5 | state.tokens.advance(); |
822 | 5 | Pattern::Literal(Literal::Integer(val)) |
823 | | } |
824 | 0 | Token::Float(val) => { |
825 | 0 | let val = *val; |
826 | 0 | state.tokens.advance(); |
827 | 0 | Pattern::Literal(Literal::Float(val)) |
828 | | } |
829 | 0 | Token::String(s) => { |
830 | 0 | let s = s.clone(); |
831 | 0 | state.tokens.advance(); |
832 | 0 | Pattern::Literal(Literal::String(s)) |
833 | | } |
834 | 0 | Token::Char(c) => { |
835 | 0 | let c = *c; |
836 | 0 | state.tokens.advance(); |
837 | 0 | Pattern::Literal(Literal::Char(c)) |
838 | | } |
839 | 0 | Token::Bool(b) => { |
840 | 0 | let b = *b; |
841 | 0 | state.tokens.advance(); |
842 | 0 | Pattern::Literal(Literal::Bool(b)) |
843 | | } |
844 | 0 | _ => bail!("Expected literal pattern, got: {:?}", token) |
845 | | }; |
846 | | |
847 | 5 | Ok(pattern) |
848 | 5 | } |
849 | | |
850 | | /// Parse Option patterns: Some, None |
851 | | /// Complexity: <5 |
852 | 0 | fn parse_option_pattern(state: &mut ParserState) -> Result<Pattern> { |
853 | 0 | let Some((token, _span)) = state.tokens.peek() else { |
854 | 0 | bail!("Expected Option pattern"); |
855 | | }; |
856 | | |
857 | 0 | match token { |
858 | | Token::Some => { |
859 | 0 | state.tokens.advance(); |
860 | 0 | if matches!(state.tokens.peek(), Some((Token::LeftParen, _))) { |
861 | 0 | parse_constructor_pattern(state, "Some".to_string()) |
862 | | } else { |
863 | 0 | Ok(Pattern::Identifier("Some".to_string())) |
864 | | } |
865 | | } |
866 | | Token::None => { |
867 | 0 | state.tokens.advance(); |
868 | 0 | if matches!(state.tokens.peek(), Some((Token::LeftParen, _))) { |
869 | 0 | parse_constructor_pattern(state, "None".to_string()) |
870 | | } else { |
871 | 0 | Ok(Pattern::Identifier("None".to_string())) |
872 | | } |
873 | | } |
874 | 0 | _ => bail!("Expected Some or None pattern") |
875 | | } |
876 | 0 | } |
877 | | |
878 | | /// Parse identifier or constructor patterns |
879 | | /// Complexity: <5 |
880 | 0 | fn parse_identifier_or_constructor_pattern(state: &mut ParserState) -> Result<Pattern> { |
881 | 0 | let Some((Token::Identifier(name), _span)) = state.tokens.peek() else { |
882 | 0 | bail!("Expected identifier pattern"); |
883 | | }; |
884 | | |
885 | 0 | let name = name.clone(); |
886 | 0 | state.tokens.advance(); |
887 | | |
888 | | // Check for enum-like patterns: Ok(x), Err(e), etc. |
889 | 0 | if matches!(state.tokens.peek(), Some((Token::LeftParen, _))) { |
890 | 0 | parse_constructor_pattern(state, name) |
891 | | } else { |
892 | 0 | Ok(Pattern::Identifier(name)) |
893 | | } |
894 | 0 | } |
895 | | |
896 | | /// Parse match tuple pattern: (a, b, c) |
897 | | /// Complexity: <7 |
898 | 0 | fn parse_match_tuple_pattern(state: &mut ParserState) -> Result<Pattern> { |
899 | 0 | state.tokens.expect(&Token::LeftParen)?; |
900 | | |
901 | | // Check for empty tuple () |
902 | 0 | if matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
903 | 0 | state.tokens.advance(); |
904 | 0 | return Ok(Pattern::Tuple(vec![])); |
905 | 0 | } |
906 | | |
907 | | // Parse pattern elements |
908 | 0 | let mut patterns = vec![parse_match_pattern(state)?]; |
909 | | |
910 | 0 | while matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
911 | 0 | state.tokens.advance(); // consume comma |
912 | 0 | if matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
913 | 0 | break; // trailing comma |
914 | 0 | } |
915 | 0 | patterns.push(parse_match_pattern(state)?); |
916 | | } |
917 | | |
918 | 0 | state.tokens.expect(&Token::RightParen)?; |
919 | 0 | Ok(Pattern::Tuple(patterns)) |
920 | 0 | } |
921 | | |
922 | | /// Parse list pattern in match: [], [a], [a, b], [head, ...tail] |
923 | | /// Complexity: <8 |
924 | 0 | fn parse_match_list_pattern(state: &mut ParserState) -> Result<Pattern> { |
925 | 0 | state.tokens.expect(&Token::LeftBracket)?; |
926 | | |
927 | | // Check for empty list [] |
928 | 0 | if matches!(state.tokens.peek(), Some((Token::RightBracket, _))) { |
929 | 0 | state.tokens.advance(); |
930 | 0 | return Ok(Pattern::List(vec![])); |
931 | 0 | } |
932 | | |
933 | | // Parse pattern elements |
934 | 0 | let mut patterns = vec![]; |
935 | | |
936 | | loop { |
937 | | // Check for rest pattern ...tail |
938 | 0 | if matches!(state.tokens.peek(), Some((Token::DotDotDot, _))) { |
939 | 0 | state.tokens.advance(); |
940 | 0 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
941 | 0 | let name = name.clone(); |
942 | 0 | state.tokens.advance(); |
943 | 0 | patterns.push(Pattern::RestNamed(name)); |
944 | 0 | break; |
945 | 0 | } |
946 | 0 | bail!("Expected identifier after ... in list pattern"); |
947 | 0 | } |
948 | | |
949 | 0 | patterns.push(parse_match_pattern(state)?); |
950 | | |
951 | 0 | if matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
952 | 0 | state.tokens.advance(); |
953 | 0 | if matches!(state.tokens.peek(), Some((Token::RightBracket, _))) { |
954 | 0 | break; // trailing comma |
955 | 0 | } |
956 | | } else { |
957 | 0 | break; |
958 | | } |
959 | | } |
960 | | |
961 | 0 | state.tokens.expect(&Token::RightBracket)?; |
962 | 0 | Ok(Pattern::List(patterns)) |
963 | 0 | } |
964 | | |
965 | | /// Parse constructor pattern: Some(x), Ok(value), etc. |
966 | | /// Complexity: <5 |
967 | 0 | fn parse_constructor_pattern(state: &mut ParserState, name: String) -> Result<Pattern> { |
968 | 0 | state.tokens.expect(&Token::LeftParen)?; |
969 | | |
970 | | // Check for empty tuple (e.g., None()) |
971 | 0 | if matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
972 | 0 | state.tokens.advance(); |
973 | 0 | return Ok(Pattern::Identifier(name)); |
974 | 0 | } |
975 | | |
976 | | // Parse inner patterns as tuple |
977 | 0 | let mut patterns = vec![parse_match_pattern(state)?]; |
978 | | |
979 | | // Parse additional patterns if comma-separated |
980 | 0 | while matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
981 | 0 | state.tokens.advance(); // consume comma |
982 | 0 | if matches!(state.tokens.peek(), Some((Token::RightParen, _))) { |
983 | 0 | break; // trailing comma |
984 | 0 | } |
985 | 0 | patterns.push(parse_match_pattern(state)?); |
986 | | } |
987 | | |
988 | 0 | state.tokens.expect(&Token::RightParen)?; |
989 | | |
990 | | // Handle constructor patterns (Some(x), Ok(val), etc.) |
991 | | // These should ideally use a proper constructor pattern type |
992 | | // For now, we'll use the appropriate pattern based on the constructor name |
993 | | |
994 | 0 | if name == "Some" && patterns.len() == 1 { |
995 | | // Some(pattern) - use Ok variant to represent Option::Some |
996 | 0 | Ok(Pattern::Ok(Box::new(patterns.into_iter().next().unwrap()))) |
997 | 0 | } else if name == "None" && patterns.is_empty() { |
998 | | // None - just an identifier |
999 | 0 | Ok(Pattern::Identifier("None".to_string())) |
1000 | 0 | } else if patterns.len() == 1 { |
1001 | | // Single argument constructor - for simplicity, use the inner pattern |
1002 | 0 | Ok(patterns.into_iter().next().unwrap()) |
1003 | | } else { |
1004 | | // Multiple arguments - use tuple pattern |
1005 | 0 | Ok(Pattern::Tuple(patterns)) |
1006 | | } |
1007 | 0 | } |
1008 | | |
1009 | | /// Parse or-pattern: pattern | pattern | ... |
1010 | | /// Complexity: <5 |
1011 | 0 | fn parse_or_pattern(state: &mut ParserState, first: Pattern) -> Result<Pattern> { |
1012 | 0 | let mut patterns = vec![first]; |
1013 | | |
1014 | 0 | while matches!(state.tokens.peek(), Some((Token::Pipe, _))) { |
1015 | 0 | state.tokens.advance(); // consume '|' |
1016 | | |
1017 | | // Need to parse the next pattern without recursing into or-patterns again |
1018 | 0 | let next = parse_single_pattern(state)?; |
1019 | 0 | patterns.push(next); |
1020 | | } |
1021 | | |
1022 | | // Use the Or pattern variant for multiple alternatives |
1023 | 0 | if patterns.len() == 1 { |
1024 | 0 | Ok(patterns.into_iter().next().unwrap()) |
1025 | | } else { |
1026 | 0 | Ok(Pattern::Or(patterns)) |
1027 | | } |
1028 | 0 | } |
1029 | | |
1030 | | /// Parse a single pattern without checking for | (helper to avoid recursion) |
1031 | | /// Complexity: <5 |
1032 | | |
1033 | | /// Parse while loop: while condition { body } |
1034 | | /// Complexity: <5 (simple structure) |
1035 | 2 | fn parse_while_loop(state: &mut ParserState) -> Result<Expr> { |
1036 | 2 | let start_span = state.tokens.expect(&Token::While)?0 ; |
1037 | | |
1038 | | // Parse condition |
1039 | 2 | let condition = Box::new(super::parse_expr_recursive(state) |
1040 | 2 | .map_err(|e| anyhow::anyhow!("Expected condition after 'while': {}"0 , e))?0 ); |
1041 | | |
1042 | | // Parse body (expect block) |
1043 | 2 | let body = Box::new(super::parse_expr_recursive(state) |
1044 | 2 | .map_err(|e| anyhow::anyhow!("Expected body after while condition: {}"0 , e))?0 ); |
1045 | | |
1046 | 2 | Ok(Expr::new( |
1047 | 2 | ExprKind::While { condition, body }, |
1048 | 2 | start_span, |
1049 | 2 | )) |
1050 | 2 | } |
1051 | | |
1052 | | /// Parse for loop: for pattern in iterator { body } |
1053 | | /// Complexity: <5 (simple structure) |
1054 | 2 | fn parse_for_loop(state: &mut ParserState) -> Result<Expr> { |
1055 | 2 | let start_span = state.tokens.expect(&Token::For)?0 ; |
1056 | | |
1057 | | // Parse pattern (e.g., "i" in "for i in ...") |
1058 | 2 | let pattern = parse_for_pattern(state)?0 ; |
1059 | | |
1060 | | // Expect 'in' keyword |
1061 | 2 | state.tokens.expect(&Token::In) |
1062 | 2 | .map_err(|_| anyhow::anyhow!("Expected 'in' after for pattern"0 ))?0 ; |
1063 | | |
1064 | | // Parse iterator expression |
1065 | 2 | let iterator = Box::new(super::parse_expr_recursive(state) |
1066 | 2 | .map_err(|e| anyhow::anyhow!("Expected iterator after 'in': {}"0 , e))?0 ); |
1067 | | |
1068 | | // Parse body (expect block) |
1069 | 2 | let body = Box::new(super::parse_expr_recursive(state) |
1070 | 2 | .map_err(|e| anyhow::anyhow!("Expected body after for iterator: {}"0 , e))?0 ); |
1071 | | |
1072 | | // Get the var name from the pattern for backward compatibility |
1073 | 2 | let var = pattern.primary_name(); |
1074 | | |
1075 | 2 | Ok(Expr::new( |
1076 | 2 | ExprKind::For { |
1077 | 2 | var, |
1078 | 2 | pattern: Some(pattern), |
1079 | 2 | iter: iterator, |
1080 | 2 | body |
1081 | 2 | }, |
1082 | 2 | start_span, |
1083 | 2 | )) |
1084 | 2 | } |
1085 | | |
1086 | | /// Parse for loop pattern (simple version) |
1087 | | /// Complexity: <3 |
1088 | 2 | fn parse_for_pattern(state: &mut ParserState) -> Result<Pattern> { |
1089 | 2 | let Some((token, _)) = state.tokens.peek() else { |
1090 | 0 | bail!("Expected pattern in for loop"); |
1091 | | }; |
1092 | | |
1093 | 2 | match token { |
1094 | 2 | Token::Identifier(name) => { |
1095 | 2 | let name = name.clone(); |
1096 | 2 | state.tokens.advance(); |
1097 | 2 | Ok(Pattern::Identifier(name)) |
1098 | | } |
1099 | | Token::Underscore => { |
1100 | 0 | state.tokens.advance(); |
1101 | 0 | Ok(Pattern::Wildcard) |
1102 | | } |
1103 | | Token::LeftParen => { |
1104 | | // Parse tuple pattern: (x, y) |
1105 | 0 | parse_tuple_pattern(state) |
1106 | | } |
1107 | | Token::LeftBracket => { |
1108 | | // Parse list pattern: [x, y] |
1109 | 0 | parse_list_pattern(state) |
1110 | | } |
1111 | 0 | _ => bail!("Expected identifier, underscore, or destructuring pattern in for loop") |
1112 | | } |
1113 | 2 | } |
1114 | | |
1115 | 53 | fn parse_list_literal(state: &mut ParserState) -> Result<Expr> { |
1116 | | // Parse [ expr, expr, ... ] or [expr for var in iter if cond] |
1117 | 53 | let start_span = state.tokens.expect(&Token::LeftBracket)?0 ; |
1118 | | |
1119 | | // Handle empty list |
1120 | 53 | if matches!50 (state.tokens.peek(), Some((Token::RightBracket, _))) { |
1121 | 3 | state.tokens.advance(); |
1122 | 3 | return Ok(Expr::new(ExprKind::List(vec![]), start_span)); |
1123 | 50 | } |
1124 | | |
1125 | | // Parse first element/expression |
1126 | 50 | let first_expr = super::parse_expr_recursive(state)?0 ; |
1127 | | |
1128 | | // Check if this is a list comprehension |
1129 | 50 | if matches!47 (state.tokens.peek(), Some((Token::For, _))) { |
1130 | 3 | return parse_list_comprehension_body(state, first_expr, start_span); |
1131 | 47 | } |
1132 | | |
1133 | | // Regular list literal |
1134 | 47 | let mut elements = vec![first_expr]; |
1135 | | |
1136 | | // Parse remaining elements |
1137 | 113 | while matches!45 (state.tokens.peek(), Some((Token::Comma, _))) { |
1138 | 68 | state.tokens.advance(); |
1139 | | |
1140 | | // Check for trailing comma |
1141 | 68 | if matches!(state.tokens.peek(), Some((Token::RightBracket, _))) { |
1142 | 0 | break; |
1143 | 68 | } |
1144 | | |
1145 | 68 | elements.push66 (super::parse_expr_recursive(state)?2 ); |
1146 | | } |
1147 | | |
1148 | 45 | state.tokens.expect(&Token::RightBracket) |
1149 | 45 | .map_err(|_| anyhow::anyhow!("Expected ']' to close list literal"0 ))?0 ; |
1150 | | |
1151 | 45 | Ok(Expr::new(ExprKind::List(elements), start_span)) |
1152 | 53 | } |
1153 | | |
1154 | 3 | fn parse_list_comprehension_body( |
1155 | 3 | state: &mut ParserState, |
1156 | 3 | expr: Expr, |
1157 | 3 | start_span: Span, |
1158 | 3 | ) -> Result<Expr> { |
1159 | | // Parse: for var in iter [if cond] |
1160 | 3 | state.tokens.expect(&Token::For)?0 ; |
1161 | | |
1162 | | // Parse variable |
1163 | 3 | let var = if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1164 | 3 | let name = n.clone(); |
1165 | 3 | state.tokens.advance(); |
1166 | 3 | name |
1167 | | } else { |
1168 | 0 | bail!("Expected variable name in list comprehension"); |
1169 | | }; |
1170 | | |
1171 | 3 | state.tokens.expect(&Token::In)?0 ; |
1172 | | |
1173 | | // Parse iterator |
1174 | 3 | let iter = super::parse_expr_recursive(state)?0 ; |
1175 | | |
1176 | | // Parse optional condition |
1177 | 3 | let condition = if matches!1 (state.tokens.peek(), Some((Token::If, _))) { |
1178 | 2 | state.tokens.advance(); |
1179 | 2 | Some(Box::new(super::parse_expr_recursive(state)?0 )) |
1180 | | } else { |
1181 | 1 | None |
1182 | | }; |
1183 | | |
1184 | 3 | state.tokens.expect(&Token::RightBracket)?0 ; |
1185 | | |
1186 | 3 | Ok(Expr::new( |
1187 | 3 | ExprKind::ListComprehension { |
1188 | 3 | element: Box::new(expr), |
1189 | 3 | variable: var, |
1190 | 3 | iterable: Box::new(iter), |
1191 | 3 | condition, |
1192 | 3 | }, |
1193 | 3 | start_span, |
1194 | 3 | )) |
1195 | 3 | } |
1196 | | |
1197 | 1 | fn parse_lambda_no_params(state: &mut ParserState) -> Result<Expr> { |
1198 | | // Parse || body |
1199 | 1 | let start_span = state.tokens.expect(&Token::OrOr)?0 ; |
1200 | | |
1201 | | // Parse the body |
1202 | 1 | let body = Box::new(super::parse_expr_recursive(state)?0 ); |
1203 | | |
1204 | 1 | Ok(Expr::new(ExprKind::Lambda { |
1205 | 1 | params: vec![], |
1206 | 1 | body |
1207 | 1 | }, start_span)) |
1208 | 1 | } |
1209 | | |
1210 | 2 | fn parse_lambda_from_expr(state: &mut ParserState, expr: Expr, start_span: Span) -> Result<Expr> { |
1211 | | // Convert (x) => expr syntax |
1212 | 2 | state.tokens.advance(); // consume => |
1213 | | |
1214 | | // Convert the expression to a parameter |
1215 | 2 | let param = match &expr.kind { |
1216 | 2 | ExprKind::Identifier(name) => Param { |
1217 | 2 | pattern: Pattern::Identifier(name.clone()), |
1218 | 2 | ty: Type { |
1219 | 2 | kind: TypeKind::Named("_".to_string()), |
1220 | 2 | span: expr.span, |
1221 | 2 | }, |
1222 | 2 | default_value: None, |
1223 | 2 | is_mutable: false, |
1224 | 2 | span: expr.span, |
1225 | 2 | }, |
1226 | 0 | _ => bail!("Expected identifier in lambda parameter") |
1227 | | }; |
1228 | | |
1229 | | // Parse the body |
1230 | 2 | let body = Box::new(super::parse_expr_recursive(state)?0 ); |
1231 | | |
1232 | 2 | Ok(Expr::new(ExprKind::Lambda { |
1233 | 2 | params: vec![param], |
1234 | 2 | body, |
1235 | 2 | }, start_span)) |
1236 | 2 | } |
1237 | | |
1238 | 22 | fn parse_lambda_expression(state: &mut ParserState) -> Result<Expr> { |
1239 | | // Parse |param, param| body or |param| body |
1240 | 22 | let start_span = state.tokens.expect(&Token::Pipe)?0 ; |
1241 | | |
1242 | 22 | let mut params = Vec::new(); |
1243 | | |
1244 | | // Parse parameters |
1245 | 48 | while !matches!28 (state.tokens.peek(), Some((Token::Pipe, _))) { |
1246 | 28 | if let Some((Token::Identifier(name26 ), _)) = state.tokens.peek() { |
1247 | 26 | params.push(Pattern::Identifier(name.clone())); |
1248 | 26 | state.tokens.advance(); |
1249 | | |
1250 | | // Check for comma |
1251 | 26 | if matches!20 (state.tokens.peek(), Some((Token::Comma, _))) { |
1252 | 6 | state.tokens.advance(); |
1253 | 20 | } |
1254 | | } else { |
1255 | 2 | bail!("Expected parameter name in lambda"); |
1256 | | } |
1257 | | } |
1258 | | |
1259 | 20 | state.tokens.expect(&Token::Pipe) |
1260 | 20 | .map_err(|_| anyhow::anyhow!("Expected '|' after lambda parameters"0 ))?0 ; |
1261 | | |
1262 | | // Parse body |
1263 | 20 | let body = Box::new(super::parse_expr_recursive(state)?0 ); |
1264 | | |
1265 | | // Convert Pattern to Param for Lambda |
1266 | 20 | let params = params.into_iter().map(|p| Param { |
1267 | 26 | pattern: p, |
1268 | 26 | ty: Type { |
1269 | 26 | kind: TypeKind::Named("_".to_string()), |
1270 | 26 | span: start_span, |
1271 | 26 | }, |
1272 | 26 | span: start_span, |
1273 | | is_mutable: false, |
1274 | 26 | default_value: None, |
1275 | 26 | }).collect20 (); |
1276 | | |
1277 | 20 | Ok(Expr::new(ExprKind::Lambda { params, body }, start_span)) |
1278 | 22 | } |
1279 | | |
1280 | 6 | fn parse_struct_definition(state: &mut ParserState) -> Result<Expr> { |
1281 | | // Parse struct Name<T> { field: Type, ... } |
1282 | 6 | let start_span = state.tokens.expect(&Token::Struct)?0 ; |
1283 | | |
1284 | | // Get struct name |
1285 | 6 | let name5 = if let Some((Token::Identifier(n5 ), _)) = state.tokens.peek() { |
1286 | 5 | let name = n.clone(); |
1287 | 5 | state.tokens.advance(); |
1288 | 5 | name |
1289 | | } else { |
1290 | 1 | bail!("Expected struct name after 'struct'"); |
1291 | | }; |
1292 | | |
1293 | | // Parse optional generic parameters |
1294 | 5 | let type_params = parse_optional_generics(state)?0 ; |
1295 | | |
1296 | | // Parse { fields } |
1297 | 5 | state.tokens.expect(&Token::LeftBrace)?0 ; |
1298 | | |
1299 | 5 | let mut fields = Vec::new(); |
1300 | | |
1301 | | // Parse fields |
1302 | 12 | while !matches!7 (state.tokens.peek(), Some((Token::RightBrace, _))) { |
1303 | | // Parse field name |
1304 | 7 | let field_name = if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1305 | 7 | let name = n.clone(); |
1306 | 7 | state.tokens.advance(); |
1307 | 7 | name |
1308 | | } else { |
1309 | 0 | bail!("Expected field name in struct"); |
1310 | | }; |
1311 | | |
1312 | | // Parse : Type |
1313 | 7 | state.tokens.expect(&Token::Colon)?0 ; |
1314 | 7 | let field_type = super::utils::parse_type(state)?0 ; |
1315 | | |
1316 | 7 | fields.push((field_name, field_type)); |
1317 | | |
1318 | | // Check for comma |
1319 | 7 | if matches!4 (state.tokens.peek(), Some((Token::Comma, _))) { |
1320 | 3 | state.tokens.advance(); |
1321 | 4 | } |
1322 | | } |
1323 | | |
1324 | 5 | state.tokens.expect(&Token::RightBrace)?0 ; |
1325 | | |
1326 | | // Convert to proper Struct variant with StructField |
1327 | 5 | let struct_fields = fields.into_iter().map(|(name, ty)| StructField { |
1328 | 7 | name, |
1329 | 7 | ty, |
1330 | | is_pub: false, |
1331 | 7 | }).collect5 (); |
1332 | | |
1333 | 5 | Ok(Expr::new(ExprKind::Struct { |
1334 | 5 | name, |
1335 | 5 | type_params, |
1336 | 5 | fields: struct_fields, |
1337 | 5 | is_pub: false, |
1338 | 5 | }, start_span)) |
1339 | 6 | } |
1340 | | |
1341 | 1 | fn parse_trait_definition(state: &mut ParserState) -> Result<Expr> { |
1342 | | // Parse trait Name { fun method(self) -> Type ... } |
1343 | 1 | let start_span = state.tokens.expect(&Token::Trait)?0 ; |
1344 | | |
1345 | | // Get trait name |
1346 | 1 | let name = if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1347 | 1 | let name = n.clone(); |
1348 | 1 | state.tokens.advance(); |
1349 | 1 | name |
1350 | | } else { |
1351 | 0 | bail!("Expected trait name after 'trait'"); |
1352 | | }; |
1353 | | |
1354 | | // Parse { methods } |
1355 | 1 | state.tokens.expect(&Token::LeftBrace)?0 ; |
1356 | | |
1357 | 1 | let mut methods = Vec::new(); |
1358 | | |
1359 | | // Parse methods |
1360 | 2 | while !matches!1 (state.tokens.peek(), Some((Token::RightBrace, _))) { |
1361 | | // Expect 'fun' keyword |
1362 | 1 | state.tokens.expect(&Token::Fun)?0 ; |
1363 | | |
1364 | | // Parse method name |
1365 | 1 | let method_name = if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1366 | 1 | let name = n.clone(); |
1367 | 1 | state.tokens.advance(); |
1368 | 1 | name |
1369 | | } else { |
1370 | 0 | bail!("Expected method name in trait"); |
1371 | | }; |
1372 | | |
1373 | | // For now, skip the rest of the method signature |
1374 | | // This is a simplified implementation |
1375 | 1 | methods.push(method_name); |
1376 | | |
1377 | | // Skip to end of line or next method |
1378 | 7 | while !matches!6 (state.tokens.peek(), Some((Token::Fun | Token::RightBrace, _))) |
1379 | 6 | && state.tokens.peek().is_some() { |
1380 | 6 | state.tokens.advance(); |
1381 | 6 | } |
1382 | | } |
1383 | | |
1384 | 1 | state.tokens.expect(&Token::RightBrace)?0 ; |
1385 | | |
1386 | | // Convert to proper Trait variant with TraitMethod |
1387 | 1 | let trait_methods = methods.into_iter().map(|name| TraitMethod { |
1388 | 1 | name, |
1389 | 1 | params: vec![], |
1390 | 1 | return_type: None, |
1391 | 1 | body: None, |
1392 | | is_pub: true, |
1393 | 1 | }).collect(); |
1394 | | |
1395 | 1 | Ok(Expr::new(ExprKind::Trait { |
1396 | 1 | name, |
1397 | 1 | type_params: vec![], |
1398 | 1 | methods: trait_methods, |
1399 | 1 | is_pub: false, |
1400 | 1 | }, start_span)) |
1401 | 1 | } |
1402 | | |
1403 | 1 | fn parse_impl_block(state: &mut ParserState) -> Result<Expr> { |
1404 | | // Parse impl Trait for Type { ... } or impl Type { ... } |
1405 | 1 | let start_span = state.tokens.expect(&Token::Impl)?0 ; |
1406 | | |
1407 | | // Parse trait or type name |
1408 | 1 | let trait_name = if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1409 | 1 | let name = n.clone(); |
1410 | 1 | state.tokens.advance(); |
1411 | 1 | Some(name) |
1412 | | } else { |
1413 | 0 | None |
1414 | | }; |
1415 | | |
1416 | | // Check for "for" keyword |
1417 | 1 | let type_name = if matches!(state.tokens.peek(), Some((Token::For, _))) { |
1418 | 0 | state.tokens.advance(); |
1419 | 0 | if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1420 | 0 | let name = n.clone(); |
1421 | 0 | state.tokens.advance(); |
1422 | 0 | name |
1423 | | } else { |
1424 | 0 | bail!("Expected type name after 'for' in impl"); |
1425 | | } |
1426 | 1 | } else if let Some(t) = trait_name { |
1427 | | // impl Type { ... } case |
1428 | 1 | t |
1429 | | } else { |
1430 | 0 | bail!("Expected type or trait name in impl"); |
1431 | | }; |
1432 | | |
1433 | | // Parse { methods } |
1434 | 1 | state.tokens.expect(&Token::LeftBrace)?0 ; |
1435 | | |
1436 | | // For now, parse until closing brace |
1437 | 1 | let mut depth = 1; |
1438 | 20 | while depth > 0 && state.tokens.peek()19 .is_some19 () { |
1439 | 19 | match state.tokens.peek() { |
1440 | 2 | Some((Token::LeftBrace, _)) => depth += 1, |
1441 | 3 | Some((Token::RightBrace, _)) => depth -= 1, |
1442 | 14 | _ => {} |
1443 | | } |
1444 | 19 | if depth > 0 { |
1445 | 18 | state.tokens.advance(); |
1446 | 18 | }1 |
1447 | | } |
1448 | | |
1449 | 1 | state.tokens.expect(&Token::RightBrace)?0 ; |
1450 | | |
1451 | 1 | Ok(Expr::new(ExprKind::Impl { |
1452 | 1 | type_params: vec![], |
1453 | 1 | trait_name: None, // Simplified implementation for now |
1454 | 1 | for_type: type_name, |
1455 | 1 | methods: vec![], |
1456 | 1 | is_pub: false, |
1457 | 1 | }, start_span)) |
1458 | 1 | } |
1459 | | |
1460 | 1 | fn parse_import_statement(state: &mut ParserState) -> Result<Expr> { |
1461 | | // Parse import path::to::module |
1462 | 1 | let start_span = state.tokens.expect(&Token::Import)?0 ; |
1463 | | |
1464 | | // Parse module path |
1465 | 1 | let mut path_parts = Vec::new(); |
1466 | | |
1467 | | // Get first identifier |
1468 | 1 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
1469 | 1 | path_parts.push(name.clone()); |
1470 | 1 | state.tokens.advance(); |
1471 | 1 | } else { |
1472 | 0 | bail!("Expected module path after 'import'"); |
1473 | | } |
1474 | | |
1475 | | // Parse additional path segments |
1476 | 1 | while matches!(state.tokens.peek(), Some((Token::ColonColon, _))) { |
1477 | 0 | state.tokens.advance(); // consume :: |
1478 | 0 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
1479 | 0 | path_parts.push(name.clone()); |
1480 | 0 | state.tokens.advance(); |
1481 | 0 | } else { |
1482 | 0 | bail!("Expected identifier after '::'"); |
1483 | | } |
1484 | | } |
1485 | | |
1486 | 1 | let path = path_parts.join("::"); |
1487 | | |
1488 | 1 | Ok(Expr::new(ExprKind::Import { |
1489 | 1 | path, |
1490 | 1 | items: vec![], |
1491 | 1 | }, start_span)) |
1492 | 1 | } |
1493 | | |
1494 | 2 | fn parse_use_statement(state: &mut ParserState) -> Result<Expr> { |
1495 | | // Parse use path::to::Type or use path::to::{Type1, Type2} |
1496 | 2 | let start_span = state.tokens.expect(&Token::Use)?0 ; |
1497 | | |
1498 | | // Parse module path |
1499 | 2 | let mut path_parts = Vec::new(); |
1500 | | |
1501 | | // Get first identifier |
1502 | 2 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
1503 | 2 | path_parts.push(name.clone()); |
1504 | 2 | state.tokens.advance(); |
1505 | 2 | } else { |
1506 | 0 | bail!("Expected module path after 'use'"); |
1507 | | } |
1508 | | |
1509 | | // Parse additional path segments |
1510 | 2 | while matches!(state.tokens.peek(), Some((Token::ColonColon, _))) { |
1511 | 0 | state.tokens.advance(); // consume :: |
1512 | | |
1513 | | // Check for { imports } |
1514 | 0 | if matches!(state.tokens.peek(), Some((Token::LeftBrace, _))) { |
1515 | 0 | state.tokens.advance(); |
1516 | 0 | let mut items = Vec::new(); |
1517 | | |
1518 | | // Parse imported items |
1519 | 0 | while !matches!(state.tokens.peek(), Some((Token::RightBrace, _))) { |
1520 | 0 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
1521 | 0 | items.push(ImportItem::Named(name.clone())); |
1522 | 0 | state.tokens.advance(); |
1523 | | |
1524 | | // Check for comma |
1525 | 0 | if matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
1526 | 0 | state.tokens.advance(); |
1527 | 0 | } |
1528 | | } else { |
1529 | 0 | bail!("Expected identifier in import list"); |
1530 | | } |
1531 | | } |
1532 | | |
1533 | 0 | state.tokens.expect(&Token::RightBrace)?; |
1534 | | |
1535 | 0 | let path = path_parts.join("::"); |
1536 | 0 | return Ok(Expr::new(ExprKind::Import { path, items }, start_span)); |
1537 | 0 | } else if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
1538 | 0 | path_parts.push(name.clone()); |
1539 | 0 | state.tokens.advance(); |
1540 | 0 | } else { |
1541 | 0 | bail!("Expected identifier or '{{' after '::'"); |
1542 | | } |
1543 | | } |
1544 | | |
1545 | | // Simple use statement (use fully::qualified::Name) |
1546 | 2 | let path = path_parts.join("::"); |
1547 | 2 | let last_part = path_parts.last().unwrap().clone(); |
1548 | | |
1549 | 2 | Ok(Expr::new(ExprKind::Import { |
1550 | 2 | path, |
1551 | 2 | items: vec![ImportItem::Named(last_part)], |
1552 | 2 | }, start_span)) |
1553 | 2 | } |
1554 | | |
1555 | 5 | fn parse_dataframe_literal(state: &mut ParserState) -> Result<Expr> { |
1556 | | // Parse df![...] macro syntax |
1557 | 5 | let start_span = parse_dataframe_header(state)?0 ; |
1558 | 5 | let columns = parse_dataframe_columns(state)?0 ; |
1559 | 5 | state.tokens.expect(&Token::RightBracket)?0 ; |
1560 | | |
1561 | | // Convert to DataFrame expression |
1562 | 5 | let df_columns = create_dataframe_columns(columns); |
1563 | 5 | Ok(Expr::new(ExprKind::DataFrame { columns: df_columns }, start_span)) |
1564 | 5 | } |
1565 | | |
1566 | | /// Parse dataframe header: df![ |
1567 | | /// Complexity: 3 |
1568 | 5 | fn parse_dataframe_header(state: &mut ParserState) -> Result<Span> { |
1569 | 5 | let start_span = state.tokens.expect(&Token::DataFrame)?0 ; |
1570 | 5 | state.tokens.expect(&Token::Bang)?0 ; |
1571 | 5 | state.tokens.expect(&Token::LeftBracket)?0 ; |
1572 | 5 | Ok(start_span) |
1573 | 5 | } |
1574 | | |
1575 | | /// Parse all dataframe columns |
1576 | | /// Complexity: <5 |
1577 | 5 | fn parse_dataframe_columns(state: &mut ParserState) -> Result<Vec<(String, Expr)>> { |
1578 | 5 | let mut columns = Vec::new(); |
1579 | | |
1580 | 12 | while !matches!7 (state.tokens.peek(), Some((Token::RightBracket, _))) { |
1581 | 7 | let column = parse_single_dataframe_column(state)?0 ; |
1582 | 7 | columns.push(column); |
1583 | | |
1584 | | // Check for comma separator |
1585 | 7 | if matches!5 (state.tokens.peek(), Some((Token::Comma, _))) { |
1586 | 2 | state.tokens.advance(); |
1587 | 5 | } |
1588 | | } |
1589 | | |
1590 | 5 | Ok(columns) |
1591 | 5 | } |
1592 | | |
1593 | | /// Parse a single dataframe column: "name" => [values] |
1594 | | /// Complexity: <5 |
1595 | 7 | fn parse_single_dataframe_column(state: &mut ParserState) -> Result<(String, Expr)> { |
1596 | 7 | let col_name = parse_dataframe_column_name(state)?0 ; |
1597 | 7 | state.tokens.expect(&Token::FatArrow)?0 ; |
1598 | 7 | let values = parse_dataframe_column_values(state)?0 ; |
1599 | 7 | Ok((col_name, values)) |
1600 | 7 | } |
1601 | | |
1602 | | /// Parse dataframe column name (string or identifier) |
1603 | | /// Complexity: 3 |
1604 | 7 | fn parse_dataframe_column_name(state: &mut ParserState) -> Result<String> { |
1605 | 7 | match state.tokens.peek() { |
1606 | 0 | Some((Token::String(name), _)) => { |
1607 | 0 | let name = name.clone(); |
1608 | 0 | state.tokens.advance(); |
1609 | 0 | Ok(name) |
1610 | | } |
1611 | 7 | Some((Token::Identifier(name), _)) => { |
1612 | 7 | let name = name.clone(); |
1613 | 7 | state.tokens.advance(); |
1614 | 7 | Ok(name) |
1615 | | } |
1616 | 0 | _ => bail!("Expected column name (string or identifier) in dataframe") |
1617 | | } |
1618 | 7 | } |
1619 | | |
1620 | | /// Parse dataframe column values (must be a list) |
1621 | | /// Complexity: 2 |
1622 | 7 | fn parse_dataframe_column_values(state: &mut ParserState) -> Result<Expr> { |
1623 | 7 | if matches!0 (state.tokens.peek(), Some((Token::LeftBracket, _))) { |
1624 | 7 | parse_list_literal(state) |
1625 | | } else { |
1626 | 0 | bail!("Expected list of values after => in dataframe column") |
1627 | | } |
1628 | 7 | } |
1629 | | |
1630 | | /// Convert parsed columns to `DataFrameColumn` structs |
1631 | | /// Complexity: <5 |
1632 | 5 | fn create_dataframe_columns(columns: Vec<(String, Expr)>) -> Vec<DataFrameColumn> { |
1633 | 7 | columns5 .into_iter5 ().map5 (|(name, values)| { |
1634 | 7 | let value_exprs = match values.kind { |
1635 | 7 | ExprKind::List(exprs) => exprs, |
1636 | 0 | _ => vec![values], // Fallback for non-list |
1637 | | }; |
1638 | 7 | DataFrameColumn { |
1639 | 7 | name, |
1640 | 7 | values: value_exprs, |
1641 | 7 | } |
1642 | 7 | }).collect5 () |
1643 | 5 | } |
1644 | | |
1645 | 2 | fn parse_enum_definition(state: &mut ParserState) -> Result<Expr> { |
1646 | 2 | let start_span = state.tokens.expect(&Token::Enum)?0 ; |
1647 | 2 | let name = parse_enum_name(state)?0 ; |
1648 | 2 | let type_params = parse_optional_generics(state)?0 ; |
1649 | 2 | let variants = parse_enum_variants(state)?0 ; |
1650 | | |
1651 | 2 | Ok(Expr::new(ExprKind::Enum { |
1652 | 2 | name, |
1653 | 2 | type_params, |
1654 | 2 | variants, |
1655 | 2 | is_pub: false, |
1656 | 2 | }, start_span)) |
1657 | 2 | } |
1658 | | |
1659 | 2 | fn parse_enum_name(state: &mut ParserState) -> Result<String> { |
1660 | 2 | match state.tokens.peek() { |
1661 | 1 | Some((Token::Identifier(n), _)) => { |
1662 | 1 | let name = n.clone(); |
1663 | 1 | state.tokens.advance(); |
1664 | 1 | Ok(name) |
1665 | | } |
1666 | | Some((Token::Option, _)) => { |
1667 | 0 | state.tokens.advance(); |
1668 | 0 | Ok("Option".to_string()) |
1669 | | } |
1670 | | Some((Token::Result, _)) => { |
1671 | 1 | state.tokens.advance(); |
1672 | 1 | Ok("Result".to_string()) |
1673 | | } |
1674 | 0 | _ => bail!("Expected enum name after 'enum'") |
1675 | | } |
1676 | 2 | } |
1677 | | |
1678 | 7 | fn parse_optional_generics(state: &mut ParserState) -> Result<Vec<String>> { |
1679 | 7 | if matches!4 (state.tokens.peek(), Some((Token::Less, _))) { |
1680 | 3 | parse_generic_params(state) |
1681 | | } else { |
1682 | 4 | Ok(vec![]) |
1683 | | } |
1684 | 7 | } |
1685 | | |
1686 | 2 | fn parse_enum_variants(state: &mut ParserState) -> Result<Vec<EnumVariant>> { |
1687 | 2 | state.tokens.expect(&Token::LeftBrace)?0 ; |
1688 | 2 | let mut variants = Vec::new(); |
1689 | | |
1690 | 7 | while !matches!5 (state.tokens.peek(), Some((Token::RightBrace, _))) { |
1691 | 5 | variants.push(parse_single_variant(state)?0 ); |
1692 | | |
1693 | 5 | if matches!2 (state.tokens.peek(), Some((Token::Comma, _))) { |
1694 | 3 | state.tokens.advance(); |
1695 | 3 | }2 |
1696 | | } |
1697 | | |
1698 | 2 | state.tokens.expect(&Token::RightBrace)?0 ; |
1699 | 2 | Ok(variants) |
1700 | 2 | } |
1701 | | |
1702 | 5 | fn parse_single_variant(state: &mut ParserState) -> Result<EnumVariant> { |
1703 | 5 | let variant_name = parse_variant_name(state)?0 ; |
1704 | | |
1705 | | // Check for discriminant value: = <integer> |
1706 | 5 | let discriminant = if matches!(state.tokens.peek(), Some((Token::Equal, _))) { |
1707 | 0 | state.tokens.advance(); // consume = |
1708 | 0 | parse_variant_discriminant(state)? |
1709 | | } else { |
1710 | 5 | None |
1711 | | }; |
1712 | | |
1713 | | // Check for fields (tuple variants) |
1714 | 5 | let fields = if discriminant.is_none() { |
1715 | 5 | parse_variant_fields(state)?0 |
1716 | | } else { |
1717 | 0 | None // Can't have both discriminant and fields |
1718 | | }; |
1719 | | |
1720 | 5 | Ok(EnumVariant { |
1721 | 5 | name: variant_name, |
1722 | 5 | fields, |
1723 | 5 | discriminant, |
1724 | 5 | }) |
1725 | 5 | } |
1726 | | |
1727 | | /// Parse discriminant value for enum variant |
1728 | | /// Complexity: <5 |
1729 | 0 | fn parse_variant_discriminant(state: &mut ParserState) -> Result<Option<i64>> { |
1730 | 0 | match state.tokens.peek() { |
1731 | 0 | Some((Token::Integer(val), _)) => { |
1732 | 0 | let value = *val; |
1733 | 0 | state.tokens.advance(); |
1734 | 0 | Ok(Some(value)) |
1735 | | } |
1736 | | Some((Token::Minus, _)) => { |
1737 | 0 | state.tokens.advance(); // consume - |
1738 | 0 | match state.tokens.peek() { |
1739 | 0 | Some((Token::Integer(val), _)) => { |
1740 | 0 | let value = -(*val); |
1741 | 0 | state.tokens.advance(); |
1742 | 0 | Ok(Some(value)) |
1743 | | } |
1744 | 0 | _ => bail!("Expected integer after - in enum discriminant") |
1745 | | } |
1746 | | } |
1747 | 0 | _ => bail!("Expected integer value for enum discriminant") |
1748 | | } |
1749 | 0 | } |
1750 | | |
1751 | 5 | fn parse_variant_name(state: &mut ParserState) -> Result<String> { |
1752 | 5 | match state.tokens.peek() { |
1753 | 3 | Some((Token::Identifier(n), _)) => { |
1754 | 3 | let name = n.clone(); |
1755 | 3 | state.tokens.advance(); |
1756 | 3 | Ok(name) |
1757 | | } |
1758 | | Some((Token::Some, _)) => { |
1759 | 0 | state.tokens.advance(); |
1760 | 0 | Ok("Some".to_string()) |
1761 | | } |
1762 | | Some((Token::None, _)) => { |
1763 | 0 | state.tokens.advance(); |
1764 | 0 | Ok("None".to_string()) |
1765 | | } |
1766 | | Some((Token::Ok, _)) => { |
1767 | 1 | state.tokens.advance(); |
1768 | 1 | Ok("Ok".to_string()) |
1769 | | } |
1770 | | Some((Token::Err, _)) => { |
1771 | 1 | state.tokens.advance(); |
1772 | 1 | Ok("Err".to_string()) |
1773 | | } |
1774 | 0 | _ => bail!("Expected variant name in enum") |
1775 | | } |
1776 | 5 | } |
1777 | | |
1778 | 5 | fn parse_variant_fields(state: &mut ParserState) -> Result<Option<Vec<Type>>> { |
1779 | 5 | if !matches!3 (state.tokens.peek(), Some((Token::LeftParen, _))) { |
1780 | 3 | return Ok(None); |
1781 | 2 | } |
1782 | | |
1783 | 2 | state.tokens.advance(); |
1784 | 2 | let mut field_types = Vec::new(); |
1785 | | |
1786 | 4 | while !matches!2 (state.tokens.peek(), Some((Token::RightParen, _))) { |
1787 | 2 | field_types.push(super::utils::parse_type(state)?0 ); |
1788 | | |
1789 | 2 | if matches!(state.tokens.peek(), Some((Token::Comma, _))) { |
1790 | 0 | state.tokens.advance(); |
1791 | 2 | } |
1792 | | } |
1793 | | |
1794 | 2 | state.tokens.expect(&Token::RightParen)?0 ; |
1795 | 2 | Ok(Some(field_types)) |
1796 | 5 | } |
1797 | | |
1798 | 3 | fn parse_generic_params(state: &mut ParserState) -> Result<Vec<String>> { |
1799 | | // Parse <T, U, ...> |
1800 | 3 | state.tokens.expect(&Token::Less)?0 ; |
1801 | 3 | let mut params = Vec::new(); |
1802 | | |
1803 | 8 | while !matches!5 (state.tokens.peek(), Some((Token::Greater, _))) { |
1804 | 5 | if let Some((Token::Identifier(name), _)) = state.tokens.peek() { |
1805 | 5 | params.push(name.clone()); |
1806 | 5 | state.tokens.advance(); |
1807 | | |
1808 | | // Check for comma |
1809 | 5 | if matches!3 (state.tokens.peek(), Some((Token::Comma, _))) { |
1810 | 2 | state.tokens.advance(); |
1811 | 3 | } |
1812 | | } else { |
1813 | 0 | bail!("Expected type parameter name"); |
1814 | | } |
1815 | | } |
1816 | | |
1817 | 3 | state.tokens.expect(&Token::Greater)?0 ; |
1818 | 3 | Ok(params) |
1819 | 3 | } |
1820 | | |
1821 | 1 | fn parse_actor_definition(state: &mut ParserState) -> Result<Expr> { |
1822 | | // Parse actor Name { state: fields, receive handlers } |
1823 | 1 | let start_span = state.tokens.expect(&Token::Actor)?0 ; |
1824 | | |
1825 | | // Get actor name |
1826 | 1 | let name = parse_actor_name(state)?0 ; |
1827 | | |
1828 | | // Parse { body } |
1829 | 1 | state.tokens.expect(&Token::LeftBrace)?0 ; |
1830 | | |
1831 | | // Parse actor body components |
1832 | 1 | let (state_fields, handlers) = parse_actor_body(state)?0 ; |
1833 | | |
1834 | 1 | state.tokens.expect(&Token::RightBrace)?0 ; |
1835 | | |
1836 | | // Create the actor expression |
1837 | 1 | create_actor_expression(name, state_fields, handlers, start_span) |
1838 | 1 | } |
1839 | | |
1840 | | /// Parse actor name |
1841 | | /// Extracted from `parse_actor_definition` to reduce complexity |
1842 | 1 | fn parse_actor_name(state: &mut ParserState) -> Result<String> { |
1843 | 1 | if let Some((Token::Identifier(n), _)) = state.tokens.peek() { |
1844 | 1 | let name = n.clone(); |
1845 | 1 | state.tokens.advance(); |
1846 | 1 | Ok(name) |
1847 | | } else { |
1848 | 0 | bail!("Expected actor name after 'actor'"); |
1849 | | } |
1850 | 1 | } |
1851 | | |
1852 | | /// Parse actor body including state fields and handlers |
1853 | | /// Extracted from `parse_actor_definition` to reduce complexity |
1854 | 1 | fn parse_actor_body(state: &mut ParserState) -> Result<(Vec<(String, Type, Option<Box<Expr>>)>, Vec<String>)> { |
1855 | 1 | let mut state_fields = Vec::new(); |
1856 | 1 | let mut handlers = Vec::new(); |
1857 | | |
1858 | 3 | while !matches!2 (state.tokens.peek(), Some((Token::RightBrace, _))) { |
1859 | 2 | match state.tokens.peek() { |
1860 | | Some((Token::State, _)) => { |
1861 | 0 | let field = parse_actor_state_field(state)?; |
1862 | 0 | state_fields.push(field); |
1863 | | } |
1864 | | Some((Token::Receive, _)) => { |
1865 | 1 | let new_handlers = parse_actor_receive_block(state)?0 ; |
1866 | 1 | handlers.extend(new_handlers); |
1867 | | } |
1868 | | Some((Token::Identifier(_), _)) => { |
1869 | 1 | let field = parse_actor_bare_field(state)?0 ; |
1870 | 1 | state_fields.push(field); |
1871 | | } |
1872 | 0 | _ => { |
1873 | 0 | // Skip unknown tokens |
1874 | 0 | state.tokens.advance(); |
1875 | 0 | } |
1876 | | } |
1877 | | } |
1878 | | |
1879 | 1 | Ok((state_fields, handlers)) |
1880 | 1 | } |
1881 | | |
1882 | | /// Parse state field with 'state' keyword |
1883 | | /// Extracted from `parse_actor_body` to reduce complexity |
1884 | 0 | fn parse_actor_state_field(state: &mut ParserState) -> Result<(String, Type, Option<Box<Expr>>)> { |
1885 | 0 | state.tokens.advance(); // consume 'state' |
1886 | | |
1887 | 0 | if let Some((Token::Identifier(field_name), _)) = state.tokens.peek() { |
1888 | 0 | let field = field_name.clone(); |
1889 | 0 | state.tokens.advance(); |
1890 | | |
1891 | | // Parse : Type |
1892 | 0 | state.tokens.expect(&Token::Colon)?; |
1893 | 0 | let field_type = super::utils::parse_type(state)?; |
1894 | | |
1895 | | // Optional = initial_value |
1896 | 0 | let initial_value = if matches!(state.tokens.peek(), Some((Token::Equal, _))) { |
1897 | 0 | state.tokens.advance(); |
1898 | 0 | Some(Box::new(super::parse_expr_recursive(state)?)) |
1899 | | } else { |
1900 | 0 | None |
1901 | | }; |
1902 | | |
1903 | 0 | Ok((field, field_type, initial_value)) |
1904 | | } else { |
1905 | 0 | bail!("Expected field name after 'state'"); |
1906 | | } |
1907 | 0 | } |
1908 | | |
1909 | | /// Parse receive block with handlers |
1910 | | /// Extracted from `parse_actor_body` to reduce complexity |
1911 | 1 | fn parse_actor_receive_block(state: &mut ParserState) -> Result<Vec<String>> { |
1912 | 1 | state.tokens.advance(); // consume 'receive' |
1913 | 1 | state.tokens.expect(&Token::LeftBrace)?0 ; |
1914 | | |
1915 | 1 | let mut handlers = Vec::new(); |
1916 | | |
1917 | 3 | while !matches!2 (state.tokens.peek(), Some((Token::RightBrace, _))) { |
1918 | 2 | if let Some((Token::Identifier(handler_name), _)) = state.tokens.peek() { |
1919 | 2 | handlers.push(handler_name.clone()); |
1920 | 2 | state.tokens.advance(); |
1921 | | |
1922 | | // Skip => value for now |
1923 | 2 | state.tokens.expect(&Token::FatArrow)?0 ; |
1924 | 2 | super::parse_expr_recursive(state)?0 ; // Skip the value |
1925 | | |
1926 | | // Optional comma |
1927 | 2 | if matches!1 (state.tokens.peek(), Some((Token::Comma, _))) { |
1928 | 1 | state.tokens.advance(); |
1929 | 1 | } |
1930 | | } else { |
1931 | 0 | bail!("Expected handler name in receive block"); |
1932 | | } |
1933 | | } |
1934 | | |
1935 | 1 | state.tokens.expect(&Token::RightBrace)?0 ; |
1936 | 1 | Ok(handlers) |
1937 | 1 | } |
1938 | | |
1939 | | /// Parse bare field definition |
1940 | | /// Extracted from `parse_actor_body` to reduce complexity |
1941 | 1 | fn parse_actor_bare_field(state: &mut ParserState) -> Result<(String, Type, Option<Box<Expr>>)> { |
1942 | 1 | if let Some((Token::Identifier(field_name), _)) = state.tokens.peek() { |
1943 | 1 | let field = field_name.clone(); |
1944 | 1 | state.tokens.advance(); |
1945 | | |
1946 | | // Parse : Type |
1947 | 1 | state.tokens.expect(&Token::Colon)?0 ; |
1948 | 1 | let field_type = super::utils::parse_type(state)?0 ; |
1949 | | |
1950 | | // Optional comma |
1951 | 1 | if matches!0 (state.tokens.peek(), Some((Token::Comma, _))) { |
1952 | 1 | state.tokens.advance(); |
1953 | 1 | }0 |
1954 | | |
1955 | 1 | Ok((field, field_type, None)) |
1956 | | } else { |
1957 | 0 | bail!("Expected field name in actor"); |
1958 | | } |
1959 | 1 | } |
1960 | | |
1961 | | /// Create the final actor expression |
1962 | | /// Extracted from `parse_actor_definition` to reduce complexity |
1963 | 1 | fn create_actor_expression( |
1964 | 1 | name: String, |
1965 | 1 | state_fields: Vec<(String, Type, Option<Box<Expr>>)>, |
1966 | 1 | handlers: Vec<String>, |
1967 | 1 | start_span: Span, |
1968 | 1 | ) -> Result<Expr> { |
1969 | | // Create an Actor expression with proper types |
1970 | 1 | let actor_state = state_fields.into_iter().map(|(name, ty, _init)| StructField { |
1971 | 1 | name, |
1972 | 1 | ty, |
1973 | | is_pub: false, |
1974 | 1 | }).collect(); |
1975 | | |
1976 | | // For now, create simple handlers |
1977 | 1 | let actor_handlers = handlers.into_iter().map(|name| ActorHandler { |
1978 | 2 | message_type: name, |
1979 | 2 | params: vec![], |
1980 | 2 | body: Box::new(Expr::new(ExprKind::Block(vec![]), start_span)), |
1981 | 2 | }).collect1 (); |
1982 | | |
1983 | 1 | Ok(Expr::new(ExprKind::Actor { |
1984 | 1 | name, |
1985 | 1 | state: actor_state, |
1986 | 1 | handlers: actor_handlers, |
1987 | 1 | }, start_span)) |
1988 | 1 | } |
1989 | | |
1990 | 791 | pub fn token_to_binary_op(token: &Token) -> Option<BinaryOp> { |
1991 | | // Try each category of operators |
1992 | 791 | map_arithmetic_operator(token) |
1993 | 791 | .or_else(|| map_comparison_operator681 (token681 )) |
1994 | 791 | .or_else(|| map_logical_operator649 (token649 )) |
1995 | 791 | .or_else(|| map_bitwise_operator638 (token638 )) |
1996 | 791 | } |
1997 | | |
1998 | | /// Map arithmetic tokens to binary operators |
1999 | | /// Extracted from `token_to_binary_op` to reduce complexity |
2000 | 791 | fn map_arithmetic_operator(token: &Token) -> Option<BinaryOp> { |
2001 | 791 | match token { |
2002 | 57 | Token::Plus => Some(BinaryOp::Add), |
2003 | 13 | Token::Minus => Some(BinaryOp::Subtract), |
2004 | 29 | Token::Star => Some(BinaryOp::Multiply), |
2005 | 5 | Token::Slash => Some(BinaryOp::Divide), |
2006 | 5 | Token::Percent => Some(BinaryOp::Modulo), |
2007 | 1 | Token::Power => Some(BinaryOp::Power), |
2008 | 681 | _ => None, |
2009 | | } |
2010 | 791 | } |
2011 | | |
2012 | | /// Map comparison tokens to binary operators |
2013 | | /// Extracted from `token_to_binary_op` to reduce complexity |
2014 | 681 | fn map_comparison_operator(token: &Token) -> Option<BinaryOp> { |
2015 | 681 | match token { |
2016 | 5 | Token::EqualEqual => Some(BinaryOp::Equal), |
2017 | 3 | Token::NotEqual => Some(BinaryOp::NotEqual), |
2018 | 6 | Token::Less => Some(BinaryOp::Less), |
2019 | 5 | Token::LessEqual => Some(BinaryOp::LessEqual), |
2020 | 10 | Token::Greater => Some(BinaryOp::Greater), |
2021 | 3 | Token::GreaterEqual => Some(BinaryOp::GreaterEqual), |
2022 | 649 | _ => None, |
2023 | | } |
2024 | 681 | } |
2025 | | |
2026 | | /// Map logical tokens to binary operators |
2027 | | /// Extracted from `token_to_binary_op` to reduce complexity |
2028 | 649 | fn map_logical_operator(token: &Token) -> Option<BinaryOp> { |
2029 | 649 | match token { |
2030 | 9 | Token::AndAnd => Some(BinaryOp::And), |
2031 | 2 | Token::OrOr => Some(BinaryOp::Or), |
2032 | 0 | Token::NullCoalesce => Some(BinaryOp::NullCoalesce), |
2033 | 638 | _ => None, |
2034 | | } |
2035 | 649 | } |
2036 | | |
2037 | | /// Map bitwise tokens to binary operators |
2038 | | /// Extracted from `token_to_binary_op` to reduce complexity |
2039 | 638 | fn map_bitwise_operator(token: &Token) -> Option<BinaryOp> { |
2040 | 638 | match token { |
2041 | 1 | Token::Ampersand => Some(BinaryOp::BitwiseAnd), |
2042 | 2 | Token::Pipe => Some(BinaryOp::BitwiseOr), |
2043 | 1 | Token::Caret => Some(BinaryOp::BitwiseXor), |
2044 | 1 | Token::LeftShift => Some(BinaryOp::LeftShift), |
2045 | 633 | _ => None, |
2046 | | } |
2047 | 638 | } |
2048 | | |
2049 | 158 | pub fn get_precedence(op: BinaryOp) -> i32 { |
2050 | 158 | match op { |
2051 | 2 | BinaryOp::Or => 1, |
2052 | 0 | BinaryOp::NullCoalesce => 2, |
2053 | 9 | BinaryOp::And => 3, |
2054 | 2 | BinaryOp::BitwiseOr => 4, |
2055 | 1 | BinaryOp::BitwiseXor => 5, |
2056 | 1 | BinaryOp::BitwiseAnd => 6, |
2057 | 8 | BinaryOp::Equal | BinaryOp::NotEqual => 7, |
2058 | 24 | BinaryOp::Less | BinaryOp::LessEqual | BinaryOp::Greater | BinaryOp::GreaterEqual => 8, |
2059 | 1 | BinaryOp::LeftShift => 9, |
2060 | 70 | BinaryOp::Add | BinaryOp::Subtract => 10, |
2061 | 39 | BinaryOp::Multiply | BinaryOp::Divide | BinaryOp::Modulo => 11, |
2062 | 1 | BinaryOp::Power => 12, |
2063 | | } |
2064 | 158 | } |