1#![allow(clippy::unwrap_used)]
2#![allow(dead_code)]
3
4use crate::expr::{
5 BinaryOp, BinaryOpExpr, BindingExpr, ConditionalExpr, Expr, FieldAccessExpr, LiteralExpr,
6 MethodCallExpr, SharedFieldAccessExpr, UnaryOp, UnaryOpExpr,
7};
8use crate::ir::span::Span;
9
10pub fn tokenize_binding_expr(
12 input: &str,
13 start_pos: usize,
14 line: u32,
15 column: u32,
16) -> Result<BindingExpr, String> {
17 let mut parser = ExprParser::new(input, start_pos, line, column);
18 let expr = parser.parse()?;
19 let span = Span::new(start_pos, start_pos + input.len(), line, column);
20 Ok(BindingExpr { expr, span })
21}
22
23struct ExprParser<'a> {
24 input: &'a str,
25 pos: usize,
26 start_pos: usize,
27 line: u32,
28 column: u32,
29}
30
31impl<'a> ExprParser<'a> {
32 fn new(input: &'a str, start_pos: usize, line: u32, column: u32) -> Self {
33 Self {
34 input,
35 pos: 0,
36 start_pos,
37 line,
38 column,
39 }
40 }
41
42 fn parse(&mut self) -> Result<Expr, String> {
43 self.parse_conditional()
44 }
45
46 fn parse_conditional(&mut self) -> Result<Expr, String> {
47 self.skip_whitespace();
48 if self.peek_keyword("if") {
49 self.consume_keyword("if")?;
50 self.skip_whitespace();
51 let condition = self.parse_or()?;
52 self.skip_whitespace();
53 self.consume_keyword("then")?;
54 self.skip_whitespace();
55 let then_branch = self.parse_or()?;
56 self.skip_whitespace();
57 self.consume_keyword("else")?;
58 self.skip_whitespace();
59 let else_branch = self.parse_or()?;
60
61 return Ok(Expr::Conditional(ConditionalExpr {
62 condition: Box::new(condition),
63 then_branch: Box::new(then_branch),
64 else_branch: Box::new(else_branch),
65 }));
66 }
67
68 self.parse_or()
69 }
70
71 fn parse_or(&mut self) -> Result<Expr, String> {
72 let mut left = self.parse_and()?;
73
74 loop {
75 self.skip_whitespace();
76 if self.peek_str("||") {
77 self.consume_str("||")?;
78 self.skip_whitespace();
79 let right = self.parse_and()?;
80 left = Expr::BinaryOp(BinaryOpExpr {
81 left: Box::new(left),
82 op: BinaryOp::Or,
83 right: Box::new(right),
84 });
85 } else {
86 break;
87 }
88 }
89
90 Ok(left)
91 }
92
93 fn parse_and(&mut self) -> Result<Expr, String> {
94 let mut left = self.parse_comparison()?;
95
96 loop {
97 self.skip_whitespace();
98 if self.peek_str("&&") {
99 self.consume_str("&&")?;
100 self.skip_whitespace();
101 let right = self.parse_comparison()?;
102 left = Expr::BinaryOp(BinaryOpExpr {
103 left: Box::new(left),
104 op: BinaryOp::And,
105 right: Box::new(right),
106 });
107 } else {
108 break;
109 }
110 }
111
112 Ok(left)
113 }
114
115 fn parse_comparison(&mut self) -> Result<Expr, String> {
116 let mut left = self.parse_additive()?;
117
118 loop {
119 self.skip_whitespace();
120
121 if self.peek_str("==") {
122 self.consume_str("==")?;
123 self.skip_whitespace();
124 let right = self.parse_additive()?;
125 left = Expr::BinaryOp(BinaryOpExpr {
126 left: Box::new(left),
127 op: BinaryOp::Eq,
128 right: Box::new(right),
129 });
130 } else if self.peek_str("!=") {
131 self.consume_str("!=")?;
132 self.skip_whitespace();
133 let right = self.parse_additive()?;
134 left = Expr::BinaryOp(BinaryOpExpr {
135 left: Box::new(left),
136 op: BinaryOp::Ne,
137 right: Box::new(right),
138 });
139 } else if self.peek_str("<=") {
140 self.consume_str("<=")?;
141 self.skip_whitespace();
142 let right = self.parse_additive()?;
143 left = Expr::BinaryOp(BinaryOpExpr {
144 left: Box::new(left),
145 op: BinaryOp::Le,
146 right: Box::new(right),
147 });
148 } else if self.peek_str(">=") {
149 self.consume_str(">=")?;
150 self.skip_whitespace();
151 let right = self.parse_additive()?;
152 left = Expr::BinaryOp(BinaryOpExpr {
153 left: Box::new(left),
154 op: BinaryOp::Ge,
155 right: Box::new(right),
156 });
157 } else if self.peek_str("<") {
158 self.consume_str("<")?;
159 self.skip_whitespace();
160 let right = self.parse_additive()?;
161 left = Expr::BinaryOp(BinaryOpExpr {
162 left: Box::new(left),
163 op: BinaryOp::Lt,
164 right: Box::new(right),
165 });
166 } else if self.peek_str(">") {
167 self.consume_str(">")?;
168 self.skip_whitespace();
169 let right = self.parse_additive()?;
170 left = Expr::BinaryOp(BinaryOpExpr {
171 left: Box::new(left),
172 op: BinaryOp::Gt,
173 right: Box::new(right),
174 });
175 } else {
176 break;
177 }
178 }
179
180 Ok(left)
181 }
182
183 fn parse_additive(&mut self) -> Result<Expr, String> {
184 let mut left = self.parse_multiplicative()?;
185
186 loop {
187 self.skip_whitespace();
188
189 if self.peek_str("+") {
190 self.consume_str("+")?;
191 self.skip_whitespace();
192 let right = self.parse_multiplicative()?;
193 left = Expr::BinaryOp(BinaryOpExpr {
194 left: Box::new(left),
195 op: BinaryOp::Add,
196 right: Box::new(right),
197 });
198 } else if self.peek_str("-") {
199 self.consume_str("-")?;
200 self.skip_whitespace();
201 let right = self.parse_multiplicative()?;
202 left = Expr::BinaryOp(BinaryOpExpr {
203 left: Box::new(left),
204 op: BinaryOp::Sub,
205 right: Box::new(right),
206 });
207 } else {
208 break;
209 }
210 }
211
212 Ok(left)
213 }
214
215 fn parse_multiplicative(&mut self) -> Result<Expr, String> {
216 let mut left = self.parse_unary()?;
217
218 loop {
219 self.skip_whitespace();
220
221 if self.peek_str("*") {
222 self.consume_str("*")?;
223 self.skip_whitespace();
224 let right = self.parse_unary()?;
225 left = Expr::BinaryOp(BinaryOpExpr {
226 left: Box::new(left),
227 op: BinaryOp::Mul,
228 right: Box::new(right),
229 });
230 } else if self.peek_str("/") {
231 self.consume_str("/")?;
232 self.skip_whitespace();
233 let right = self.parse_unary()?;
234 left = Expr::BinaryOp(BinaryOpExpr {
235 left: Box::new(left),
236 op: BinaryOp::Div,
237 right: Box::new(right),
238 });
239 } else {
240 break;
241 }
242 }
243
244 Ok(left)
245 }
246
247 fn parse_unary(&mut self) -> Result<Expr, String> {
248 self.skip_whitespace();
249
250 if self.peek_str("!") {
251 self.consume_str("!")?;
252 let operand = self.parse_unary()?;
253 return Ok(Expr::UnaryOp(UnaryOpExpr {
254 op: UnaryOp::Not,
255 operand: Box::new(operand),
256 }));
257 } else if self.peek_str("-") {
258 self.consume_str("-")?;
259 let operand = self.parse_unary()?;
260 return Ok(Expr::UnaryOp(UnaryOpExpr {
261 op: UnaryOp::Neg,
262 operand: Box::new(operand),
263 }));
264 }
265
266 self.parse_primary()
267 }
268
269 fn parse_primary(&mut self) -> Result<Expr, String> {
270 self.skip_whitespace();
271
272 if self.peek_str("\"") || self.peek_str("'") {
274 return self.parse_string_literal();
275 }
276
277 if self.peek_digit() || self.peek_str("-") {
279 return self.parse_number_literal();
280 }
281
282 if self.peek_keyword("true") {
284 self.consume_keyword("true")?;
285 return Ok(Expr::Literal(LiteralExpr::Bool(true)));
286 }
287 if self.peek_keyword("false") {
288 self.consume_keyword("false")?;
289 return Ok(Expr::Literal(LiteralExpr::Bool(false)));
290 }
291
292 if self.peek_alpha() || self.peek_str("_") {
294 return self.parse_field_or_method();
295 }
296
297 if self.peek_str("(") {
299 self.consume_str("(")?;
300 let expr = self.parse()?;
301 self.skip_whitespace();
302 self.consume_str(")")?;
303 return Ok(expr);
304 }
305
306 Err(format!("Unexpected character at position {}", self.pos))
307 }
308
309 fn parse_field_or_method(&mut self) -> Result<Expr, String> {
310 let mut path = Vec::new();
311
312 let ident = self.parse_identifier()?;
314
315 let is_shared = ident == "shared";
317
318 if is_shared {
319 self.skip_whitespace();
321 if !self.peek_str(".") {
322 path.push(ident);
324 } else {
325 self.consume_str(".")?;
327
328 let mut shared_path = Vec::new();
330 let first_field = self.parse_identifier()?;
331 shared_path.push(first_field);
332
333 loop {
335 self.skip_whitespace();
336 if self.peek_str(".") {
337 self.consume_str(".")?;
338 let next_ident = self.parse_identifier()?;
339 shared_path.push(next_ident);
340 } else {
341 break;
342 }
343 }
344
345 self.skip_whitespace();
347 if self.peek_str("(") {
348 self.consume_str("(")?;
349 let mut args = Vec::new();
350
351 loop {
353 self.skip_whitespace();
354 if self.peek_str(")") {
355 break;
356 }
357
358 let arg = self.parse()?;
359 args.push(arg);
360
361 self.skip_whitespace();
362 if self.peek_str(",") {
363 self.consume_str(",")?;
364 } else {
365 break;
366 }
367 }
368
369 self.consume_str(")")?;
370
371 let method = shared_path.pop().ok_or("Empty path for method call")?;
373 let receiver = if shared_path.is_empty() {
374 Expr::SharedFieldAccess(SharedFieldAccessExpr { path: vec![] })
376 } else {
377 Expr::SharedFieldAccess(SharedFieldAccessExpr { path: shared_path })
378 };
379
380 return Ok(Expr::MethodCall(MethodCallExpr {
381 receiver: Box::new(receiver),
382 method,
383 args,
384 }));
385 }
386
387 return Ok(Expr::SharedFieldAccess(SharedFieldAccessExpr {
389 path: shared_path,
390 }));
391 }
392 } else {
393 path.push(ident);
394 }
395
396 loop {
398 self.skip_whitespace();
399 if self.peek_str(".") {
400 self.consume_str(".")?;
401 let next_ident = self.parse_identifier()?;
402 path.push(next_ident);
403 } else {
404 break;
405 }
406 }
407
408 self.skip_whitespace();
410 if self.peek_str("(") {
411 self.consume_str("(")?;
412 let mut args = Vec::new();
413
414 loop {
416 self.skip_whitespace();
417 if self.peek_str(")") {
418 break;
419 }
420
421 let arg = self.parse()?;
422 args.push(arg);
423
424 self.skip_whitespace();
425 if self.peek_str(",") {
426 self.consume_str(",")?;
427 } else {
428 break;
429 }
430 }
431
432 self.consume_str(")")?;
433
434 let method = path.pop().ok_or("Empty path for method call")?;
436 let receiver = if path.is_empty() {
437 Expr::Literal(LiteralExpr::String("self".to_string()))
438 } else {
439 Expr::FieldAccess(FieldAccessExpr { path })
440 };
441
442 return Ok(Expr::MethodCall(MethodCallExpr {
443 receiver: Box::new(receiver),
444 method,
445 args,
446 }));
447 }
448
449 Ok(Expr::FieldAccess(FieldAccessExpr { path }))
451 }
452
453 fn parse_string_literal(&mut self) -> Result<Expr, String> {
454 let quote = if self.peek_str("\"") { "\"" } else { "'" };
455 self.consume_str(quote)?;
456
457 let mut value = String::new();
458 while self.pos < self.input.len() {
459 let c = self.input[self.pos..].chars().next().unwrap();
460 if c.to_string() == quote {
461 self.pos += 1;
462 break;
463 }
464 if c == '\\' {
465 self.pos += 1;
467 if self.pos < self.input.len() {
468 let next = self.input[self.pos..].chars().next().unwrap();
469 value.push(next);
470 self.pos += next.len_utf8();
471 }
472 } else {
473 value.push(c);
474 self.pos += c.len_utf8();
475 }
476 }
477
478 Ok(Expr::Literal(LiteralExpr::String(value)))
479 }
480
481 fn parse_number_literal(&mut self) -> Result<Expr, String> {
482 let start = self.pos;
483 let mut is_float = false;
484
485 if self.peek_str("-") {
486 self.pos += 1;
487 }
488
489 while self.pos < self.input.len() {
490 let c = self.input[self.pos..].chars().next().unwrap();
491 if c.is_ascii_digit() {
492 self.pos += 1;
493 } else if c == '.' && !is_float {
494 is_float = true;
495 self.pos += 1;
496 } else {
497 break;
498 }
499 }
500
501 let num_str = &self.input[start..self.pos];
502
503 if is_float {
504 let value: f64 = num_str
505 .parse()
506 .map_err(|e| format!("Invalid float: {}", e))?;
507 Ok(Expr::Literal(LiteralExpr::Float(value)))
508 } else {
509 let value: i64 = num_str
510 .parse()
511 .map_err(|e| format!("Invalid integer: {}", e))?;
512 Ok(Expr::Literal(LiteralExpr::Integer(value)))
513 }
514 }
515
516 fn parse_identifier(&mut self) -> Result<String, String> {
517 let start = self.pos;
518
519 if self.pos >= self.input.len() {
520 return Err("Expected identifier".to_string());
521 }
522
523 let first = self.input[self.pos..].chars().next().unwrap();
524 if !first.is_alphabetic() && first != '_' {
525 return Err(format!("Expected identifier, got '{}'", first));
526 }
527
528 self.pos += first.len_utf8();
529
530 while self.pos < self.input.len() {
531 let c = self.input[self.pos..].chars().next().unwrap();
532 if c.is_alphanumeric() || c == '_' {
533 self.pos += c.len_utf8();
534 } else {
535 break;
536 }
537 }
538
539 Ok(self.input[start..self.pos].to_string())
540 }
541
542 fn skip_whitespace(&mut self) {
543 while self.pos < self.input.len() {
544 if let Some(c) = self.input[self.pos..].chars().next() {
545 if c.is_whitespace() {
546 self.pos += c.len_utf8();
547 } else {
548 break;
549 }
550 } else {
551 break;
552 }
553 }
554 }
555
556 fn peek_str(&self, s: &str) -> bool {
557 self.input[self.pos..].starts_with(s)
558 }
559
560 fn peek_keyword(&self, keyword: &str) -> bool {
561 let remaining = &self.input[self.pos..];
562 if !remaining.starts_with(keyword) {
563 return false;
564 }
565 if let Some(next_char) = remaining[keyword.len()..].chars().next() {
567 !next_char.is_alphanumeric() && next_char != '_'
568 } else {
569 true
570 }
571 }
572
573 fn peek_digit(&self) -> bool {
574 self.input[self.pos..]
575 .chars()
576 .next()
577 .map(|c| c.is_ascii_digit())
578 .unwrap_or(false)
579 }
580
581 fn peek_alpha(&self) -> bool {
582 self.input[self.pos..]
583 .chars()
584 .next()
585 .map(|c| c.is_alphabetic())
586 .unwrap_or(false)
587 }
588
589 fn consume_str(&mut self, s: &str) -> Result<(), String> {
590 if self.peek_str(s) {
591 self.pos += s.len();
592 Ok(())
593 } else {
594 Err(format!("Expected '{}'", s))
595 }
596 }
597
598 fn consume_keyword(&mut self, keyword: &str) -> Result<(), String> {
599 if self.peek_keyword(keyword) {
600 self.pos += keyword.len();
601 Ok(())
602 } else {
603 Err(format!("Expected keyword '{}'", keyword))
604 }
605 }
606}