diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index ab2b18ad81aa014acecabc50db0c7b131aa6c945..0436245808a05644b981900a7705735ba1f7457b 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -1317,15 +1317,38 @@ impl PassDefinitions { )); } } else { + // Can be a select expression for struct fields, or a select + // for a tuple element. debug_assert_eq!(token, TokenKind::Dot); let subject = result; - let field_name = consume_ident_interned(&module.source, iter, ctx)?; - let full_span = InputSpan::from_positions( - ctx.heap[subject].full_span().begin, field_name.span.end - ); + let next = iter.next(); + let (select_kind, full_span) = if Some(TokenKind::Integer) == next { + // Tuple member + let (index, index_span) = consume_integer_literal(&module.source, iter, &mut self.buffer)?; + let full_span = InputSpan::from_positions( + ctx.heap[subject].full_span().begin, index_span.end + ); + + (SelectKind::TupleMember(index), full_span) + } else if Some(TokenKind::Ident) == next { + // Struct field + let field_name = consume_ident_interned(&module.source, iter, ctx)?; + + let full_span = InputSpan::from_positions( + ctx.heap[subject].full_span().begin, field_name.span.end + ); + + (SelectKind::StructField(field_name), full_span) + } else { + return Err(ParseError::new_error_str_at_pos( + &module.source, iter.last_valid_pos(), "unexpected token: expected integer or identifier" + )); + }; + result = ctx.heap.alloc_select_expression(|this| SelectExpression{ - this, operator_span, full_span, subject, field_name, + this, operator_span, full_span, subject, + kind: select_kind, parent: ExpressionParent::None, unique_id_in_definition: -1, }).upcast();