seraphine_core/
parser.rs

1use crate::{
2    common::Pos,
3    error::{OperatorKind, ParseError},
4    tokenizer::{Keyword, Operator, Token, TokenKind},
5};
6
7#[derive(Debug, Clone)]
8pub enum Ast {
9    Lines(Vec<Ast>),
10    Null,
11    NumberLiteral(f64),
12    BooleanLiteral(bool),
13    StringLiteral(String),
14    ListLiteral(Vec<Ast>),
15    ObjectLiteral(Vec<(String, Ast)>),
16    Variable(String),
17    Add(Box<Ast>, Box<Ast>),
18    Subtract(Box<Ast>, Box<Ast>),
19    Multiply(Box<Ast>, Box<Ast>),
20    Divide(Box<Ast>, Box<Ast>),
21    Modulo(Box<Ast>, Box<Ast>),
22    Power(Box<Ast>, Box<Ast>),
23    UnaryMinus(Box<Ast>),
24    BooleanNegate(Box<Ast>),
25    Equality(Box<Ast>, Box<Ast>),
26    Inequality(Box<Ast>, Box<Ast>),
27    LessThan(Box<Ast>, Box<Ast>),
28    GreaterThan(Box<Ast>, Box<Ast>),
29    LessThanOrEqual(Box<Ast>, Box<Ast>),
30    GreaterThanOrEqual(Box<Ast>, Box<Ast>),
31    And(Box<Ast>, Box<Ast>),
32    Or(Box<Ast>, Box<Ast>),
33    Brackets(Box<Ast>),
34    Assign(String, Box<Ast>),
35    IndexingAssign {
36        value: Box<Ast>,
37        index: Box<Ast>,
38        rhs: Box<Ast>,
39    },
40    MemberAssign {
41        value: Box<Ast>,
42        member: String,
43        rhs: Box<Ast>,
44    },
45    FunctionCall {
46        value: Box<Ast>,
47        args: Vec<Ast>,
48    },
49    FunctionDefinition {
50        name: String,
51        arg_names: Vec<String>,
52        body: Box<Ast>,
53    },
54    UnnamedFunction {
55        arg_names: Vec<String>,
56        body: Box<Ast>,
57    },
58    MemberAccess {
59        value: Box<Ast>,
60        member: String,
61    },
62    Indexing {
63        value: Box<Ast>,
64        index: Box<Ast>,
65    },
66    IfStatement {
67        condition: Box<Ast>,
68        if_body: Box<Ast>,
69        else_body: Option<Box<Ast>>,
70    },
71    WhileLoop {
72        condition: Box<Ast>,
73        body: Box<Ast>,
74    },
75    ForLoop {
76        variable: String,
77        iterable: Box<Ast>,
78        body: Box<Ast>,
79    },
80    Continue,
81    Break,
82    Return(Option<Box<Ast>>),
83}
84
85/// Returns the precedence of the operator.
86///
87/// Higher precedence means that the operator is calculated first (e.g. multiplication has higher
88/// precedence than addition).
89/// `is_binary` provides information about the operator being used as a
90/// unary or binary operator (i.e. if `is_binary` is false, the operator is unary).
91fn op_precedence(op: Operator, is_binary: bool, op_pos: Pos) -> Result<u8, ParseError> {
92    let precedence = match (op, is_binary) {
93        (Operator::Or, true) => 1,
94        (Operator::And, true) => 2,
95        (
96            Operator::Equal
97            | Operator::Unequal
98            | Operator::LessThan
99            | Operator::GreaterThan
100            | Operator::LessThanOrEqual
101            | Operator::GreaterThanOrEqual,
102            true,
103        ) => 3,
104        (Operator::Plus | Operator::Minus, true) => 4,
105        (Operator::Star | Operator::Slash | Operator::Percent, true) => 5,
106        (Operator::Caret, true) => 6,
107        (Operator::Minus | Operator::Exclamation, false) => 7,
108        _ => {
109            let kind = if is_binary {
110                OperatorKind::Binary
111            } else {
112                OperatorKind::Unary
113            };
114            return Err(ParseError::InvalidOperator {
115                op,
116                kind,
117                pos: op_pos,
118            });
119        }
120    };
121
122    Ok(precedence)
123}
124
125fn combine_lhs_rhs(op: Operator, lhs: Ast, rhs: Ast) -> Result<Ast, ParseError> {
126    let combined = match op {
127        Operator::Plus => Ast::Add(Box::new(lhs), Box::new(rhs)),
128        Operator::Minus => Ast::Subtract(Box::new(lhs), Box::new(rhs)),
129        Operator::Star => Ast::Multiply(Box::new(lhs), Box::new(rhs)),
130        Operator::Slash => Ast::Divide(Box::new(lhs), Box::new(rhs)),
131        Operator::Percent => Ast::Modulo(Box::new(lhs), Box::new(rhs)),
132        Operator::Caret => Ast::Power(Box::new(lhs), Box::new(rhs)),
133        Operator::Equal => Ast::Equality(Box::new(lhs), Box::new(rhs)),
134        Operator::Unequal => Ast::Inequality(Box::new(lhs), Box::new(rhs)),
135        Operator::LessThan => Ast::LessThan(Box::new(lhs), Box::new(rhs)),
136        Operator::GreaterThan => Ast::GreaterThan(Box::new(lhs), Box::new(rhs)),
137        Operator::LessThanOrEqual => Ast::LessThanOrEqual(Box::new(lhs), Box::new(rhs)),
138        Operator::GreaterThanOrEqual => Ast::GreaterThanOrEqual(Box::new(lhs), Box::new(rhs)),
139        Operator::And => Ast::And(Box::new(lhs), Box::new(rhs)),
140        Operator::Or => Ast::Or(Box::new(lhs), Box::new(rhs)),
141        Operator::Exclamation => unreachable!(),
142    };
143    Ok(combined)
144}
145
146pub fn parse(tokens: &[Token]) -> Result<Ast, ParseError> {
147    Parser::new(tokens).parse()
148}
149
150struct Parser<'a> {
151    tokens: &'a [Token],
152    idx: usize,
153}
154
155impl<'a> Parser<'a> {
156    fn new(tokens: &'a [Token]) -> Self {
157        Parser { tokens, idx: 0 }
158    }
159
160    /// Entrypoint to the parser
161    fn parse(&mut self) -> Result<Ast, ParseError> {
162        let ast = self.parse_block()?;
163        // If some function stopped parsing for some reason and we haven't parsed all tokens, the
164        // token at the current position is unexpected.
165        //
166        // For example: A `}`, where the function stops parsing to let the caller decide whether
167        // the token makes sense at this place.
168        if self.idx < self.tokens.len() {
169            return Err(ParseError::UnexpectedToken {
170                token: self.tokens[self.idx].clone(),
171                expected: None,
172            });
173        }
174        Ok(ast)
175    }
176
177    fn parse_block(&mut self) -> Result<Ast, ParseError> {
178        let mut lines = Vec::new();
179        let mut want_newline_this_iteration = false;
180        while let Some(token) = self.peek() {
181            let (line, want_newline_next_iteration) = match &token.kind {
182                TokenKind::Eof | TokenKind::Newline => {
183                    self.next();
184                    (None, false)
185                }
186                TokenKind::RBrace => break,
187                // All following constructs can only appear at the beginning of a line
188                _ if want_newline_this_iteration => {
189                    return Err(ParseError::UnexpectedToken {
190                        token: token.clone(),
191                        expected: Some(TokenKind::Newline),
192                    });
193                }
194                TokenKind::Keyword(Keyword::Fn)
195                    if matches!(
196                        self.peek_next_non_newline_from_offset(2),
197                        Some(Token {
198                            kind: TokenKind::Identifier(_),
199                            ..
200                        })
201                    ) =>
202                {
203                    (Some(self.parse_function_definition(true)?), true)
204                }
205                TokenKind::Keyword(Keyword::If) => (Some(self.parse_if_statement()?), true),
206                TokenKind::Keyword(Keyword::While) => (Some(self.parse_while_loop()?), true),
207                TokenKind::Keyword(Keyword::For) => (Some(self.parse_for_loop()?), true),
208                TokenKind::Keyword(Keyword::Continue) => {
209                    self.next();
210                    (Some(Ast::Continue), true)
211                }
212                TokenKind::Keyword(Keyword::Break) => {
213                    self.next();
214                    (Some(Ast::Break), true)
215                }
216                TokenKind::Keyword(Keyword::Return) => (Some(self.parse_return()?), true),
217                _ => (Some(self.parse_expression_or_assignment()?), true),
218            };
219
220            if let Some(token) = line {
221                lines.push(token);
222            }
223
224            want_newline_this_iteration = want_newline_next_iteration;
225        }
226        Ok(Ast::Lines(lines))
227    }
228
229    fn parse_expression_or_assignment(&mut self) -> Result<Ast, ParseError> {
230        let is_potential_assignment = matches!(self.peek_kind(), Some(TokenKind::Identifier(_)));
231        let lhs = self.parse_expression()?;
232        if is_potential_assignment && self.peek_next_non_newline_kind() == Some(&TokenKind::Equal) {
233            match lhs {
234                Ast::Variable(var) => {
235                    self.skip_newlines();
236                    self.next();
237                    self.skip_newlines();
238                    let rhs = self.parse_expression()?;
239                    return Ok(Ast::Assign(var, Box::new(rhs)));
240                }
241                Ast::Indexing { value, index } => {
242                    self.skip_newlines();
243                    self.next();
244                    self.skip_newlines();
245                    let rhs = self.parse_expression()?;
246                    return Ok(Ast::IndexingAssign {
247                        value,
248                        index,
249                        rhs: Box::new(rhs),
250                    });
251                }
252                Ast::MemberAccess { value, member } => {
253                    self.skip_newlines();
254                    self.next();
255                    self.skip_newlines();
256                    let rhs = self.parse_expression()?;
257                    return Ok(Ast::MemberAssign {
258                        value,
259                        member,
260                        rhs: Box::new(rhs),
261                    });
262                }
263                _ => {}
264            }
265        }
266
267        Ok(lhs)
268    }
269
270    /// Parses an expression.
271    ///
272    /// This works by calling a helper function that parses a part of an expression. Once that
273    /// helper function returned the AST of the expression snipper, this function reads the next
274    /// operator and creates a new AST node. The currently parsed AST becomes the left hand side of
275    /// the new node and the right hand side is once again determined by the helper function.
276    fn parse_expression(&mut self) -> Result<Ast, ParseError> {
277        let mut lhs = self.parse_expression_with_min_precedence(0)?;
278        while let Some(Token {
279            kind: TokenKind::Operator(op),
280            pos,
281        }) = self.peek_next_non_newline()
282        {
283            let op = *op;
284            let pos = *pos;
285            self.skip_newlines();
286            self.next();
287            self.skip_newlines();
288            let precedence = op_precedence(op, true, pos)?;
289            let rhs = self.parse_expression_with_min_precedence(precedence + 1)?;
290            lhs = combine_lhs_rhs(op, lhs, rhs)?;
291        }
292        Ok(lhs)
293    }
294
295    /// Helper function for [`Self::parse_expression`] that parses an expression that includes all
296    /// operators with a precedence equal to or higher than `min_precedence`. This means that it
297    /// takes all operators until it sees an operator of lower precedence than `min_precedence`.
298    ///
299    /// When this function meets an operator with a precedence that is equal to or higher than
300    /// `min_precedence`, it calls itself again. The recursive call accepts only operators that
301    /// have higher predence than the current one. This is done until an operator of lower
302    /// precedence is found. In that case the function returns the AST that it parsed so far and
303    /// walks up the recursive call stack until that operator's precedence is equal to or higher
304    /// than `min_precedence`. The returned AST is then used as the left hand side for that
305    /// operator. The right hand side is once again determined by this function as was already
306    /// explained.
307    ///
308    /// ## Example
309    ///
310    /// Calling the function with the input `1 + 2 ^ 3 * 4` and a `min_precedence` of `0` would
311    /// result in the following AST:
312    ///
313    /// ```notest
314    ///              +
315    ///            1         *
316    ///                  ^     4
317    ///                2   3
318    /// ```
319    ///
320    /// Or in another notation: `Add(1, Multiply(Power(2, 3), 4)`
321    fn parse_expression_with_min_precedence(
322        &mut self,
323        min_precedence: u8,
324    ) -> Result<Ast, ParseError> {
325        match self.peek() {
326            Some(token) => {
327                match token.kind {
328                    TokenKind::Operator(Operator::Minus) => {
329                        let pos = token.pos;
330                        self.next();
331                        self.skip_newlines();
332                        let unary_minus_precedence = op_precedence(Operator::Minus, false, pos)?;
333                        // Not `+ 1` like in the other cases so we can take multiple unary minus operators
334                        // after each other
335                        let rhs =
336                            self.parse_expression_with_min_precedence(unary_minus_precedence)?;
337                        Ok(Ast::UnaryMinus(Box::new(rhs)))
338                    }
339                    TokenKind::Operator(Operator::Exclamation) => {
340                        let pos = token.pos;
341                        self.next();
342                        self.skip_newlines();
343                        let boolean_negate_precedence =
344                            op_precedence(Operator::Exclamation, false, pos)?;
345                        // Not `+ 1` like in the other cases so we can take multiple boolean negate operators
346                        // after each other
347                        let rhs =
348                            self.parse_expression_with_min_precedence(boolean_negate_precedence)?;
349                        Ok(Ast::BooleanNegate(Box::new(rhs)))
350                    }
351                    TokenKind::LParen
352                    | TokenKind::LBrace
353                    | TokenKind::LBracket
354                    | TokenKind::Identifier(_)
355                    | TokenKind::Number(_)
356                    | TokenKind::String(_)
357                    | TokenKind::Keyword(Keyword::True | Keyword::False)
358                    | TokenKind::Keyword(Keyword::Null)
359                    | TokenKind::Keyword(Keyword::Fn) => {
360                        let mut lhs = self.parse_identifier_or_value()?;
361                        while let Some(Token {
362                            kind: TokenKind::Operator(op),
363                            pos,
364                        }) = self.peek_next_non_newline()
365                        {
366                            let op = *op;
367                            let precedence = op_precedence(op, true, *pos)?;
368                            if precedence >= min_precedence {
369                                self.skip_newlines();
370                                self.next();
371                                self.skip_newlines();
372                                let rhs =
373                                    self.parse_expression_with_min_precedence(precedence + 1)?;
374                                lhs = combine_lhs_rhs(op, lhs, rhs)?;
375                            } else {
376                                break;
377                            }
378                        }
379                        Ok(lhs)
380                    }
381                    _ => Err(ParseError::UnexpectedToken {
382                        token: token.clone(),
383                        expected: None,
384                    }),
385                }
386            }
387            None => Err(ParseError::NoTokensLeft),
388        }
389    }
390
391    fn parse_identifier_or_value(&mut self) -> Result<Ast, ParseError> {
392        let mut ast = match self.next() {
393            Some(token) => match &token.kind {
394                TokenKind::LParen => {
395                    self.skip_newlines();
396                    let inner = self.parse_expression()?;
397                    self.skip_newlines();
398                    self.expect(TokenKind::RParen)?;
399                    Ast::Brackets(Box::new(inner))
400                }
401                TokenKind::LBrace => {
402                    // We match on `self.next()`, but the parse function expects the `{` token
403                    self.idx -= 1;
404                    self.parse_object_literal()?
405                }
406                TokenKind::LBracket => {
407                    // We match on `self.next()`, but the parse function expects the `[` token
408                    self.idx -= 1;
409                    self.parse_list_literal()?
410                }
411                TokenKind::Identifier(name) => Ast::Variable(name.clone()),
412                TokenKind::Number(num) => Ast::NumberLiteral(*num),
413                TokenKind::String(str) => Ast::StringLiteral(str.clone()),
414                TokenKind::Keyword(Keyword::True) => Ast::BooleanLiteral(true),
415                TokenKind::Keyword(Keyword::False) => Ast::BooleanLiteral(false),
416                TokenKind::Keyword(Keyword::Null) => Ast::Null,
417                TokenKind::Keyword(Keyword::Fn) => {
418                    // We match on `self.next()`, but the parse function expects the `fn` keyword
419                    self.idx -= 1;
420                    self.parse_function_definition(false)?
421                }
422                _ => {
423                    return Err(ParseError::UnexpectedToken {
424                        token: token.clone(),
425                        expected: None,
426                    })
427                }
428            },
429            None => return Err(ParseError::NoTokensLeft),
430        };
431        loop {
432            // Don't allow newlines before LParen and LBracket to avoid confusion with expressions
433            // in the next non-empty line.
434            match self.peek_kind() {
435                Some(TokenKind::LParen) => {
436                    ast = self.parse_function_call(ast)?;
437                }
438                Some(TokenKind::LBracket) => {
439                    ast = self.parse_indexing(ast)?;
440                }
441                _ if self.peek_next_non_newline_kind() == Some(&TokenKind::Dot) => {
442                    self.skip_newlines();
443                    self.next();
444                    self.skip_newlines();
445                    let member = self.expect_identifier()?;
446                    ast = Ast::MemberAccess {
447                        value: Box::new(ast),
448                        member: member.to_string(),
449                    };
450                }
451                _ => break,
452            }
453        }
454        Ok(ast)
455    }
456
457    fn parse_function_call(&mut self, called_value: Ast) -> Result<Ast, ParseError> {
458        // <value>(<val1>, <val2>, ...)
459        self.expect(TokenKind::LParen)?;
460        self.skip_newlines();
461        let mut args = Vec::new();
462        while self.peek_kind() != Some(&TokenKind::RParen) {
463            let arg = self.parse_expression()?;
464            args.push(arg);
465            self.skip_newlines();
466
467            if self.peek_kind() != Some(&TokenKind::Comma) {
468                break;
469            }
470
471            self.next();
472            self.skip_newlines();
473        }
474        self.expect(TokenKind::RParen)?;
475        Ok(Ast::FunctionCall {
476            value: Box::new(called_value),
477            args,
478        })
479    }
480
481    fn parse_indexing(&mut self, value: Ast) -> Result<Ast, ParseError> {
482        // <value>[<index>]
483        self.expect(TokenKind::LBracket)?;
484        self.skip_newlines();
485        let index = self.parse_expression()?;
486        self.skip_newlines();
487        self.expect(TokenKind::RBracket)?;
488        Ok(Ast::Indexing {
489            value: Box::new(value),
490            index: Box::new(index),
491        })
492    }
493
494    fn parse_object_literal(&mut self) -> Result<Ast, ParseError> {
495        // { <key1>[: <val1> | <unnamed_function_definition_without_fn>], ... }
496        self.expect(TokenKind::LBrace)?;
497        let mut key_value_pairs = Vec::new();
498        while self.peek_kind() != Some(&TokenKind::RBrace) {
499            self.skip_newlines();
500            let key = self.expect_identifier()?.to_string();
501            self.skip_newlines();
502            let value = match self.peek() {
503                Some(Token {
504                    kind: TokenKind::Colon,
505                    ..
506                }) => {
507                    self.next();
508                    self.skip_newlines();
509                    self.parse_expression()?
510                }
511                Some(Token {
512                    kind: TokenKind::LParen,
513                    ..
514                }) => self.parse_function_definition_without_fn(false)?,
515                Some(Token {
516                    kind: TokenKind::Comma | TokenKind::RBrace,
517                    ..
518                }) => Ast::Variable(key.clone()),
519                Some(t) => {
520                    return Err(ParseError::UnexpectedToken {
521                        token: t.clone(),
522                        expected: Some(TokenKind::Colon),
523                    })
524                }
525                None => return Err(ParseError::NoTokensLeft),
526            };
527            key_value_pairs.push((key, value));
528
529            self.skip_newlines();
530            if self.peek_kind() != Some(&TokenKind::Comma) {
531                break;
532            }
533
534            self.next();
535            self.skip_newlines();
536        }
537        self.expect(TokenKind::RBrace)?;
538        Ok(Ast::ObjectLiteral(key_value_pairs))
539    }
540
541    fn parse_list_literal(&mut self) -> Result<Ast, ParseError> {
542        // [ <val1>, <val2>, ... ]
543        self.expect(TokenKind::LBracket)?;
544        self.skip_newlines();
545        let mut values = Vec::new();
546        while self.peek_kind() != Some(&TokenKind::RBracket) {
547            let value = self.parse_expression()?;
548            values.push(value);
549            self.skip_newlines();
550
551            if self.peek_kind() != Some(&TokenKind::Comma) {
552                break;
553            }
554
555            self.next();
556            self.skip_newlines();
557        }
558        self.expect(TokenKind::RBracket)?;
559        Ok(Ast::ListLiteral(values))
560    }
561
562    fn parse_function_definition(&mut self, named: bool) -> Result<Ast, ParseError> {
563        // fn <function_definition_without_fn>
564        self.expect(TokenKind::Keyword(Keyword::Fn))?;
565        self.skip_newlines();
566        self.parse_function_definition_without_fn(named)
567    }
568
569    fn parse_function_definition_without_fn(&mut self, named: bool) -> Result<Ast, ParseError> {
570        // [ <name> ] (<arg1>, <arg2>, ...) { <body> }
571        let fn_name = if named {
572            let ident = self.expect_identifier()?.to_string();
573            self.skip_newlines();
574            Some(ident)
575        } else {
576            None
577        };
578        self.expect(TokenKind::LParen)?;
579        self.skip_newlines();
580
581        let mut arg_names = Vec::new();
582        while let Some(TokenKind::Identifier(arg_name)) = self.peek_kind() {
583            arg_names.push(arg_name.to_string());
584            self.next();
585            self.skip_newlines();
586
587            if self.peek_kind() != Some(&TokenKind::Comma) {
588                break;
589            }
590
591            self.next();
592            self.skip_newlines();
593        }
594
595        self.expect(TokenKind::RParen)?;
596        self.skip_newlines();
597        self.expect(TokenKind::LBrace)?;
598        let body = self.parse_block()?;
599        self.expect(TokenKind::RBrace)?;
600
601        if let Some(name) = fn_name {
602            Ok(Ast::FunctionDefinition {
603                name,
604                arg_names,
605                body: Box::new(body),
606            })
607        } else {
608            Ok(Ast::UnnamedFunction {
609                arg_names,
610                body: Box::new(body),
611            })
612        }
613    }
614
615    fn parse_if_statement(&mut self) -> Result<Ast, ParseError> {
616        // if ( <expr> ) { <body> } [ else if ( <expr> ) { <body> } [ ... ] ] [ else { <body> } ]
617        self.expect(TokenKind::Keyword(Keyword::If))?;
618        self.skip_newlines();
619        self.expect(TokenKind::LParen)?;
620        self.skip_newlines();
621        let condition = self.parse_expression()?;
622        self.skip_newlines();
623        self.expect(TokenKind::RParen)?;
624        self.skip_newlines();
625        self.expect(TokenKind::LBrace)?;
626        let if_body = self.parse_block()?;
627        self.skip_newlines();
628        self.expect(TokenKind::RBrace)?;
629
630        let else_body = if self.peek_next_non_newline().map(|t| &t.kind)
631            == Some(&TokenKind::Keyword(Keyword::Else))
632        {
633            self.skip_newlines();
634            self.next();
635            if self.peek_kind() == Some(&TokenKind::Keyword(Keyword::If)) {
636                let else_if_statement = self.parse_if_statement()?;
637                Some(Box::new(else_if_statement))
638            } else {
639                self.skip_newlines();
640                self.expect(TokenKind::LBrace)?;
641                let else_body = self.parse_block()?;
642                self.skip_newlines();
643                self.expect(TokenKind::RBrace)?;
644                Some(Box::new(else_body))
645            }
646        } else {
647            None
648        };
649
650        Ok(Ast::IfStatement {
651            condition: Box::new(condition),
652            if_body: Box::new(if_body),
653            else_body,
654        })
655    }
656
657    fn parse_while_loop(&mut self) -> Result<Ast, ParseError> {
658        // while ( <expr> ) { <body> }
659        self.expect(TokenKind::Keyword(Keyword::While))?;
660        self.skip_newlines();
661        self.expect(TokenKind::LParen)?;
662        self.skip_newlines();
663        let condition = self.parse_expression()?;
664        self.skip_newlines();
665        self.expect(TokenKind::RParen)?;
666        self.skip_newlines();
667
668        self.expect(TokenKind::LBrace)?;
669        let body = self.parse_block()?;
670        self.expect(TokenKind::RBrace)?;
671
672        Ok(Ast::WhileLoop {
673            condition: Box::new(condition),
674            body: Box::new(body),
675        })
676    }
677
678    fn parse_for_loop(&mut self) -> Result<Ast, ParseError> {
679        // for ( <name> in <expr> ) { <body> }
680        self.expect(TokenKind::Keyword(Keyword::For))?;
681        self.skip_newlines();
682        self.expect(TokenKind::LParen)?;
683        self.skip_newlines();
684        let variable = self.expect_identifier()?.to_string();
685        self.skip_newlines();
686        self.expect(TokenKind::Keyword(Keyword::In))?;
687        self.skip_newlines();
688        let iterable = self.parse_expression()?;
689        self.skip_newlines();
690        self.expect(TokenKind::RParen)?;
691        self.skip_newlines();
692
693        self.expect(TokenKind::LBrace)?;
694        let body = self.parse_block()?;
695        self.expect(TokenKind::RBrace)?;
696
697        Ok(Ast::ForLoop {
698            variable,
699            iterable: Box::new(iterable),
700            body: Box::new(body),
701        })
702    }
703
704    fn parse_return(&mut self) -> Result<Ast, ParseError> {
705        // return [ <expr> ]
706        self.expect(TokenKind::Keyword(Keyword::Return))?;
707        let expr = match self.peek_kind() {
708            Some(&TokenKind::Newline | &TokenKind::RBrace) => None,
709            _ => Some(Box::new(self.parse_expression()?)),
710        };
711        Ok(Ast::Return(expr))
712    }
713
714    /// Takes the next token, behaving like `next` of an iterator.
715    fn next(&mut self) -> Option<&Token> {
716        let token = self.tokens.get(self.idx);
717        self.idx += 1;
718        token
719    }
720
721    /// Peeks the nth token.
722    ///
723    /// Peek with n = 1 behaves like `peek` of an iterator, peeking the next available token.
724    fn peek_nth(&self, n: usize) -> Option<&Token> {
725        self.tokens.get(self.idx + n - 1)
726    }
727
728    /// Peeks the next token, behaving like `peek` of an iterator.
729    fn peek(&self) -> Option<&Token> {
730        self.peek_nth(1)
731    }
732
733    /// Peeks the kind of the nth token.
734    fn peek_nth_kind(&self, n: usize) -> Option<&TokenKind> {
735        self.peek_nth(n).map(|t| &t.kind)
736    }
737
738    /// Peeks the kind of the next token.
739    fn peek_kind(&self) -> Option<&TokenKind> {
740        self.peek_nth_kind(1)
741    }
742
743    /// Peeks the next token that isn't a newline.
744    ///
745    /// [`Self::skip_newlines`] and [`Self::next`] can be used to advance the position to the next non-newline
746    /// token.
747    fn peek_next_non_newline(&self) -> Option<&Token> {
748        self.peek_next_non_newline_from_offset(1)
749    }
750
751    /// Peeks the kind of the next token that isn't a newline.
752    ///
753    /// See [`Self::peek_next_non_newline`].
754    fn peek_next_non_newline_kind(&self) -> Option<&TokenKind> {
755        self.peek_next_non_newline_from_offset(1).map(|t| &t.kind)
756    }
757
758    /// Peeks the next token that isn't a newline from one-based offset of `offset`.
759    ///
760    /// `offset` must be greater than or equal to 1.
761    fn peek_next_non_newline_from_offset(&self, offset: usize) -> Option<&Token> {
762        let mut peek_idx = offset.max(1);
763        while let Some(TokenKind::Newline) = self.peek_nth_kind(peek_idx) {
764            peek_idx += 1;
765        }
766
767        self.peek_nth(peek_idx)
768    }
769
770    /// Asserts that `expected` is the next token, while also advancing the position.
771    fn expect(&mut self, expected: TokenKind) -> Result<(), ParseError> {
772        match self.next() {
773            Some(actual) => {
774                if actual.kind != expected {
775                    Err(ParseError::UnexpectedToken {
776                        token: actual.clone(),
777                        expected: Some(expected),
778                    })
779                } else {
780                    Ok(())
781                }
782            }
783            None => Err(ParseError::NoTokensLeft),
784        }
785    }
786
787    /// Asserts that the next token is an identifier, returning the inner string slice of the
788    /// identifier and advancing the position.
789    fn expect_identifier(&mut self) -> Result<&str, ParseError> {
790        match self.next() {
791            Some(Token {
792                kind: TokenKind::Identifier(ref name),
793                ..
794            }) => Ok(name),
795            Some(Token { pos, .. }) => Err(ParseError::ExpectedIdentifier { pos: *pos }),
796            None => Err(ParseError::NoTokensLeft),
797        }
798    }
799
800    /// Advanced the position until the next token is not a newline.
801    fn skip_newlines(&mut self) {
802        while self.peek_kind() == Some(&TokenKind::Newline) {
803            self.next();
804        }
805    }
806}