leo_parser/parser/
expression.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use super::*;
18use leo_errors::{ParserError, Result};
19
20use leo_span::sym;
21use snarkvm::console::{account::Address, network::Network};
22
23const INT_TYPES: &[Token] = &[
24    Token::I8,
25    Token::I16,
26    Token::I32,
27    Token::I64,
28    Token::I128,
29    Token::U8,
30    Token::U16,
31    Token::U32,
32    Token::U64,
33    Token::U128,
34    Token::Field,
35    Token::Group,
36    Token::Scalar,
37];
38
39impl<N: Network> ParserContext<'_, N> {
40    /// Returns an [`Expression`] AST node if the next token is an expression.
41    /// Includes struct init expressions.
42    pub(crate) fn parse_expression(&mut self) -> Result<Expression> {
43        // Store current parser state.
44        let prior_fuzzy_state = self.disallow_struct_construction;
45
46        // Allow struct init expressions.
47        self.disallow_struct_construction = false;
48
49        // Parse expression.
50        let result = self.parse_conditional_expression();
51
52        // Restore prior parser state.
53        self.disallow_struct_construction = prior_fuzzy_state;
54
55        result
56    }
57
58    /// Returns an [`Expression`] AST node if the next tokens represent
59    /// a ternary expression. May or may not include struct init expressions.
60    ///
61    /// Otherwise, tries to parse the next token using [`parse_boolean_or_expression`].
62    pub(super) fn parse_conditional_expression(&mut self) -> Result<Expression> {
63        // Try to parse the next expression. Try BinaryOperation::Or.
64        let mut expr = self.parse_boolean_or_expression()?;
65
66        // Parse the rest of the ternary expression.
67        if self.eat(&Token::Question) {
68            let if_true = self.parse_expression()?;
69            self.expect(&Token::Colon)?;
70            let if_false = self.parse_expression()?;
71            expr = TernaryExpression {
72                span: expr.span() + if_false.span(),
73                condition: expr,
74                if_true,
75                if_false,
76                id: self.node_builder.next_id(),
77            }
78            .into();
79        }
80        Ok(expr)
81    }
82
83    /// Constructs a binary expression `left op right`.
84    fn bin_expr(node_builder: &NodeBuilder, left: Expression, right: Expression, op: BinaryOperation) -> Expression {
85        BinaryExpression { span: left.span() + right.span(), op, left, right, id: node_builder.next_id() }.into()
86    }
87
88    /// Parses a left-associative binary expression `<left> token <right>` using `f` for left/right.
89    /// The `token` is translated to `op` in the AST.
90    fn parse_bin_expr(
91        &mut self,
92        tokens: &[Token],
93        mut f: impl FnMut(&mut Self) -> Result<Expression>,
94    ) -> Result<Expression> {
95        let mut expr = f(self)?;
96        while let Some(op) = self.eat_bin_op(tokens) {
97            expr = Self::bin_expr(self.node_builder, expr, f(self)?, op);
98        }
99        Ok(expr)
100    }
101
102    /// Returns an [`Expression`] AST node if the next tokens represent
103    /// a binary OR expression.
104    ///
105    /// Otherwise, tries to parse the next token using [`parse_boolean_and_expression`].
106    fn parse_boolean_or_expression(&mut self) -> Result<Expression> {
107        self.parse_bin_expr(&[Token::Or], Self::parse_boolean_and_expression)
108    }
109
110    /// Returns an [`Expression`] AST node if the next tokens represent a
111    /// binary AND expression.
112    ///
113    /// Otherwise, tries to parse the next token using [`parse_equality_expression`].
114    fn parse_boolean_and_expression(&mut self) -> Result<Expression> {
115        self.parse_bin_expr(&[Token::And], Self::parse_equality_expression)
116    }
117
118    fn eat_unary_op(&mut self) -> Option<UnaryOperation> {
119        self.eat_any(&[Token::Not, Token::Sub]).then(|| match &self.prev_token.token {
120            Token::Not => UnaryOperation::Not,
121            Token::Sub => UnaryOperation::Negate,
122            _ => panic!("Can't happen."),
123        })
124    }
125
126    /// Eats one of binary operators matching any in `tokens`.
127    fn eat_bin_op(&mut self, tokens: &[Token]) -> Option<BinaryOperation> {
128        self.eat_any(tokens).then(|| match &self.prev_token.token {
129            Token::Eq => BinaryOperation::Eq,
130            Token::NotEq => BinaryOperation::Neq,
131            Token::Lt => BinaryOperation::Lt,
132            Token::LtEq => BinaryOperation::Lte,
133            Token::Gt => BinaryOperation::Gt,
134            Token::GtEq => BinaryOperation::Gte,
135            Token::Add => BinaryOperation::Add,
136            Token::Sub => BinaryOperation::Sub,
137            Token::Mul => BinaryOperation::Mul,
138            Token::Div => BinaryOperation::Div,
139            Token::Rem => BinaryOperation::Rem,
140            Token::Or => BinaryOperation::Or,
141            Token::And => BinaryOperation::And,
142            Token::BitOr => BinaryOperation::BitwiseOr,
143            Token::BitAnd => BinaryOperation::BitwiseAnd,
144            Token::Pow => BinaryOperation::Pow,
145            Token::Shl => BinaryOperation::Shl,
146            Token::Shr => BinaryOperation::Shr,
147            Token::BitXor => BinaryOperation::Xor,
148            _ => unreachable!("`eat_bin_op` shouldn't produce this"),
149        })
150    }
151
152    /// Returns an [`Expression`] AST node if the next tokens represent a
153    /// binary relational expression: less than, less than or equals, greater than, greater than or equals.
154    ///
155    /// Otherwise, tries to parse the next token using [`parse_additive_expression`].
156    fn parse_ordering_expression(&mut self) -> Result<Expression> {
157        let mut expr = self.parse_bitwise_exclusive_or_expression()?;
158        if let Some(op) = self.eat_bin_op(&[Token::Lt, Token::LtEq, Token::Gt, Token::GtEq]) {
159            let right = self.parse_bitwise_exclusive_or_expression()?;
160            expr = Self::bin_expr(self.node_builder, expr, right, op);
161        }
162        Ok(expr)
163    }
164
165    /// Returns an [`Expression`] AST node if the next tokens represent a
166    /// binary equals or not equals expression.
167    ///
168    /// Otherwise, tries to parse the next token using [`parse_ordering_expression`].
169    fn parse_equality_expression(&mut self) -> Result<Expression> {
170        let mut expr = self.parse_ordering_expression()?;
171        if let Some(op) = self.eat_bin_op(&[Token::Eq, Token::NotEq]) {
172            let right = self.parse_ordering_expression()?;
173            expr = Self::bin_expr(self.node_builder, expr, right, op);
174        }
175        Ok(expr)
176    }
177
178    /// Returns an [`Expression`] AST node if the next tokens represent a
179    /// bitwise exclusive or expression.
180    ///
181    /// Otherwise, tries to parse the next token using [`parse_bitwise_inclusive_or_expression`].
182    fn parse_bitwise_exclusive_or_expression(&mut self) -> Result<Expression> {
183        self.parse_bin_expr(&[Token::BitXor], Self::parse_bitwise_inclusive_or_expression)
184    }
185
186    /// Returns an [`Expression`] AST node if the next tokens represent a
187    /// bitwise inclusive or expression.
188    ///
189    /// Otherwise, tries to parse the next token using [`parse_bitwise_and_expression`].
190    fn parse_bitwise_inclusive_or_expression(&mut self) -> Result<Expression> {
191        self.parse_bin_expr(&[Token::BitOr], Self::parse_bitwise_and_expression)
192    }
193
194    /// Returns an [`Expression`] AST node if the next tokens represent a
195    /// bitwise and expression.
196    ///
197    /// Otherwise, tries to parse the next token using [`parse_shift_expression`].
198    fn parse_bitwise_and_expression(&mut self) -> Result<Expression> {
199        self.parse_bin_expr(&[Token::BitAnd], Self::parse_shift_expression)
200    }
201
202    /// Returns an [`Expression`] AST node if the next tokens represent a
203    /// shift left or a shift right expression.
204    ///
205    /// Otherwise, tries to parse the next token using [`parse_additive_expression`].
206    fn parse_shift_expression(&mut self) -> Result<Expression> {
207        self.parse_bin_expr(&[Token::Shl, Token::Shr], Self::parse_additive_expression)
208    }
209
210    /// Returns an [`Expression`] AST node if the next tokens represent a
211    /// binary addition or subtraction expression.
212    ///
213    /// Otherwise, tries to parse the next token using [`parse_mul_div_pow_expression`].
214    fn parse_additive_expression(&mut self) -> Result<Expression> {
215        self.parse_bin_expr(&[Token::Add, Token::Sub], Self::parse_multiplicative_expression)
216    }
217
218    /// Returns an [`Expression`] AST node if the next tokens represent a
219    /// binary multiplication, division, or a remainder expression.
220    ///
221    /// Otherwise, tries to parse the next token using [`parse_exponential_expression`].
222    fn parse_multiplicative_expression(&mut self) -> Result<Expression> {
223        self.parse_bin_expr(&[Token::Mul, Token::Div, Token::Rem], Self::parse_exponential_expression)
224    }
225
226    /// Returns an [`Expression`] AST node if the next tokens represent a
227    /// binary exponentiation expression.
228    ///
229    /// Otherwise, tries to parse the next token using [`parse_cast_expression`].
230    fn parse_exponential_expression(&mut self) -> Result<Expression> {
231        self.parse_bin_expr(&[Token::Pow], Self::parse_cast_expression)
232    }
233
234    /// Returns an [`Expression`] AST node if the next tokens represent a
235    /// cast expression.
236    ///
237    /// Otherwise, tries to parse the next token using [`parse_unary_expression`].
238    fn parse_cast_expression(&mut self) -> Result<Expression> {
239        let mut expr = self.parse_unary_expression()?;
240        if self.eat(&Token::As) {
241            let (type_, end_span) = self.parse_primitive_type()?;
242            let span = expr.span() + end_span;
243            expr = CastExpression { expression: expr, type_, span, id: self.node_builder.next_id() }.into();
244        }
245
246        Ok(expr)
247    }
248
249    /// Returns an [`Expression`] AST node if the next tokens represent a
250    /// unary not, negate, or bitwise not expression.
251    ///
252    /// Otherwise, tries to parse the next token using [`parse_postfix_expression`].
253    pub(super) fn parse_unary_expression(&mut self) -> Result<Expression> {
254        let token_span = self.token.span;
255
256        let Some(op) = self.eat_unary_op() else {
257            return self.parse_postfix_expression();
258        };
259
260        let mut inner = self.parse_unary_expression()?;
261
262        // Try to construct a negative literal.
263        if let UnaryOperation::Negate = op {
264            use LiteralVariant::*;
265            if let Expression::Literal(Literal {
266                variant: Integer(_, string) | Field(string) | Group(string) | Scalar(string),
267                span,
268                ..
269            }) = &mut inner
270            {
271                if !string.starts_with('-') {
272                    // The operation was a negation and the literal was not already negative, so fold it in.
273                    string.insert(0, '-');
274                    *span = token_span + *span;
275                    return Ok(inner);
276                }
277            }
278        }
279
280        Ok(UnaryExpression { span: token_span + inner.span(), op, receiver: inner, id: self.node_builder.next_id() }
281            .into())
282    }
283
284    // TODO: Parse method call expressions directly and later put them into a canonical form.
285    /// Returns an [`Expression`] AST node if the next tokens represent a
286    /// method call expression.
287    fn parse_method_call_expression(&mut self, receiver: Expression, method: Identifier) -> Result<Expression> {
288        // Parse the argument list.
289        let (mut args, _, span) = self.parse_expr_tuple()?;
290        let span = receiver.span() + span;
291
292        if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) {
293            // Found an unary operator and the argument list is empty.
294            Ok(UnaryExpression { span, op, receiver, id: self.node_builder.next_id() }.into())
295        } else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) {
296            // Found a binary operator and the argument list contains a single argument.
297            Ok(BinaryExpression {
298                span,
299                op,
300                left: receiver,
301                right: args.swap_remove(0),
302                id: self.node_builder.next_id(),
303            }
304            .into())
305        } else if let (2, Some(CoreFunction::SignatureVerify)) =
306            (args.len(), CoreFunction::from_symbols(sym::signature, method.name))
307        {
308            Ok(AssociatedFunctionExpression {
309                variant: Identifier::new(sym::signature, self.node_builder.next_id()),
310                name: method,
311                arguments: std::iter::once(receiver).chain(args).collect(),
312                span,
313                id: self.node_builder.next_id(),
314            }
315            .into())
316        } else if let (0, Some(CoreFunction::FutureAwait)) =
317            (args.len(), CoreFunction::from_symbols(sym::Future, method.name))
318        {
319            Ok(AssociatedFunctionExpression {
320                variant: Identifier::new(sym::Future, self.node_builder.next_id()),
321                name: method,
322                arguments: vec![receiver],
323                span,
324                id: self.node_builder.next_id(),
325            }
326            .into())
327        } else {
328            // Attempt to parse the method call as a mapping operation.
329            match (args.len(), CoreFunction::from_symbols(sym::Mapping, method.name)) {
330                (1, Some(CoreFunction::MappingGet))
331                | (2, Some(CoreFunction::MappingGetOrUse))
332                | (2, Some(CoreFunction::MappingSet))
333                | (1, Some(CoreFunction::MappingRemove))
334                | (1, Some(CoreFunction::MappingContains)) => {
335                    // Found an instance of `<mapping>.get`, `<mapping>.get_or_use`, `<mapping>.set`, `<mapping>.remove`, or `<mapping>.contains`.
336                    Ok(AssociatedFunctionExpression {
337                        variant: Identifier::new(sym::Mapping, self.node_builder.next_id()),
338                        name: method,
339                        arguments: std::iter::once(receiver).chain(args).collect(),
340                        span,
341                        id: self.node_builder.next_id(),
342                    }
343                    .into())
344                }
345                _ => {
346                    // Either an invalid unary/binary operator, or more arguments given.
347                    self.emit_err(ParserError::invalid_method_call(receiver, method, args.len(), span));
348                    Ok(ErrExpression { span, id: self.node_builder.next_id() }.into())
349                }
350            }
351        }
352    }
353
354    /// Returns an [`Expression`] AST node if the next tokens represent a
355    /// static access expression.
356    fn parse_associated_access_expression(&mut self, module_name: Expression) -> Result<Expression> {
357        // Ensure that the preceding expression is an identifier (a named type).
358        let variant = if let Expression::Identifier(ident) = module_name {
359            ident
360        } else {
361            return Err(ParserError::invalid_associated_access(&module_name, module_name.span()).into());
362        };
363
364        // Parse the constant or function name.
365        let member_name = self.expect_identifier()?;
366
367        // Check if there are arguments.
368        let expression = if self.check(&Token::LeftParen) {
369            // Parse the arguments
370            let (args, _, end) = self.parse_expr_tuple()?;
371
372            // Return the associated function.
373            AssociatedFunctionExpression {
374                span: module_name.span() + end,
375                variant,
376                name: member_name,
377                arguments: args,
378                id: self.node_builder.next_id(),
379            }
380            .into()
381        } else {
382            // Return the associated constant.
383            AssociatedConstantExpression {
384                span: module_name.span() + member_name.span(),
385                ty: Type::Identifier(variant),
386                name: member_name,
387                id: self.node_builder.next_id(),
388            }
389            .into()
390        };
391
392        Ok(expression)
393    }
394
395    /// Parses a tuple of `Expression` AST nodes.
396    pub(crate) fn parse_expr_tuple(&mut self) -> Result<(Vec<Expression>, bool, Span)> {
397        self.parse_paren_comma_list(|p| p.parse_expression().map(Some))
398    }
399
400    /// Parses an external function call `credits.aleo/transfer()` or locator `token.aleo/accounts`.
401    ///
402    /// In the ABNF grammar,
403    /// an external function call is one of the two kinds of free function calls,
404    /// namely the one that uses a locator to designate the function;
405    /// a locator is a kind of primary expression.
406    fn parse_external_resource(&mut self, expr: Expression, network_span: Span) -> Result<Expression> {
407        // Parse `/`.
408        self.expect(&Token::Div)?;
409
410        // Parse name.
411        let name = self.expect_identifier()?;
412
413        // Ensure the preceding expression is a (program) identifier.
414        let program: Identifier = match expr {
415            Expression::Identifier(identifier) => identifier,
416            _ => unreachable!("Function called must be preceded by a program identifier."),
417        };
418
419        // Parsing a '{' means that user is trying to illegally define an external record.
420        if self.token.token == Token::LeftCurly {
421            return Err(ParserError::cannot_define_external_record(expr.span() + name.span()).into());
422        }
423
424        // If there is no parenthesis, then it is a locator.
425        if self.token.token != Token::LeftParen {
426            // Parse an external resource locator.
427            return Ok(LocatorExpression {
428                program: ProgramId {
429                    name: program,
430                    network: Identifier { name: sym::aleo, span: network_span, id: self.node_builder.next_id() },
431                },
432                name: name.name,
433                span: expr.span() + name.span(),
434                id: self.node_builder.next_id(),
435            }
436            .into());
437        }
438
439        // Parse the function call.
440        let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
441
442        Ok(CallExpression {
443            span: expr.span() + span,
444            function: name,
445            program: Some(program.name),
446            const_arguments: vec![], // we do not expect const arguments for external calls at this time
447            arguments,
448            id: self.node_builder.next_id(),
449        }
450        .into())
451    }
452
453    /// Returns an [`Expression`] AST node if the next tokens represent an
454    /// array access, struct member access, tuple access, or method call expression.
455    ///
456    /// Otherwise, tries to parse the next token using [`parse_primary_expression`].
457    /// Note that, as mentioned in [`parse_primary_expression`],
458    /// this function also completes the parsing of some primary expressions
459    /// (as defined in the ABNF grammar),
460    /// which [`parse_primary_expression`] only starts to parse.
461    fn parse_postfix_expression(&mut self) -> Result<Expression> {
462        // We don't directly parse named types and identifiers in associated constants and functions
463        // here as the ABNF states. Rather, those named types and identifiers are parsed
464        // as primary expressions, and combined to form associated constants and functions here.
465        let mut expr = self.parse_primary_expression()?;
466        loop {
467            if self.eat(&Token::Dot) {
468                if self.check_int() {
469                    // Eat a tuple member access.
470                    let (index, span) = self.eat_whole_number()?;
471                    expr = TupleAccess { tuple: expr, index, span, id: self.node_builder.next_id() }.into();
472                } else if self.eat(&Token::Leo) {
473                    return Err(ParserError::only_aleo_external_calls(expr.span()).into());
474                } else if self.eat(&Token::Aleo) {
475                    if self.token.token == Token::Div {
476                        expr = self.parse_external_resource(expr, self.prev_token.span)?;
477                    } else {
478                        // Parse as address literal, e.g. `hello.aleo`.
479                        if !matches!(expr, Expression::Identifier(_)) {
480                            self.emit_err(ParserError::unexpected(expr.to_string(), "an identifier", expr.span()))
481                        }
482
483                        expr =
484                            Literal::address(format!("{expr}.aleo"), expr.span(), self.node_builder.next_id()).into();
485                    }
486                } else {
487                    // Parse instances of `self.address`.
488                    if let Expression::Identifier(id) = expr {
489                        if id.name == sym::SelfLower && self.token.token == Token::Address {
490                            let span = self.expect(&Token::Address)?;
491                            // Convert `self.address` to the current program name. TODO: Move this conversion to canonicalization pass when the new pass is added.
492                            // Note that the unwrap is safe as in order to get to this stage of parsing a program name must have already been parsed.
493                            return Ok(Literal::address(
494                                format!("{}.aleo", self.program_name.unwrap()),
495                                expr.span() + span,
496                                self.node_builder.next_id(),
497                            )
498                            .into());
499                        }
500                    }
501
502                    // Parse identifier name.
503                    let name = self.expect_identifier()?;
504
505                    if self.check(&Token::LeftParen) {
506                        // Eat a method call on a type
507                        expr = self.parse_method_call_expression(expr, name)?
508                    } else {
509                        // Eat a struct member access.
510                        let expr_span = expr.span();
511                        expr = MemberAccess {
512                            inner: expr,
513                            name,
514                            span: expr_span + name.span(),
515                            id: self.node_builder.next_id(),
516                        }
517                        .into();
518                    }
519                }
520            } else if self.eat(&Token::DoubleColon) {
521                // If we see a `::`, then we either expect a core associated expression or a list of const arguments in
522                // square brackets.
523                if self.check(&Token::LeftSquare) {
524                    // Check that the expression is an identifier.
525                    let Expression::Identifier(ident) = &expr else {
526                        return Err(leo_errors::LeoError::ParserError(ParserError::unexpected(
527                            expr.to_string(),
528                            "an identifier",
529                            expr.span(),
530                        )));
531                    };
532
533                    // Parse a list of const arguments in between `[..]`
534                    let const_arguments = self.parse_bracket_comma_list(|p| p.parse_expression().map(Some))?.0;
535
536                    // Parse a list of input arguments in between `(..)`
537                    let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
538
539                    // Now form a `CallExpression`
540                    expr = CallExpression {
541                        span: expr.span() + span,
542                        function: *ident,
543                        program: self.program_name,
544                        const_arguments,
545                        arguments,
546                        id: self.node_builder.next_id(),
547                    }
548                    .into()
549                } else {
550                    // Eat a core associated constant or core associated function call.
551                    expr = self.parse_associated_access_expression(expr)?;
552                }
553            } else if self.eat(&Token::LeftSquare) {
554                // Eat an array access.
555                let index = self.parse_expression()?;
556                // Eat the closing bracket.
557                let span = self.expect(&Token::RightSquare)?;
558                let expr_span = expr.span();
559                expr =
560                    ArrayAccess { array: expr, index, span: expr_span + span, id: self.node_builder.next_id() }.into();
561            } else if self.check(&Token::LeftParen) {
562                // Check that the expression is an identifier.
563                let Expression::Identifier(ident) = &expr else {
564                    return Err(leo_errors::LeoError::ParserError(ParserError::unexpected(
565                        expr.to_string(),
566                        "an identifier",
567                        expr.span(),
568                    )));
569                };
570
571                // Parse a function call that's by itself.
572                let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
573                expr = CallExpression {
574                    span: expr.span() + span,
575                    function: *ident,
576                    program: self.program_name,
577                    const_arguments: vec![],
578                    arguments,
579                    id: self.node_builder.next_id(),
580                }
581                .into();
582            }
583            // Stop parsing the postfix expression unless a dot or square bracket follows.
584            if !(self.check(&Token::Dot) || self.check(&Token::LeftSquare)) {
585                break;
586            }
587        }
588        Ok(expr)
589    }
590
591    /// Returns an [`Expression`] AST node if the next tokens represent
592    /// a parenthesized expression or a unit expression
593    /// or a tuple initialization expression or an affine group literal.
594    fn parse_tuple_expression(&mut self) -> Result<Expression> {
595        let (mut elements, trailing, span) = self.parse_expr_tuple()?;
596
597        match (elements.len(), trailing) {
598            (0, _) | (1, true) => {
599                // A tuple with 0 or 1 elements - emit an error since tuples must have at least two elements.
600                Err(ParserError::tuple_must_have_at_least_two_elements("expression", span).into())
601            }
602            (1, false) => {
603                // If there is one element in the tuple but no trailing comma, e.g `(foo)`, return the element.
604                Ok(elements.remove(0))
605            }
606            _ => {
607                // Otherwise, return a tuple expression.
608                // Note: This is the only place where `TupleExpression` is constructed in the parser.
609                Ok(TupleExpression { elements, span, id: self.node_builder.next_id() }.into())
610            }
611        }
612    }
613
614    /// Attempts to parse an array initialization expression and returns an [`Expression`] AST node if successful.
615    fn parse_array_or_repeat_expression(&mut self) -> Result<Expression> {
616        let (open, close) = Delimiter::Bracket.open_close_pair();
617        let open_span = self.expect(&open)?;
618
619        // Attempt to parse the first expression in the array.
620        let Ok(first_expr) = self.parse_expression() else {
621            // If we're unable to parse an expression, just expect a `]` and error out on empty array.
622            let close_span = self.expect(&close)?;
623            return Err(ParserError::array_must_have_at_least_one_element("expression", open_span + close_span).into());
624        };
625
626        // Handle array repetition syntax: [expr; count]
627        if self.eat(&Token::Semicolon) {
628            let count = self.parse_expression()?;
629            let span = open_span + self.expect(&close)?;
630            return Ok(RepeatExpression { expr: first_expr, count, span, id: self.node_builder.next_id() }.into());
631        }
632
633        // Handle array with multiple elements: [expr1, expr2, ...] or single element with or without trailing comma:
634        // [expr,]
635        let mut elements = vec![first_expr];
636        while self.eat(&Token::Comma) && !self.check(&close) {
637            elements.push(self.parse_expression()?);
638        }
639        let span = open_span + self.expect(&close)?;
640        Ok(ArrayExpression { elements, span, id: self.node_builder.next_id() }.into())
641    }
642
643    fn parse_struct_member(&mut self) -> Result<StructVariableInitializer> {
644        let identifier = self.expect_identifier()?;
645
646        let (expression, span) = if self.eat(&Token::Colon) {
647            // Parse individual struct variable declarations.
648            let expression = self.parse_expression()?;
649            let span = identifier.span + expression.span();
650            (Some(expression), span)
651        } else {
652            (None, identifier.span)
653        };
654
655        Ok(StructVariableInitializer { identifier, expression, id: self.node_builder.next_id(), span })
656    }
657
658    /// Returns an [`Expression`] AST node if the next tokens represent a
659    /// struct initialization expression.
660    /// let foo = Foo { x: 1u8 };
661    pub fn parse_struct_init_expression(&mut self, identifier: Identifier) -> Result<Expression> {
662        let (members, _, end) =
663            self.parse_list(Delimiter::Brace, Some(Token::Comma), |p| p.parse_struct_member().map(Some))?;
664
665        Ok(StructExpression { span: identifier.span + end, name: identifier, members, id: self.node_builder.next_id() }
666            .into())
667    }
668
669    /// Returns an [`Expression`] AST node if the next token is a primary expression:
670    /// - Literals: field, group, unsigned integer, signed integer, boolean, address, string
671    /// - Aggregate type constructors: array, tuple, structs
672    /// - Identifiers: variables, keywords
673    ///
674    /// This function only parses some of the primary expressions defined in the ABNF grammar;
675    /// for the others, it parses their initial parts,
676    /// leaving it to the [self.parse_postfix_expression] function to complete the parsing.
677    /// For example, of the primary expression `u8::c`, this function only parses the `u8` part,
678    /// leaving it to [self.parse_postfix_expression] to parse the `::c` part.
679    /// So technically the expression returned by this function may not quite be
680    /// an expression as defined in the ABNF grammar,
681    /// but it is only a temporary expression that is combined into a larger one
682    /// by [self.parse_postfix_expression], yielding an actual expression according to the grammar.
683    ///
684    /// Returns an expression error if the token cannot be matched.
685    fn parse_primary_expression(&mut self) -> Result<Expression> {
686        if let Token::LeftParen = self.token.token {
687            return self.parse_tuple_expression();
688        } else if let Token::LeftSquare = self.token.token {
689            return self.parse_array_or_repeat_expression();
690        }
691
692        let SpannedToken { token, span } = self.token.clone();
693        self.bump();
694
695        Ok(match token {
696            Token::Integer(value) => {
697                let suffix_span = self.token.span;
698                let full_span = span + suffix_span;
699                let assert_no_whitespace = |x| assert_no_whitespace(span, suffix_span, &value, x);
700
701                match self.eat_any(INT_TYPES).then_some(&self.prev_token.token) {
702                    // Hex, octal, binary literal on a noninteger is an error.
703                    Some(Token::Field) | Some(Token::Group) | Some(Token::Scalar)
704                        if value.starts_with("0x")
705                            || value.starts_with("0o")
706                            || value.starts_with("0b")
707                            || value.starts_with("-0x")
708                            || value.starts_with("-0o")
709                            || value.starts_with("-0b") =>
710                    {
711                        return Err(ParserError::hexbin_literal_nonintegers(span).into());
712                    }
713                    // Literal followed by `field`, e.g., `42field`.
714                    Some(Token::Field) => {
715                        assert_no_whitespace("field")?;
716                        Literal::field(value, full_span, self.node_builder.next_id()).into()
717                    }
718                    // Literal followed by `group`, e.g., `42group`.
719                    Some(Token::Group) => {
720                        assert_no_whitespace("group")?;
721                        Literal::group(value, full_span, self.node_builder.next_id()).into()
722                    }
723                    // Literal followed by `scalar` e.g., `42scalar`.
724                    Some(Token::Scalar) => {
725                        assert_no_whitespace("scalar")?;
726                        Literal::scalar(value, full_span, self.node_builder.next_id()).into()
727                    }
728                    // Literal followed by other type suffix, e.g., `42u8`.
729                    Some(suffix) => {
730                        assert_no_whitespace(&suffix.to_string())?;
731                        let int_ty = Self::token_to_int_type(suffix).expect("unknown int type token");
732                        Literal::integer(int_ty, value, full_span, self.node_builder.next_id()).into()
733                    }
734                    None => {
735                        // `Integer` tokens with no suffix are `unsuffixed`. We try to infer their
736                        // type in the type inference phase of the type checker.
737                        Literal::unsuffixed(value, span, self.node_builder.next_id()).into()
738                    }
739                }
740            }
741            Token::True => Literal::boolean(true, span, self.node_builder.next_id()).into(),
742            Token::False => Literal::boolean(false, span, self.node_builder.next_id()).into(),
743            Token::AddressLit(address_string) => {
744                if address_string.parse::<Address<N>>().is_err() {
745                    self.emit_err(ParserError::invalid_address_lit(&address_string, span));
746                }
747                Literal::address(address_string, span, self.node_builder.next_id()).into()
748            }
749            Token::StaticString(value) => {
750                Literal { span, id: self.node_builder.next_id(), variant: LiteralVariant::String(value) }.into()
751            }
752            Token::Identifier(name) => {
753                let ident = Identifier { name, span, id: self.node_builder.next_id() };
754                if !self.disallow_struct_construction && self.check(&Token::LeftCurly) {
755                    // Parse struct and records inits as struct expressions.
756                    // Enforce struct or record type later at type checking.
757                    self.parse_struct_init_expression(ident)?
758                } else {
759                    ident.into()
760                }
761            }
762            Token::SelfLower => Identifier { name: sym::SelfLower, span, id: self.node_builder.next_id() }.into(),
763            Token::Block => Identifier { name: sym::block, span, id: self.node_builder.next_id() }.into(),
764            Token::Future => Identifier { name: sym::Future, span, id: self.node_builder.next_id() }.into(),
765            Token::Network => Identifier { name: sym::network, span, id: self.node_builder.next_id() }.into(),
766            t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
767                name: t.keyword_to_symbol().unwrap(),
768                span,
769                id: self.node_builder.next_id(),
770            }),
771            token => {
772                return Err(ParserError::unexpected_str(token, "expression", span).into());
773            }
774        })
775    }
776}
777
778fn assert_no_whitespace(left_span: Span, right_span: Span, left: &str, right: &str) -> Result<()> {
779    if left_span.hi != right_span.lo {
780        let error_span = Span::new(left_span.hi, right_span.lo); // The span between them.
781        return Err(ParserError::unexpected_whitespace(left, right, error_span).into());
782    }
783
784    Ok(())
785}