1use 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 pub(crate) fn parse_expression(&mut self) -> Result<Expression> {
43 let prior_fuzzy_state = self.disallow_struct_construction;
45
46 self.disallow_struct_construction = false;
48
49 let result = self.parse_conditional_expression();
51
52 self.disallow_struct_construction = prior_fuzzy_state;
54
55 result
56 }
57
58 pub(super) fn parse_conditional_expression(&mut self) -> Result<Expression> {
63 let mut expr = self.parse_boolean_or_expression()?;
65
66 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 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 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 fn parse_boolean_or_expression(&mut self) -> Result<Expression> {
107 self.parse_bin_expr(&[Token::Or], Self::parse_boolean_and_expression)
108 }
109
110 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 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 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 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 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 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 fn parse_bitwise_and_expression(&mut self) -> Result<Expression> {
199 self.parse_bin_expr(&[Token::BitAnd], Self::parse_shift_expression)
200 }
201
202 fn parse_shift_expression(&mut self) -> Result<Expression> {
207 self.parse_bin_expr(&[Token::Shl, Token::Shr], Self::parse_additive_expression)
208 }
209
210 fn parse_additive_expression(&mut self) -> Result<Expression> {
215 self.parse_bin_expr(&[Token::Add, Token::Sub], Self::parse_multiplicative_expression)
216 }
217
218 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 fn parse_exponential_expression(&mut self) -> Result<Expression> {
231 self.parse_bin_expr(&[Token::Pow], Self::parse_cast_expression)
232 }
233
234 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 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 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 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 fn parse_method_call_expression(&mut self, receiver: Expression, method: Identifier) -> Result<Expression> {
288 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 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 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 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 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 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 fn parse_associated_access_expression(&mut self, module_name: Expression) -> Result<Expression> {
357 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 let member_name = self.expect_identifier()?;
366
367 let expression = if self.check(&Token::LeftParen) {
369 let (args, _, end) = self.parse_expr_tuple()?;
371
372 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 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 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 fn parse_external_resource(&mut self, expr: Expression, network_span: Span) -> Result<Expression> {
407 self.expect(&Token::Div)?;
409
410 let name = self.expect_identifier()?;
412
413 let program: Identifier = match expr {
415 Expression::Identifier(identifier) => identifier,
416 _ => unreachable!("Function called must be preceded by a program identifier."),
417 };
418
419 if self.token.token == Token::LeftCurly {
421 return Err(ParserError::cannot_define_external_record(expr.span() + name.span()).into());
422 }
423
424 if self.token.token != Token::LeftParen {
426 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 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![], arguments,
448 id: self.node_builder.next_id(),
449 }
450 .into())
451 }
452
453 fn parse_postfix_expression(&mut self) -> Result<Expression> {
462 let mut expr = self.parse_primary_expression()?;
466 loop {
467 if self.eat(&Token::Dot) {
468 if self.check_int() {
469 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 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 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 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 let name = self.expect_identifier()?;
504
505 if self.check(&Token::LeftParen) {
506 expr = self.parse_method_call_expression(expr, name)?
508 } else {
509 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 self.check(&Token::LeftSquare) {
524 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 let const_arguments = self.parse_bracket_comma_list(|p| p.parse_expression().map(Some))?.0;
535
536 let (arguments, _, span) = self.parse_paren_comma_list(|p| p.parse_expression().map(Some))?;
538
539 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 expr = self.parse_associated_access_expression(expr)?;
552 }
553 } else if self.eat(&Token::LeftSquare) {
554 let index = self.parse_expression()?;
556 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 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 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 if !(self.check(&Token::Dot) || self.check(&Token::LeftSquare)) {
585 break;
586 }
587 }
588 Ok(expr)
589 }
590
591 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 Err(ParserError::tuple_must_have_at_least_two_elements("expression", span).into())
601 }
602 (1, false) => {
603 Ok(elements.remove(0))
605 }
606 _ => {
607 Ok(TupleExpression { elements, span, id: self.node_builder.next_id() }.into())
610 }
611 }
612 }
613
614 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 let Ok(first_expr) = self.parse_expression() else {
621 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 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 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 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 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 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 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 Some(Token::Field) => {
715 assert_no_whitespace("field")?;
716 Literal::field(value, full_span, self.node_builder.next_id()).into()
717 }
718 Some(Token::Group) => {
720 assert_no_whitespace("group")?;
721 Literal::group(value, full_span, self.node_builder.next_id()).into()
722 }
723 Some(Token::Scalar) => {
725 assert_no_whitespace("scalar")?;
726 Literal::scalar(value, full_span, self.node_builder.next_id()).into()
727 }
728 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 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 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); return Err(ParserError::unexpected_whitespace(left, right, error_span).into());
782 }
783
784 Ok(())
785}