Skip to main content

rajac_parser/
stmt.rs

1use crate::parser::Parser;
2use rajac_ast::*;
3use rajac_token::TokenKind;
4use rajac_types::Ident;
5
6impl<'a> Parser<'a> {
7    /// Parse a block of statements
8    pub fn parse_block(&mut self) -> Option<StmtId> {
9        if !self.consume(TokenKind::LBrace) {
10            return None;
11        }
12
13        let mut stmts = Vec::new();
14        while !self.is(TokenKind::RBrace) && !self.is(TokenKind::Eof) {
15            if let Some(stmt) = self.parse_statement() {
16                stmts.push(stmt);
17            } else {
18                break;
19            }
20        }
21
22        self.expect(TokenKind::RBrace);
23        let block = Stmt::Block(stmts);
24        Some(self.arena.alloc_stmt(block))
25    }
26
27    /// Parse a single statement
28    pub fn parse_statement(&mut self) -> Option<StmtId> {
29        match self.peek() {
30            TokenKind::LBrace => self.parse_block(),
31            TokenKind::Semi => {
32                self.bump();
33                Some(self.arena.alloc_stmt(Stmt::Empty))
34            }
35            TokenKind::KwIf => self.parse_if_stmt(),
36            TokenKind::KwWhile => self.parse_while_stmt(),
37            TokenKind::KwDo => self.parse_do_while_stmt(),
38            TokenKind::KwFor => self.parse_for_stmt(),
39            TokenKind::KwSwitch => self.parse_switch_stmt(),
40            TokenKind::KwReturn => self.parse_return_stmt(),
41            TokenKind::KwBreak => self.parse_break_stmt(),
42            TokenKind::KwContinue => self.parse_continue_stmt(),
43            TokenKind::KwThrow => self.parse_throw_stmt(),
44            TokenKind::KwTry => self.parse_try_stmt(),
45            TokenKind::KwSynchronized => self.parse_synchronized_stmt(),
46            // Type keywords indicate local variable declaration
47            TokenKind::KwBoolean
48            | TokenKind::KwByte
49            | TokenKind::KwChar
50            | TokenKind::KwShort
51            | TokenKind::KwInt
52            | TokenKind::KwLong
53            | TokenKind::KwFloat
54            | TokenKind::KwDouble
55            | TokenKind::KwVoid
56            | TokenKind::Ident => {
57                if self.peek() == TokenKind::Ident && self.peek_n(1) == TokenKind::Colon {
58                    return self.parse_label_stmt();
59                }
60
61                // Try to parse as local variable or expression statement
62                if self.is_local_var_decl() {
63                    self.parse_local_var_decl()
64                } else {
65                    self.parse_expr_stmt()
66                }
67            }
68            _ => {
69                // Try expression statement
70                if let Some(expr) = self.parse_expression() {
71                    self.expect(TokenKind::Semi);
72                    Some(self.arena.alloc_stmt(Stmt::Expr(expr)))
73                } else {
74                    None
75                }
76            }
77        }
78    }
79
80    fn is_local_var_decl(&self) -> bool {
81        matches!(
82            self.peek(),
83            TokenKind::KwBoolean
84                | TokenKind::KwByte
85                | TokenKind::KwChar
86                | TokenKind::KwShort
87                | TokenKind::KwInt
88                | TokenKind::KwLong
89                | TokenKind::KwFloat
90                | TokenKind::KwDouble
91                | TokenKind::KwVoid
92                | TokenKind::KwVar
93        )
94    }
95
96    fn parse_local_var_decl(&mut self) -> Option<StmtId> {
97        if let Some(ty) = self.parse_type()
98            && self.peek() == TokenKind::Ident
99        {
100            let name = Ident::new(self.ident_text());
101            self.bump();
102
103            let initializer = if self.consume(TokenKind::Eq) {
104                self.parse_expression()
105            } else {
106                None
107            };
108
109            self.expect(TokenKind::Semi);
110
111            let stmt = Stmt::LocalVar {
112                ty,
113                name,
114                initializer,
115            };
116            return Some(self.arena.alloc_stmt(stmt));
117        }
118        None
119    }
120
121    fn parse_expr_stmt(&mut self) -> Option<StmtId> {
122        if let Some(expr) = self.parse_expression() {
123            self.expect(TokenKind::Semi);
124            Some(self.arena.alloc_stmt(Stmt::Expr(expr)))
125        } else {
126            None
127        }
128    }
129
130    fn parse_if_stmt(&mut self) -> Option<StmtId> {
131        self.expect(TokenKind::KwIf);
132        self.expect(TokenKind::LParen);
133        let condition = self.parse_expression()?;
134        self.expect(TokenKind::RParen);
135
136        let then_branch = self.parse_statement()?;
137
138        let else_branch = if self.consume(TokenKind::KwElse) {
139            self.parse_statement()
140        } else {
141            None
142        };
143
144        let stmt = Stmt::If {
145            condition,
146            then_branch,
147            else_branch,
148        };
149        Some(self.arena.alloc_stmt(stmt))
150    }
151
152    fn parse_while_stmt(&mut self) -> Option<StmtId> {
153        self.expect(TokenKind::KwWhile);
154        self.expect(TokenKind::LParen);
155        let condition = self.parse_expression()?;
156        self.expect(TokenKind::RParen);
157
158        let body = self.parse_statement()?;
159
160        let stmt = Stmt::While { condition, body };
161        Some(self.arena.alloc_stmt(stmt))
162    }
163
164    fn parse_do_while_stmt(&mut self) -> Option<StmtId> {
165        self.expect(TokenKind::KwDo);
166        let body = self.parse_statement()?;
167        self.expect(TokenKind::KwWhile);
168        self.expect(TokenKind::LParen);
169        let condition = self.parse_expression()?;
170        self.expect(TokenKind::RParen);
171        self.expect(TokenKind::Semi);
172
173        let stmt = Stmt::DoWhile { body, condition };
174        Some(self.arena.alloc_stmt(stmt))
175    }
176
177    fn parse_for_stmt(&mut self) -> Option<StmtId> {
178        self.expect(TokenKind::KwFor);
179        self.expect(TokenKind::LParen);
180
181        let init = if self.is(TokenKind::Semi) {
182            None
183        } else if self.is_local_var_decl() {
184            let ty = self.parse_type()?;
185            let name = if self.peek() == TokenKind::Ident {
186                Ident::new(self.ident_text())
187            } else {
188                return None;
189            };
190            self.bump();
191
192            let initializer = if self.consume(TokenKind::Eq) {
193                self.parse_expression()
194            } else {
195                None
196            };
197
198            Some(ForInit::LocalVar {
199                ty,
200                name,
201                initializer,
202            })
203        } else {
204            self.parse_expression().map(ForInit::Expr)
205        };
206
207        self.expect(TokenKind::Semi);
208
209        let condition = if self.is(TokenKind::Semi) {
210            None
211        } else {
212            self.parse_expression()
213        };
214
215        self.expect(TokenKind::Semi);
216
217        let update = if self.is(TokenKind::RParen) {
218            None
219        } else {
220            self.parse_expression()
221        };
222
223        self.expect(TokenKind::RParen);
224
225        let body = self.parse_statement()?;
226
227        let stmt = Stmt::For {
228            init,
229            condition,
230            update,
231            body,
232        };
233        Some(self.arena.alloc_stmt(stmt))
234    }
235
236    fn parse_switch_stmt(&mut self) -> Option<StmtId> {
237        self.expect(TokenKind::KwSwitch);
238        self.expect(TokenKind::LParen);
239        let expr = self.parse_expression()?;
240        self.expect(TokenKind::RParen);
241
242        self.expect(TokenKind::LBrace);
243
244        let mut cases = Vec::new();
245        while !self.is(TokenKind::RBrace) && !self.is(TokenKind::Eof) {
246            match self.peek() {
247                TokenKind::KwCase => {
248                    self.bump();
249                    if let Some(case_expr) = self.parse_expression() {
250                        self.expect(TokenKind::Colon);
251                        let label = SwitchLabel::Case(case_expr);
252
253                        let mut body = Vec::new();
254                        while !self.is(TokenKind::KwCase)
255                            && !self.is(TokenKind::KwDefault)
256                            && !self.is(TokenKind::RBrace)
257                        {
258                            if let Some(stmt) = self.parse_statement() {
259                                body.push(stmt);
260                            } else {
261                                break;
262                            }
263                        }
264
265                        cases.push(SwitchCase {
266                            labels: vec![label],
267                            body,
268                        });
269                    }
270                }
271                TokenKind::KwDefault => {
272                    self.bump();
273                    self.expect(TokenKind::Colon);
274
275                    let mut body = Vec::new();
276                    while !self.is(TokenKind::KwCase)
277                        && !self.is(TokenKind::KwDefault)
278                        && !self.is(TokenKind::RBrace)
279                    {
280                        if let Some(stmt) = self.parse_statement() {
281                            body.push(stmt);
282                        } else {
283                            break;
284                        }
285                    }
286
287                    cases.push(SwitchCase {
288                        labels: vec![SwitchLabel::Default],
289                        body,
290                    });
291                }
292                _ => break,
293            }
294        }
295
296        self.expect(TokenKind::RBrace);
297
298        let stmt = Stmt::Switch { expr, cases };
299        Some(self.arena.alloc_stmt(stmt))
300    }
301
302    fn parse_label_stmt(&mut self) -> Option<StmtId> {
303        let name = if self.peek() == TokenKind::Ident {
304            Ident::new(self.ident_text())
305        } else {
306            return None;
307        };
308        self.bump();
309        self.expect(TokenKind::Colon);
310        let body = self.parse_statement()?;
311
312        Some(self.arena.alloc_stmt(Stmt::Label(name, body)))
313    }
314
315    fn parse_return_stmt(&mut self) -> Option<StmtId> {
316        self.expect(TokenKind::KwReturn);
317        let expr = if self.is(TokenKind::Semi) {
318            None
319        } else {
320            self.parse_expression()
321        };
322        self.expect(TokenKind::Semi);
323
324        let stmt = Stmt::Return(expr);
325        Some(self.arena.alloc_stmt(stmt))
326    }
327
328    fn parse_break_stmt(&mut self) -> Option<StmtId> {
329        self.expect(TokenKind::KwBreak);
330        let label = if self.peek() == TokenKind::Ident && !self.is(TokenKind::Semi) {
331            Some(Ident::new(self.ident_text()))
332        } else {
333            None
334        };
335        if label.is_some() {
336            self.bump();
337        }
338        self.expect(TokenKind::Semi);
339
340        let stmt = Stmt::Break(label);
341        Some(self.arena.alloc_stmt(stmt))
342    }
343
344    fn parse_continue_stmt(&mut self) -> Option<StmtId> {
345        self.expect(TokenKind::KwContinue);
346        let label = if self.peek() == TokenKind::Ident && !self.is(TokenKind::Semi) {
347            Some(Ident::new(self.ident_text()))
348        } else {
349            None
350        };
351        if label.is_some() {
352            self.bump();
353        }
354        self.expect(TokenKind::Semi);
355
356        let stmt = Stmt::Continue(label);
357        Some(self.arena.alloc_stmt(stmt))
358    }
359
360    fn parse_throw_stmt(&mut self) -> Option<StmtId> {
361        self.expect(TokenKind::KwThrow);
362        let expr = self.parse_expression()?;
363        self.expect(TokenKind::Semi);
364
365        let stmt = Stmt::Throw(expr);
366        Some(self.arena.alloc_stmt(stmt))
367    }
368
369    fn parse_try_stmt(&mut self) -> Option<StmtId> {
370        self.expect(TokenKind::KwTry);
371
372        let try_block = self.parse_block()?;
373
374        let mut catches = Vec::new();
375        while self.is(TokenKind::KwCatch) {
376            self.bump();
377            self.expect(TokenKind::LParen);
378
379            let ty = self.parse_type()?;
380            let name = if self.peek() == TokenKind::Ident {
381                Ident::new(self.ident_text())
382            } else {
383                Ident::new(rajac_base::shared_string::SharedString::new("e"))
384            };
385            self.bump();
386
387            self.expect(TokenKind::RParen);
388
389            let body = self.parse_block()?;
390
391            catches.push(CatchClause {
392                param: self.arena.alloc_param(Param {
393                    ty,
394                    name,
395                    varargs: false,
396                }),
397                body,
398            });
399        }
400
401        let finally_block = if self.consume(TokenKind::KwFinally) {
402            self.parse_block()
403        } else {
404            None
405        };
406
407        let stmt = Stmt::Try {
408            try_block,
409            catches,
410            finally_block,
411        };
412        Some(self.arena.alloc_stmt(stmt))
413    }
414
415    fn parse_synchronized_stmt(&mut self) -> Option<StmtId> {
416        self.expect(TokenKind::KwSynchronized);
417
418        let expr = if self.consume(TokenKind::LParen) {
419            let e = self.parse_expression();
420            self.expect(TokenKind::RParen);
421            e
422        } else {
423            None
424        };
425
426        let block = self.parse_block()?;
427
428        let stmt = Stmt::Synchronized { expr, block };
429        Some(self.arena.alloc_stmt(stmt))
430    }
431}