Skip to main content

rl_lang/parser/expressions/
struct_literal.rs

1//! Record (struct) literal parser: `Name { field: value, ... }`.
2//!
3//! Called from [`crate::parser::expressions::primary`] once a plain
4//! identifier is recognized as a previously-declared record name and is
5//! immediately followed by `{`.
6
7use crate::{
8    ast::{ExprId, nodes::ExpressionKind},
9    lexer::tokentypes::TokenType,
10    parser::parser_logic::Parser,
11    utils::{errors::Error, span::Span},
12};
13
14impl Parser {
15    /// Parses the body of a struct literal after `Name` has already been
16    /// consumed. `start` is the span of the beginning of the `Name` token.
17    pub fn parse_struct_literal(&mut self, name: String, start: Span) -> Result<ExprId, Error> {
18        // consume `{`
19        self.advance();
20        while self.match_type(&[TokenType::Newline]) {}
21
22        let mut fields = Vec::new();
23        while self.peek() != TokenType::RightBrace {
24            let field_name = match self.peek() {
25                TokenType::Identifier(n) => {
26                    self.advance();
27                    n
28                }
29                _ => return Err(self.err("expected field name", self.peek_span())),
30            };
31            while self.match_type(&[TokenType::Newline]) {}
32            if !self.match_type(&[TokenType::Colon]) {
33                return Err(self.err("expected `:` after field name", self.peek_span()));
34            }
35            while self.match_type(&[TokenType::Newline]) {}
36            let value = self.parse_expression()?;
37            fields.push((field_name, value));
38
39            while self.match_type(&[TokenType::Newline]) {}
40            if self.peek() == TokenType::RightBrace {
41                break;
42            }
43            if !self.match_type(&[TokenType::Comma]) {
44                return Err(self.err(
45                    "expected `,` between struct literal fields",
46                    self.peek_span(),
47                ));
48            }
49            while self.match_type(&[TokenType::Newline]) {}
50        }
51
52        if !self.match_type(&[TokenType::RightBrace]) {
53            return Err(self.err("expected `}` after struct literal", self.peek_span()));
54        }
55
56        let span = start.join(self.previous_span());
57        let expr = self
58            .ast_arena
59            .alloc_expr(ExpressionKind::StructLiteral { name, fields }, span);
60        self.parse_postfix(expr, start)
61    }
62}