Skip to main content

rajac_parser/
expr.rs

1use crate::parser::Parser;
2use rajac_ast::*;
3use rajac_token::TokenKind;
4use rajac_types::Ident;
5
6impl<'a> Parser<'a> {
7    /// Parse an expression
8    pub fn parse_expression(&mut self) -> Option<ExprId> {
9        let expr = self.parse_ternary()?;
10        self.parse_assignment(expr)
11    }
12
13    fn parse_ternary(&mut self) -> Option<ExprId> {
14        let mut expr = self.parse_or()?;
15
16        if self.consume(TokenKind::Question) {
17            let then_expr = self.parse_expression()?;
18            self.expect(TokenKind::Colon);
19            let else_expr = self.parse_expression()?;
20
21            let ternary = Expr::Ternary {
22                condition: expr,
23                then_expr,
24                else_expr,
25            };
26            expr = self.arena.alloc_expr(ternary);
27        }
28
29        Some(expr)
30    }
31
32    fn parse_or(&mut self) -> Option<ExprId> {
33        let mut expr = self.parse_and()?;
34
35        while self.consume(TokenKind::Or) {
36            let rhs = self.parse_and()?;
37            let binary = Expr::Binary {
38                op: BinaryOp::Or,
39                lhs: expr,
40                rhs,
41            };
42            expr = self.arena.alloc_expr(binary);
43        }
44
45        Some(expr)
46    }
47
48    fn parse_and(&mut self) -> Option<ExprId> {
49        let mut expr = self.parse_bitwise_or()?;
50
51        while self.consume(TokenKind::And) {
52            let rhs = self.parse_bitwise_or()?;
53            let binary = Expr::Binary {
54                op: BinaryOp::And,
55                lhs: expr,
56                rhs,
57            };
58            expr = self.arena.alloc_expr(binary);
59        }
60
61        Some(expr)
62    }
63
64    fn parse_bitwise_or(&mut self) -> Option<ExprId> {
65        let mut expr = self.parse_bitwise_xor()?;
66
67        while self.is(TokenKind::Pipe) && !self.is_or() {
68            self.bump();
69            let rhs = self.parse_bitwise_xor()?;
70            let binary = Expr::Binary {
71                op: BinaryOp::BitOr,
72                lhs: expr,
73                rhs,
74            };
75            expr = self.arena.alloc_expr(binary);
76        }
77
78        Some(expr)
79    }
80
81    fn parse_bitwise_xor(&mut self) -> Option<ExprId> {
82        let mut expr = self.parse_bitwise_and()?;
83
84        while self.consume(TokenKind::Caret) {
85            let rhs = self.parse_bitwise_and()?;
86            let binary = Expr::Binary {
87                op: BinaryOp::BitXor,
88                lhs: expr,
89                rhs,
90            };
91            expr = self.arena.alloc_expr(binary);
92        }
93
94        Some(expr)
95    }
96
97    fn parse_bitwise_and(&mut self) -> Option<ExprId> {
98        let mut expr = self.parse_equality()?;
99
100        while self.is(TokenKind::Ampersand) && !self.is_and() {
101            self.bump();
102            let rhs = self.parse_equality()?;
103            let binary = Expr::Binary {
104                op: BinaryOp::BitAnd,
105                lhs: expr,
106                rhs,
107            };
108            expr = self.arena.alloc_expr(binary);
109        }
110
111        Some(expr)
112    }
113
114    fn parse_equality(&mut self) -> Option<ExprId> {
115        let mut expr = self.parse_relational()?;
116
117        loop {
118            let op = match self.peek() {
119                TokenKind::EqEq => BinaryOp::EqEq,
120                TokenKind::BangEq => BinaryOp::BangEq,
121                _ => break,
122            };
123            self.bump();
124            let rhs = self.parse_relational()?;
125            let binary = Expr::Binary { op, lhs: expr, rhs };
126            expr = self.arena.alloc_expr(binary);
127        }
128
129        Some(expr)
130    }
131
132    fn parse_relational(&mut self) -> Option<ExprId> {
133        let mut expr = self.parse_shift()?;
134
135        loop {
136            if self.consume(TokenKind::Lt) {
137                let rhs = self.parse_shift()?;
138                let binary = Expr::Binary {
139                    op: BinaryOp::Lt,
140                    lhs: expr,
141                    rhs,
142                };
143                expr = self.arena.alloc_expr(binary);
144            } else if self.consume(TokenKind::LtEq) {
145                let rhs = self.parse_shift()?;
146                let binary = Expr::Binary {
147                    op: BinaryOp::LtEq,
148                    lhs: expr,
149                    rhs,
150                };
151                expr = self.arena.alloc_expr(binary);
152            } else if self.consume(TokenKind::Gt) {
153                let rhs = self.parse_shift()?;
154                let binary = Expr::Binary {
155                    op: BinaryOp::Gt,
156                    lhs: expr,
157                    rhs,
158                };
159                expr = self.arena.alloc_expr(binary);
160            } else if self.consume(TokenKind::GtEq) {
161                let rhs = self.parse_shift()?;
162                let binary = Expr::Binary {
163                    op: BinaryOp::GtEq,
164                    lhs: expr,
165                    rhs,
166                };
167                expr = self.arena.alloc_expr(binary);
168            } else if self.consume(TokenKind::KwInstanceof) {
169                let ty = self.parse_type()?;
170                let instanceof = Expr::InstanceOf { expr, ty };
171                expr = self.arena.alloc_expr(instanceof);
172            } else {
173                break;
174            }
175        }
176
177        Some(expr)
178    }
179
180    fn parse_shift(&mut self) -> Option<ExprId> {
181        let mut expr = self.parse_additive()?;
182
183        loop {
184            let op = match self.peek() {
185                TokenKind::LtLt => BinaryOp::LShift,
186                TokenKind::GtGt => BinaryOp::RShift,
187                TokenKind::GtGtGt => BinaryOp::ARShift,
188                _ => break,
189            };
190            self.bump();
191            let rhs = self.parse_additive()?;
192            let binary = Expr::Binary { op, lhs: expr, rhs };
193            expr = self.arena.alloc_expr(binary);
194        }
195
196        Some(expr)
197    }
198
199    fn parse_additive(&mut self) -> Option<ExprId> {
200        let mut expr = self.parse_multiplicative()?;
201
202        loop {
203            let op = match self.peek() {
204                TokenKind::Plus => BinaryOp::Add,
205                TokenKind::Minus => BinaryOp::Sub,
206                _ => break,
207            };
208            self.bump();
209            let rhs = self.parse_multiplicative()?;
210            let binary = Expr::Binary { op, lhs: expr, rhs };
211            expr = self.arena.alloc_expr(binary);
212        }
213
214        Some(expr)
215    }
216
217    fn parse_multiplicative(&mut self) -> Option<ExprId> {
218        let mut expr = self.parse_unary()?;
219
220        loop {
221            let op = match self.peek() {
222                TokenKind::Star => BinaryOp::Mul,
223                TokenKind::Slash => BinaryOp::Div,
224                TokenKind::Percent => BinaryOp::Mod,
225                _ => break,
226            };
227            self.bump();
228            let rhs = self.parse_unary()?;
229            let binary = Expr::Binary { op, lhs: expr, rhs };
230            expr = self.arena.alloc_expr(binary);
231        }
232
233        Some(expr)
234    }
235
236    fn parse_unary(&mut self) -> Option<ExprId> {
237        match self.peek() {
238            TokenKind::Plus => {
239                self.bump();
240                let expr = self.parse_unary()?;
241                let unary = Expr::Unary {
242                    op: UnaryOp::Plus,
243                    expr,
244                };
245                Some(self.arena.alloc_expr(unary))
246            }
247            TokenKind::Minus => {
248                self.bump();
249                let expr = self.parse_unary()?;
250                let unary = Expr::Unary {
251                    op: UnaryOp::Minus,
252                    expr,
253                };
254                Some(self.arena.alloc_expr(unary))
255            }
256            TokenKind::Bang => {
257                self.bump();
258                let expr = self.parse_unary()?;
259                let unary = Expr::Unary {
260                    op: UnaryOp::Bang,
261                    expr,
262                };
263                Some(self.arena.alloc_expr(unary))
264            }
265            TokenKind::Tilde => {
266                self.bump();
267                let expr = self.parse_unary()?;
268                let unary = Expr::Unary {
269                    op: UnaryOp::Tilde,
270                    expr,
271                };
272                Some(self.arena.alloc_expr(unary))
273            }
274            TokenKind::PlusPlus => {
275                self.bump();
276                let expr = self.parse_unary()?;
277                let unary = Expr::Unary {
278                    op: UnaryOp::Increment,
279                    expr,
280                };
281                Some(self.arena.alloc_expr(unary))
282            }
283            TokenKind::MinusMinus => {
284                self.bump();
285                let expr = self.parse_unary()?;
286                let unary = Expr::Unary {
287                    op: UnaryOp::Decrement,
288                    expr,
289                };
290                Some(self.arena.alloc_expr(unary))
291            }
292            TokenKind::LParen => {
293                self.bump();
294                if matches!(
295                    self.peek(),
296                    TokenKind::KwBoolean
297                        | TokenKind::KwByte
298                        | TokenKind::KwChar
299                        | TokenKind::KwShort
300                        | TokenKind::KwInt
301                        | TokenKind::KwLong
302                        | TokenKind::KwFloat
303                        | TokenKind::KwDouble
304                        | TokenKind::KwVoid
305                        | TokenKind::KwVar
306                ) {
307                    let ty = self.parse_type()?;
308                    self.expect(TokenKind::RParen);
309                    let expr = self.parse_unary()?;
310                    let cast = Expr::Cast { ty, expr };
311                    return Some(self.arena.alloc_expr(cast));
312                }
313
314                let expr = self.parse_expression()?;
315                self.expect(TokenKind::RParen);
316                Some(expr)
317            }
318            _ => self.parse_postfix(),
319        }
320    }
321
322    fn parse_postfix(&mut self) -> Option<ExprId> {
323        let mut expr = self.parse_primary()?;
324
325        loop {
326            match self.peek() {
327                TokenKind::Dot => {
328                    self.bump();
329                    if self.peek() == TokenKind::Ident {
330                        let name = Ident::new(self.ident_text());
331                        self.bump();
332
333                        if self.is(TokenKind::LParen) {
334                            // Method call
335                            self.bump();
336                            let args = self.parse_arguments();
337                            self.expect(TokenKind::RParen);
338
339                            let method_call = Expr::MethodCall {
340                                expr: Some(expr),
341                                name,
342                                type_args: None,
343                                args,
344                                method_id: None,
345                            };
346                            expr = self.arena.alloc_expr(method_call);
347                        } else {
348                            // Field access
349                            let field_access = Expr::FieldAccess {
350                                expr,
351                                name,
352                                field_id: None,
353                            };
354                            expr = self.arena.alloc_expr(field_access);
355                        }
356                    } else if self.peek() == TokenKind::KwClass {
357                        // .class literal
358                        self.bump();
359                        let length = Expr::ArrayLength { array: expr };
360                        expr = self.arena.alloc_expr(length);
361                    }
362                }
363                TokenKind::LBracket => {
364                    self.bump();
365                    let index = self.parse_expression()?;
366                    self.expect(TokenKind::RBracket);
367
368                    let array_access = Expr::ArrayAccess { array: expr, index };
369                    expr = self.arena.alloc_expr(array_access);
370                }
371                TokenKind::PlusPlus => {
372                    self.bump();
373                    let unary = Expr::Unary {
374                        op: UnaryOp::Increment,
375                        expr,
376                    };
377                    expr = self.arena.alloc_expr(unary);
378                }
379                TokenKind::MinusMinus => {
380                    self.bump();
381                    let unary = Expr::Unary {
382                        op: UnaryOp::Decrement,
383                        expr,
384                    };
385                    expr = self.arena.alloc_expr(unary);
386                }
387                _ => break,
388            }
389        }
390
391        Some(expr)
392    }
393
394    fn parse_primary(&mut self) -> Option<ExprId> {
395        match self.peek() {
396            TokenKind::IntLiteral | TokenKind::LongLiteral => {
397                let value = rajac_base::shared_string::SharedString::new(
398                    &self.source[self.current.span.clone()],
399                );
400                let kind = if matches!(self.peek(), TokenKind::LongLiteral) {
401                    LiteralKind::Long
402                } else {
403                    LiteralKind::Int
404                };
405                self.bump();
406                let lit = Literal { kind, value };
407                Some(self.arena.alloc_expr(Expr::Literal(lit)))
408            }
409            TokenKind::FloatLiteral => {
410                let value = rajac_base::shared_string::SharedString::new(
411                    &self.source[self.current.span.clone()],
412                );
413                self.bump();
414                let lit = Literal {
415                    kind: LiteralKind::Float,
416                    value,
417                };
418                Some(self.arena.alloc_expr(Expr::Literal(lit)))
419            }
420            TokenKind::DoubleLiteral => {
421                let value = rajac_base::shared_string::SharedString::new(
422                    &self.source[self.current.span.clone()],
423                );
424                self.bump();
425                let lit = Literal {
426                    kind: LiteralKind::Double,
427                    value,
428                };
429                Some(self.arena.alloc_expr(Expr::Literal(lit)))
430            }
431            TokenKind::StringLiteral => {
432                let raw_value = &self.source[self.current.span.clone()];
433                // Strip the surrounding quotes from string literal
434                let value = if raw_value.len() >= 2
435                    && raw_value.starts_with('"')
436                    && raw_value.ends_with('"')
437                {
438                    &raw_value[1..raw_value.len() - 1]
439                } else {
440                    raw_value
441                };
442                let value = rajac_base::shared_string::SharedString::new(value);
443                self.bump();
444                let lit = Literal {
445                    kind: LiteralKind::String,
446                    value,
447                };
448                Some(self.arena.alloc_expr(Expr::Literal(lit)))
449            }
450            TokenKind::CharLiteral => {
451                let value = rajac_base::shared_string::SharedString::new(
452                    &self.source[self.current.span.clone()],
453                );
454                self.bump();
455                let lit = Literal {
456                    kind: LiteralKind::Char,
457                    value,
458                };
459                Some(self.arena.alloc_expr(Expr::Literal(lit)))
460            }
461            TokenKind::KwTrue | TokenKind::KwFalse => {
462                let value = rajac_base::shared_string::SharedString::new(
463                    &self.source[self.current.span.clone()],
464                );
465                self.bump();
466                let lit = Literal {
467                    kind: LiteralKind::Bool,
468                    value,
469                };
470                Some(self.arena.alloc_expr(Expr::Literal(lit)))
471            }
472            TokenKind::NullLiteral => {
473                let value = rajac_base::shared_string::SharedString::new("null");
474                self.bump();
475                let lit = Literal {
476                    kind: LiteralKind::Null,
477                    value,
478                };
479                Some(self.arena.alloc_expr(Expr::Literal(lit)))
480            }
481            TokenKind::Ident => {
482                let name = Ident::new(self.ident_text());
483                self.bump();
484
485                if self.is(TokenKind::LParen) {
486                    // Method call without receiver
487                    self.bump();
488                    let args = self.parse_arguments();
489                    self.expect(TokenKind::RParen);
490
491                    let method_call = Expr::MethodCall {
492                        expr: None,
493                        name,
494                        type_args: None,
495                        args,
496                        method_id: None,
497                    };
498                    Some(self.arena.alloc_expr(method_call))
499                } else {
500                    // Just an identifier
501                    Some(self.arena.alloc_expr(Expr::Ident(name)))
502                }
503            }
504            TokenKind::KwThis => {
505                self.bump();
506                let expr = if self.is(TokenKind::LParen) {
507                    self.bump();
508                    Some(self.arena.alloc_expr(Expr::Ident(Ident::new(
509                        rajac_base::shared_string::SharedString::new("this"),
510                    ))))
511                } else {
512                    None
513                };
514                Some(self.arena.alloc_expr(Expr::This(expr)))
515            }
516            TokenKind::KwSuper => {
517                self.bump();
518                if self.is(TokenKind::LParen) {
519                    self.bump();
520                    let args = self.parse_arguments();
521                    self.expect(TokenKind::RParen);
522                    let super_call = Expr::SuperCall {
523                        name: Ident::new(rajac_base::shared_string::SharedString::new("super")),
524                        type_args: None,
525                        args,
526                        method_id: None,
527                    };
528                    Some(self.arena.alloc_expr(super_call))
529                } else {
530                    Some(self.arena.alloc_expr(Expr::Super))
531                }
532            }
533            TokenKind::KwNew => {
534                self.bump();
535                if let Some(ty) = self.parse_type_without_array_suffix() {
536                    if self.is(TokenKind::LBracket) {
537                        let mut dimensions = Vec::new();
538                        let mut empty_brackets = 0;
539                        while self.consume(TokenKind::LBracket) {
540                            if let Some(dim) = self.parse_expression() {
541                                dimensions.push(dim);
542                            } else {
543                                empty_brackets += 1;
544                            }
545                            self.expect(TokenKind::RBracket);
546                        }
547                        let ty = if empty_brackets > 0 {
548                            self.arena.alloc_type(AstType::array(ty, empty_brackets))
549                        } else {
550                            ty
551                        };
552                        let initializer = if self.is(TokenKind::LBrace) {
553                            self.parse_array_initializer_expr()
554                        } else {
555                            None
556                        };
557                        let new_array = Expr::NewArray {
558                            ty,
559                            dimensions,
560                            initializer,
561                        };
562                        Some(self.arena.alloc_expr(new_array))
563                    } else if self.is(TokenKind::LParen) {
564                        // Constructor call
565                        self.bump();
566                        let args = self.parse_arguments();
567                        self.expect(TokenKind::RParen);
568                        let new_expr = Expr::New { ty, args };
569                        Some(self.arena.alloc_expr(new_expr))
570                    } else {
571                        None
572                    }
573                } else {
574                    None
575                }
576            }
577            TokenKind::LParen => {
578                self.bump();
579                let expr = self.parse_expression()?;
580                self.expect(TokenKind::RParen);
581                Some(expr)
582            }
583            _ => None,
584        }
585    }
586
587    fn parse_array_initializer_expr(&mut self) -> Option<ExprId> {
588        if !self.consume(TokenKind::LBrace) {
589            return None;
590        }
591
592        let mut elements = Vec::new();
593        while !self.is(TokenKind::RBrace) && !self.is(TokenKind::Eof) {
594            let element = if self.is(TokenKind::LBrace) {
595                self.parse_array_initializer_expr()
596            } else {
597                self.parse_expression()
598            }?;
599            elements.push(element);
600
601            if !self.consume(TokenKind::Comma) {
602                break;
603            }
604            if self.is(TokenKind::RBrace) {
605                break;
606            }
607        }
608
609        self.expect(TokenKind::RBrace);
610        Some(self.arena.alloc_expr(Expr::ArrayInitializer { elements }))
611    }
612
613    fn parse_arguments(&mut self) -> Vec<ExprId> {
614        let mut args = Vec::new();
615
616        if self.is(TokenKind::RParen) {
617            return args;
618        }
619
620        loop {
621            if let Some(arg) = self.parse_expression() {
622                args.push(arg);
623            }
624            if !self.consume(TokenKind::Comma) {
625                break;
626            }
627        }
628
629        args
630    }
631
632    // Helper to check for assignment operators
633    pub fn parse_assignment(&mut self, expr: ExprId) -> Option<ExprId> {
634        let op = match self.peek() {
635            TokenKind::Eq => AssignOp::Eq,
636            TokenKind::PlusEq => AssignOp::AddEq,
637            TokenKind::MinusEq => AssignOp::SubEq,
638            TokenKind::StarEq => AssignOp::MulEq,
639            TokenKind::SlashEq => AssignOp::DivEq,
640            TokenKind::PercentEq => AssignOp::ModEq,
641            TokenKind::AmpersandEq => AssignOp::AndEq,
642            TokenKind::PipeEq => AssignOp::OrEq,
643            TokenKind::CaretEq => AssignOp::XorEq,
644            TokenKind::LtLtEq => AssignOp::LShiftEq,
645            TokenKind::GtGtEq => AssignOp::RShiftEq,
646            TokenKind::GtGtGtEq => AssignOp::ARShiftEq,
647            _ => return Some(expr),
648        };
649        self.bump();
650        let rhs = self.parse_ternary()?;
651        let assign = Expr::Assign { op, lhs: expr, rhs };
652        Some(self.arena.alloc_expr(assign))
653    }
654
655    // Check if next two tokens are || (logical OR)
656    fn is_or(&self) -> bool {
657        self.peek() == TokenKind::Or
658    }
659
660    // Check if next two tokens are && (logical AND)
661    fn is_and(&self) -> bool {
662        self.peek() == TokenKind::And
663    }
664}