roan_ast/parser/
statements.rs

1use crate::{
2    Block, ElseBlock, FnParam, FunctionType, ParseContext, Parser, Stmt, StructField, Token,
3    TokenKind, TypeAnnotation,
4};
5use anyhow::Result;
6use colored::Colorize;
7use roan_error::error::RoanError::{
8    ExpectedToken, InvalidType, MultipleRestParameters, MultipleSelfParameters,
9    RestParameterNotLastPosition, SelfParameterCannotBeRest, SelfParameterNotFirst,
10};
11use tracing::debug;
12
13static VALID_TYPE_NAMES: [&str; 8] = [
14    "bool", "int", "float", "string", "void", "anytype", "char", "object",
15];
16
17impl Parser {
18    /// Parses a statement from the tokens.
19    ///
20    /// This method checks the type of token to determine the kind of statement it should create.
21    /// It supports function declarations, variable assignments, control flow, and more.
22    ///
23    /// # Returns
24    /// - `Ok(Some(Stmt))`: A parsed statement.
25    /// - `Ok(None)`: If the token is a comment or semicolon.
26    /// - `Err`: If there is a parsing error.
27    pub fn parse_stmt(&mut self) -> Result<Option<Stmt>> {
28        let token = self.peek();
29
30        let stmt = match token.kind {
31            TokenKind::Pub => {
32                if self.peek_next().kind == TokenKind::Fn {
33                    Some(self.parse_fn()?)
34                } else if self.peek_next().kind == TokenKind::Struct {
35                    Some(self.parse_struct()?)
36                } else if self.peek_next().kind == TokenKind::Trait {
37                    Some(self.parse_trait()?)
38                } else if self.peek_next().kind == TokenKind::Const {
39                    Some(self.parse_const()?)
40                } else {
41                    // TODO: return error
42                    None
43                }
44            }
45            TokenKind::Fn => Some(self.parse_fn()?),
46            TokenKind::Struct => Some(self.parse_struct()?),
47            TokenKind::Trait => Some(self.parse_trait()?),
48            TokenKind::Const => Some(self.parse_const()?),
49            TokenKind::Impl => {
50                let impl_keyword = self.consume();
51                if self.peek().kind == TokenKind::Identifier {
52                    let ident = self.consume();
53
54                    if self.peek().kind == TokenKind::For {
55                        Some(self.parse_trait_impl(impl_keyword, ident)?)
56                    } else if self.peek().kind == TokenKind::LeftBrace {
57                        Some(self.parse_impl(impl_keyword, ident)?)
58                    } else {
59                        None
60                    }
61                } else {
62                    None
63                }
64            }
65            TokenKind::Use => Some(self.parse_use()?),
66            TokenKind::If => Some(self.parse_if()?),
67            TokenKind::Let => Some(self.parse_let()?),
68            TokenKind::Throw => Some(self.parse_throw()?),
69            TokenKind::Try => Some(self.parse_try()?),
70            TokenKind::Break => {
71                self.consume();
72                self.possible_check(TokenKind::Semicolon);
73                Some(Stmt::new_break(token))
74            }
75            TokenKind::Continue => {
76                self.consume();
77                self.possible_check(TokenKind::Semicolon);
78                Some(Stmt::new_continue(token))
79            }
80            TokenKind::Loop => {
81                self.consume();
82                let block = self.parse_block()?;
83                Some(Stmt::new_loop(token, block))
84            }
85            TokenKind::While => self.parse_while()?,
86            TokenKind::LeftBrace => {
87                self.consume();
88                let block = self.parse_block()?;
89                self.expect(TokenKind::RightBrace)?;
90                Some(Stmt::Block(block))
91            }
92            TokenKind::Return => self.parse_return()?,
93            TokenKind::Semicolon | TokenKind::Comment => {
94                self.consume();
95                None
96            }
97            _ => Some(self.expression_stmt()?),
98        };
99
100        Ok(stmt)
101    }
102
103    /// Parses an `impl` block for implementing a struct.
104    ///
105    /// An `impl` block is used to implement methods for a struct.
106    ///
107    /// # Returns
108    /// - `Ok(Stmt)`: An impl block.
109    /// - `Err`: If there is a parsing error.
110    pub fn parse_impl(&mut self, impl_keyword: Token, ident: Token) -> Result<Stmt> {
111        debug!("Parsing impl block");
112        self.expect(TokenKind::LeftBrace)?;
113
114        let mut methods: Vec<crate::Fn> = vec![];
115
116        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
117            let func = self.parse_fn()?.into_function();
118
119            methods.push(func);
120        }
121
122        self.expect(TokenKind::RightBrace)?;
123
124        Ok(Stmt::new_struct_impl(impl_keyword, ident, methods))
125    }
126
127    /// Parses an `impl` block for implementing a trait.
128    ///
129    /// An `impl` block is used to implement methods for a trait.
130    ///
131    /// # Returns
132    /// - `Ok(Stmt)`: An impl block.
133    /// - `Err`: If there is a parsing error.
134    pub fn parse_trait_impl(&mut self, impl_keyword: Token, ident: Token) -> Result<Stmt> {
135        debug!("Parsing impl block");
136        let for_token = self.expect(TokenKind::For)?;
137
138        let trait_name = self.expect(TokenKind::Identifier)?;
139
140        self.expect(TokenKind::LeftBrace)?;
141
142        let mut methods: Vec<crate::Fn> = vec![];
143
144        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
145            let func = self.parse_fn()?.into_function();
146
147            methods.push(func);
148        }
149
150        self.expect(TokenKind::RightBrace)?;
151
152        Ok(Stmt::new_trait_impl(
153            impl_keyword,
154            ident,
155            for_token,
156            trait_name,
157            methods,
158        ))
159    }
160
161    /// Parses a 'pub' keyword (if present) followed by an identifier.
162    pub fn parse_pub(&mut self, expected: TokenKind) -> Result<(Token, bool)> {
163        let mut public = false;
164        let token = if self.peek().kind == TokenKind::Pub {
165            self.consume();
166            public = true;
167            self.consume()
168        } else {
169            self.consume()
170        };
171
172        Ok((token, public))
173    }
174
175    /// Parses a `trait` declaration.
176    ///
177    /// A `trait` declaration defines a new interface that can be implemented by other types.
178    ///
179    /// # Returns
180    /// - `Ok(Stmt)`: A trait declaration.
181    /// - `Err`: If there is a parsing error.
182    pub fn parse_trait(&mut self) -> Result<Stmt> {
183        debug!("Parsing trait");
184        let (trait_token, public) = self.parse_pub(TokenKind::Trait)?;
185
186        let name = self.expect(TokenKind::Identifier)?;
187
188        self.expect(TokenKind::LeftBrace)?;
189
190        let mut methods: Vec<crate::Fn> = vec![];
191
192        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
193            let func = self.parse_fn()?.into_function();
194            methods.push(func);
195        }
196
197        self.expect(TokenKind::RightBrace)?;
198
199        Ok(Stmt::new_trait_def(trait_token, name, methods, public))
200    }
201
202    /// Parses an expression statement.
203    ///
204    /// An expression statement is a statement that consists of an expression followed by a semicolon.
205    ///
206    /// # Returns
207    ///
208    /// - `Stmt`: An expression statement.
209    /// - `Err`: If there is a parsing error.
210    pub fn parse_const(&mut self) -> Result<Stmt> {
211        debug!("Parsing const");
212        let (_, public) = self.parse_pub(TokenKind::Const)?;
213
214        let name = self.expect(TokenKind::Identifier)?;
215
216        self.expect(TokenKind::Equals)?;
217
218        let expr = self.parse_expr()?;
219
220        Ok(Stmt::new_const(Box::new(expr), name, public))
221    }
222
223    /// Parses a `struct` declaration.
224    ///
225    /// A `struct` declaration defines a new data structure with named fields.
226    ///
227    /// # Returns
228    /// - `Ok(Stmt)`: A struct declaration.
229    /// - `Err`: If there is a parsing error.
230    pub fn parse_struct(&mut self) -> Result<Stmt> {
231        debug!("Parsing struct");
232        let (struct_token, public) = self.parse_pub(TokenKind::Struct)?;
233        let name = self.expect(TokenKind::Identifier)?;
234
235        self.expect(TokenKind::LeftBrace)?;
236
237        let mut fields: Vec<StructField> = vec![];
238
239        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
240            let ident = self.expect(TokenKind::Identifier)?;
241            let type_annotation = self.parse_type_annotation()?;
242            fields.push(StructField {
243                ident,
244                type_annotation,
245            });
246
247            if self.peek().kind != TokenKind::RightBrace {
248                self.expect(TokenKind::Comma)?;
249            }
250        }
251
252        self.expect(TokenKind::RightBrace)?;
253
254        Ok(Stmt::new_struct(struct_token, name, fields, public))
255    }
256
257    /// Parses a `while` statement.
258    ///
259    /// A `while` statement is used to execute a block of code repeatedly as long as a condition is true.
260    ///
261    /// # Returns
262    /// - `Ok(Stmt)`: A while statement.
263    /// - `Err`: If there is a parsing error.
264    pub fn parse_while(&mut self) -> Result<Option<Stmt>> {
265        debug!("Parsing while statement");
266        let while_token = self.consume();
267
268        self.push_context(ParseContext::WhileCondition);
269        let condition = self.parse_expr()?;
270        self.pop_context();
271
272        self.expect(TokenKind::LeftBrace)?;
273        let block = self.parse_block()?;
274        self.expect(TokenKind::RightBrace)?;
275
276        Ok(Some(Stmt::new_while(while_token, condition, block)))
277    }
278
279    /// Parses a `throw` statement.
280    ///
281    /// A `throw` statement is used to raise an exception.
282    ///
283    /// # Returns
284    /// - `Ok(Stmt)`: A throw statement.
285    /// - `Err`: If there is a parsing error.
286    pub fn parse_throw(&mut self) -> Result<Stmt> {
287        debug!("Parsing throw statement");
288        let throw_token = self.consume();
289        let value = self.parse_expr()?;
290
291        self.possible_check(TokenKind::Semicolon);
292
293        Ok(Stmt::new_throw(throw_token, value))
294    }
295
296    /// Parses a `try` statement with a `catch` block.
297    ///
298    /// The `try` statement lets you catch exceptions and handle errors in a safe way.
299    ///
300    /// # Returns
301    /// - `Ok(Stmt)`: A try-catch statement.
302    /// - `Err`: If there is a parsing error.
303    pub fn parse_try(&mut self) -> Result<Stmt> {
304        debug!("Parsing try statement");
305        let try_token = self.consume();
306
307        self.expect(TokenKind::LeftBrace)?;
308        let try_block = self.parse_block()?;
309        self.expect(TokenKind::RightBrace)?;
310
311        self.expect(TokenKind::Catch)?;
312
313        let error_ident = self.expect(TokenKind::Identifier)?;
314
315        self.expect(TokenKind::LeftBrace)?;
316        let catch_block = self.parse_block()?;
317        self.expect(TokenKind::RightBrace)?;
318
319        Ok(Stmt::new_try(
320            try_token,
321            try_block,
322            error_ident,
323            catch_block,
324        ))
325    }
326
327    /// Parses a `return` statement.
328    ///
329    /// The `return` statement is used to return a value from a function.
330    ///
331    /// # Returns
332    /// - `Ok(Some(Stmt))`: A return statement with or without a value.
333    /// - `Err`: If there is a parsing error.
334    pub fn parse_return(&mut self) -> Result<Option<Stmt>> {
335        debug!("Parsing return statement");
336        let return_token = self.consume();
337        let value = if self.peek().kind != TokenKind::Semicolon {
338            Some(Box::new(self.parse_expr()?))
339        } else {
340            None
341        };
342
343        self.possible_check(TokenKind::Semicolon);
344
345        Ok(Some(Stmt::new_return(return_token, value)))
346    }
347
348    /// Parses a `let` statement.
349    ///
350    /// A `let` statement declares a new variable with an optional type annotation.
351    ///
352    /// # Returns
353    /// - `Ok(Stmt)`: A variable declaration statement.
354    /// - `Err`: If there is a parsing error.
355    pub fn parse_let(&mut self) -> Result<Stmt> {
356        debug!("Parsing let statement");
357        self.expect(TokenKind::Let)?;
358        let ident = self.expect(TokenKind::Identifier)?;
359        let type_annotation = self.parse_optional_type_annotation()?;
360        self.expect(TokenKind::Equals)?;
361        let value = self.parse_expr()?;
362        Ok(Stmt::new_let(ident, Box::new(value), type_annotation))
363    }
364
365    /// Parses an `if` statement with optional `else if` and `else` blocks.
366    ///
367    /// An `if` statement is used for conditional logic.
368    ///
369    /// # Returns
370    /// - `Ok(Stmt)`: An if statement with possible elseif and else blocks.
371    /// - `Err`: If there is a parsing error.
372    pub fn parse_if(&mut self) -> Result<Stmt> {
373        debug!("Parsing if statement");
374        let if_token = self.consume();
375
376        self.push_context(ParseContext::IfCondition);
377
378        let condition = self.parse_expr()?;
379
380        self.pop_context();
381
382        self.expect(TokenKind::LeftBrace)?;
383
384        let body = self.parse_block()?;
385        self.expect(TokenKind::RightBrace)?;
386
387        let mut elseif_blocks = vec![];
388        let mut else_block: Option<ElseBlock> = None;
389
390        while self.peek().kind == TokenKind::Else {
391            self.consume();
392
393            if self.peek().kind == TokenKind::If {
394                self.consume();
395                self.possible_check(TokenKind::LeftParen);
396
397                self.push_context(ParseContext::IfCondition);
398                let elseif_condition = self.parse_expr()?;
399                self.pop_context();
400
401                self.possible_check(TokenKind::RightParen);
402
403                self.expect(TokenKind::LeftBrace)?;
404                let elseif_body = self.parse_block()?;
405                self.expect(TokenKind::RightBrace)?;
406
407                elseif_blocks.push(ElseBlock {
408                    condition: Box::new(elseif_condition),
409                    block: elseif_body,
410                    else_if: true,
411                });
412            } else {
413                self.expect(TokenKind::LeftBrace)?;
414                let else_body = self.parse_block()?;
415                self.expect(TokenKind::RightBrace)?;
416
417                else_block = Some(ElseBlock {
418                    condition: Box::new(condition.clone()),
419                    block: else_body,
420                    else_if: false,
421                });
422            }
423        }
424
425        Ok(Stmt::new_if(
426            if_token,
427            condition.into(),
428            body,
429            elseif_blocks.into(),
430            else_block,
431        ))
432    }
433
434    /// Parses a `use` statement for importing modules.
435    ///
436    /// A `use` statement allows importing items from other modules or files.
437    ///
438    /// # Returns
439    /// - `Ok(Stmt)`: A use statement.
440    /// - `Err`: If there is a parsing error.
441    pub fn parse_use(&mut self) -> Result<Stmt> {
442        debug!("Parsing use statement");
443        let use_token = self.consume();
444
445        let mut items = vec![];
446
447        self.expect(TokenKind::LeftBrace)?;
448
449        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
450            let item = self.expect(TokenKind::Identifier)?;
451
452            if self.peek().kind != TokenKind::RightBrace {
453                self.expect(TokenKind::Comma)?;
454            }
455
456            items.push(item);
457        }
458
459        self.expect(TokenKind::RightBrace)?;
460
461        self.expect(TokenKind::From)?;
462
463        let from = if self.peek().is_string() {
464            self.consume()
465        } else {
466            return Err(ExpectedToken(
467                "string".to_string(),
468                "Expected string that is valid module or file".to_string(),
469                self.peek().span.clone(),
470            )
471            .into());
472        };
473
474        Ok(Stmt::new_use(use_token, from, items))
475    }
476
477    /// Checks if the next token is a question mark and consumes it.
478    pub fn is_nullable(&mut self) -> bool {
479        if self.peek().kind == TokenKind::QuestionMark {
480            self.consume();
481            true
482        } else {
483            false
484        }
485    }
486
487    /// Helper method to parse a type with optional array and nullability.
488    fn parse_type(&mut self) -> Result<(Token, bool)> {
489        let type_name = self.expect(TokenKind::Identifier)?;
490        Parser::validate_type_name(type_name.clone())?;
491
492        let is_array = if self.peek().kind == TokenKind::LeftBracket {
493            self.consume();
494            self.expect(TokenKind::RightBracket)?;
495            true
496        } else {
497            false
498        };
499
500        Ok((type_name, is_array))
501    }
502
503    /// Parses a type annotation following a variable or parameter.
504    ///
505    /// # Returns
506    /// - `Ok(TypeAnnotation)`: A parsed type annotation.
507    /// - `Err`: If there is a parsing error.
508    pub fn parse_type_annotation(&mut self) -> Result<TypeAnnotation> {
509        debug!("Parsing type annotation");
510        let colon = self.expect(TokenKind::Colon)?;
511        let (type_name, is_array) = self.parse_type()?;
512
513        Ok(TypeAnnotation {
514            type_name,
515            is_array,
516            is_nullable: self.is_nullable(),
517            colon,
518        })
519    }
520
521    /// Parses the return type of function.
522    ///
523    /// # Returns
524    /// - `Ok(Some(FunctionType))`: If the return type is parsed.
525    /// - `Ok(None)`: If no return type is provided.
526    /// - `Err`: If the syntax is incorrect.
527    pub fn parse_return_type(&mut self) -> Result<Option<FunctionType>> {
528        debug!("Parsing return type");
529
530        if self.peek().kind != TokenKind::Arrow {
531            return Ok(None);
532        }
533
534        let arrow = self.consume(); // consume the arrow
535        let (type_name, is_array) = self.parse_type()?;
536
537        Ok(Some(FunctionType {
538            type_name,
539            is_array,
540            is_nullable: self.is_nullable(),
541            arrow,
542        }))
543    }
544
545    /// Validates if the provided string is valid type name.
546    ///
547    /// # Returns
548    /// - `Ok(())`: If the type name is valid.
549    /// - `Err`: If the type name is invalid.
550    pub fn validate_type_name(token: Token) -> Result<()> {
551        let name = token.literal();
552
553        debug!("Validating type name: {}", name);
554
555        if !VALID_TYPE_NAMES.contains(&&*name) {
556            debug!("Invalid type name: {}", name);
557            return Err(InvalidType(
558                name.cyan().to_string(),
559                VALID_TYPE_NAMES.join(", "),
560                token.span.clone(),
561            )
562            .into());
563        }
564
565        Ok(())
566    }
567
568    /// Parses a block of statements enclosed by curly braces `{}`.
569    ///
570    /// A block is a group of statements that are executed in sequence.
571    ///
572    /// # Returns
573    /// - `Ok(Block)`: A parsed block of statements.
574    /// - `Err`: If there is a parsing error.
575    pub fn parse_block(&mut self) -> Result<Block> {
576        debug!("Parsing block");
577        let mut stmts = vec![];
578
579        while self.peek().kind != TokenKind::RightBrace && !self.is_eof() {
580            let stmt = self.parse_stmt()?;
581
582            if let Some(stmt) = stmt {
583                debug!("Adding statement to block");
584                stmts.push(stmt);
585            }
586        }
587
588        Ok(Block { stmts })
589    }
590
591    /// Parses a function declaration.
592    ///
593    /// A function declaration defines a new function, including its parameters, return type, and body.
594    ///
595    /// # Returns
596    /// - `Ok(Stmt)`: A function declaration.
597    /// - `Err`: If there is a parsing error.
598    pub fn parse_fn(&mut self) -> Result<Stmt> {
599        debug!("Parsing function");
600        self.possible_check(TokenKind::Comment);
601
602        let (fn_token, public) = self.parse_pub(TokenKind::Fn)?;
603
604        let name = self.expect(TokenKind::Identifier)?;
605
606        self.expect(TokenKind::LeftParen)?;
607        let mut params = vec![];
608
609        let mut has_rest_param = false;
610        let mut is_static = true;
611
612        if self.peek().kind != TokenKind::RightParen {
613            while self.peek().kind != TokenKind::RightParen && !self.is_eof() {
614                self.possible_check(TokenKind::Comma);
615
616                let is_rest = self.peek().kind == TokenKind::TripleDot;
617
618                if is_rest {
619                    if has_rest_param {
620                        return Err(MultipleRestParameters(self.peek().span.clone()).into());
621                    }
622                    has_rest_param = true;
623                    self.consume();
624                }
625
626                let param = self.consume();
627
628                if param.literal() == "self" {
629                    if !is_static {
630                        return Err(MultipleSelfParameters(self.peek().span.clone()).into());
631                    }
632
633                    is_static = false;
634
635                    if is_rest {
636                        return Err(SelfParameterCannotBeRest(self.peek().span.clone()).into());
637                    }
638                }
639
640                let type_annotation = self.parse_optional_type_annotation()?;
641
642                if has_rest_param && self.peek().kind != TokenKind::RightParen {
643                    return Err(RestParameterNotLastPosition(param.span.clone()).into());
644                }
645
646                params.push(FnParam {
647                    type_annotation,
648                    ident: param,
649                    is_rest,
650                });
651            }
652        }
653
654        if !is_static && params[0].ident.literal() != "self" {
655            return Err(SelfParameterNotFirst(self.peek().span.clone()).into());
656        }
657
658        self.expect(TokenKind::RightParen)?;
659
660        let return_type = self.parse_return_type()?;
661
662        let mut body = Block { stmts: vec![] };
663        if self.peek().kind != TokenKind::LeftBrace {
664            self.expect(TokenKind::Semicolon)?;
665        } else {
666            self.expect(TokenKind::LeftBrace)?;
667            body = self.parse_block()?;
668            self.expect(TokenKind::RightBrace)?;
669        }
670
671        Ok(Stmt::new_fn(
672            fn_token,
673            name.literal(),
674            params,
675            body,
676            public,
677            return_type,
678            is_static,
679        ))
680    }
681}