diff --git a/toolchain/check/handle_pack_expansion.cpp b/toolchain/check/handle_pack_expansion.cpp new file mode 100644 index 000000000000..8e1a3f206d1c --- /dev/null +++ b/toolchain/check/handle_pack_expansion.cpp @@ -0,0 +1,25 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/context.h" +#include "toolchain/check/handle.h" + +namespace Carbon::Check { + +auto HandleParseNode(Context& context, Parse::PackExpansionStartId node_id) + -> bool { + return context.TODO(node_id, "HandlePackExpansionStart"); +} + +auto HandleParseNode(Context& context, Parse::PackExpansionStatementId node_id) + -> bool { + return context.TODO(node_id, "HandlePackExpansionStatement"); +} + +auto HandleParseNode(Context& context, Parse::PrefixOperatorExpandId node_id) + -> bool { + return context.TODO(node_id, "HandlePrefixOperatorExpand"); +} + +} // namespace Carbon::Check diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index da469ae30c79..dfada597538d 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -468,6 +468,7 @@ class NodeStack { case Parse::NodeKind::LetInitializer: case Parse::NodeKind::LetIntroducer: case Parse::NodeKind::NamedConstraintIntroducer: + case Parse::NodeKind::PackExpansionStart: case Parse::NodeKind::RefBindingName: case Parse::NodeKind::RuntimeBindingName: case Parse::NodeKind::ReturnStatementStart: diff --git a/toolchain/check/testdata/variadics/pack_expansion.carbon b/toolchain/check/testdata/variadics/pack_expansion.carbon new file mode 100644 index 000000000000..274067048670 --- /dev/null +++ b/toolchain/check/testdata/variadics/pack_expansion.carbon @@ -0,0 +1,33 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/variadics/pack_expansion.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/variadics/pack_expansion.carbon + +// --- fail_todo_pack_expansion_statement.carbon +library "[[@TEST_NAME]]"; + +fn F() { + // CHECK:STDERR: fail_todo_pack_expansion_statement.carbon:[[@LINE+4]]:3: error: semantics TODO: `HandlePackExpansionStart` [SemanticsTodo] + // CHECK:STDERR: ... F(); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + ... F(); +} + +// --- fail_todo_expand.carbon +library "[[@TEST_NAME]]"; + +fn F(x: (i32, i32)) { + // CHECK:STDERR: fail_todo_expand.carbon:[[@LINE+4]]:3: error: semantics TODO: `HandlePrefixOperatorExpand` [SemanticsTodo] + // CHECK:STDERR: expand x; + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: + expand x; +} diff --git a/toolchain/lex/testdata/periods.carbon b/toolchain/lex/testdata/periods.carbon new file mode 100644 index 000000000000..b7eccde765f3 --- /dev/null +++ b/toolchain/lex/testdata/periods.carbon @@ -0,0 +1,23 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lex/testdata/periods.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lex/testdata/periods.carbon +// CHECK:STDOUT: - filename: periods.carbon +// CHECK:STDOUT: tokens: + +. .. ... .... ...... ...expand +// CHECK:STDOUT: - { index: 1, kind: "Period", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: ".", has_leading_space: true } +// CHECK:STDOUT: - { index: 2, kind: "Period", line: {{ *}}[[@LINE-2]], column: 3, indent: 1, spelling: ".", has_leading_space: true } +// CHECK:STDOUT: - { index: 3, kind: "Period", line: {{ *}}[[@LINE-3]], column: 4, indent: 1, spelling: "." } +// CHECK:STDOUT: - { index: 4, kind: "PeriodPeriodPeriod", line: {{ *}}[[@LINE-4]], column: 6, indent: 1, spelling: "...", has_leading_space: true } +// CHECK:STDOUT: - { index: 5, kind: "PeriodPeriodPeriod", line: {{ *}}[[@LINE-5]], column: 10, indent: 1, spelling: "...", has_leading_space: true } +// CHECK:STDOUT: - { index: 6, kind: "Period", line: {{ *}}[[@LINE-6]], column: 13, indent: 1, spelling: "." } +// CHECK:STDOUT: - { index: 7, kind: "PeriodPeriodPeriod", line: {{ *}}[[@LINE-7]], column: 15, indent: 1, spelling: "...", has_leading_space: true } +// CHECK:STDOUT: - { index: 8, kind: "PeriodPeriodPeriod", line: {{ *}}[[@LINE-8]], column: 18, indent: 1, spelling: "..." } +// CHECK:STDOUT: - { index: 9, kind: "PeriodPeriodPeriod", line: {{ *}}[[@LINE-9]], column: 22, indent: 1, spelling: "...", has_leading_space: true } +// CHECK:STDOUT: - { index: 10, kind: "Expand", line: {{ *}}[[@LINE-10]], column: 25, indent: 1, spelling: "expand" } diff --git a/toolchain/lex/token_kind.def b/toolchain/lex/token_kind.def index 42aac1025af3..0b2bf42155c2 100644 --- a/toolchain/lex/token_kind.def +++ b/toolchain/lex/token_kind.def @@ -60,6 +60,8 @@ CARBON_SYMBOL_TOKEN(GreaterGreaterEqual, ">>=") CARBON_SYMBOL_TOKEN(LessEqualGreater, "<=>") CARBON_SYMBOL_TOKEN(LessLessEqual, "<<=") CARBON_SYMBOL_TOKEN(MinusGreaterQuestion,"->?") +CARBON_TOKEN_WITH_VIRTUAL_NODE( + CARBON_SYMBOL_TOKEN(PeriodPeriodPeriod, "...")) CARBON_SYMBOL_TOKEN(AmpEqual, "&=") CARBON_SYMBOL_TOKEN(CaretEqual, "^=") @@ -189,6 +191,7 @@ CARBON_KEYWORD_TOKEN(Cpp, "Cpp") CARBON_KEYWORD_TOKEN(Default, "default") CARBON_KEYWORD_TOKEN(Else, "else") CARBON_KEYWORD_TOKEN(Eval, "eval") +CARBON_KEYWORD_TOKEN(Expand, "expand") CARBON_KEYWORD_TOKEN(Extend, "extend") CARBON_KEYWORD_TOKEN(Extern, "extern") CARBON_KEYWORD_TOKEN(False, "false") diff --git a/toolchain/parse/handle_statement.cpp b/toolchain/parse/handle_statement.cpp index 6605ff8269b4..29ab7820fdf8 100644 --- a/toolchain/parse/handle_statement.cpp +++ b/toolchain/parse/handle_statement.cpp @@ -51,6 +51,12 @@ auto HandleStatement(Context& context) -> void { context.PushState(StateKind::MatchIntroducer); break; } + case Lex::TokenKind::PeriodPeriodPeriod: { + context.PushState(StateKind::StatementPackExpansionFinish); + context.AddLeafNode(NodeKind::PackExpansionStart, context.Consume()); + context.PushState(StateKind::Statement); + break; + } #define CARBON_PARSE_NODE_KIND(Name) #define CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name) case Lex::TokenKind::Name: #include "toolchain/parse/node_kind.def" @@ -228,6 +234,13 @@ auto HandleStatementReturnFinish(Context& context) -> void { HandleStatementKeywordFinish(context, NodeKind::ReturnStatement); } +auto HandleStatementPackExpansionFinish(Context& context) -> void { + auto state = context.PopState(); + + context.AddNode(NodeKind::PackExpansionStatement, state.token, + state.has_error); +} + auto HandleStatementScopeLoop(Context& context) -> void { // This maintains the current state until we're at the end of the scope. diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index bc86ef7448da..fb623749baaa 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -286,6 +286,9 @@ CARBON_PARSE_NODE_KIND_STATEMENT(WhileConditionStart) CARBON_PARSE_NODE_KIND_STATEMENT(WhileCondition) CARBON_PARSE_NODE_KIND_STATEMENT(WhileStatement) +CARBON_PARSE_NODE_KIND_STATEMENT(PackExpansionStart) +CARBON_PARSE_NODE_KIND_STATEMENT(PackExpansionStatement) + CARBON_PARSE_NODE_KIND_EXPRESSION(IndexExprStart) CARBON_PARSE_NODE_KIND_EXPRESSION(IndexExpr) @@ -337,6 +340,7 @@ CARBON_PARSE_NODE_KIND_TOKEN_LITERAL(UnsignedIntTypeLiteral, CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Amp) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Caret) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Const) +CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Expand) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Not) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(Minus) CARBON_PARSE_NODE_KIND_PREFIX_OPERATOR(MinusMinus) diff --git a/toolchain/parse/precedence.cpp b/toolchain/parse/precedence.cpp index f056217fc0cf..493ea5d2f738 100644 --- a/toolchain/parse/precedence.cpp +++ b/toolchain/parse/precedence.cpp @@ -149,6 +149,7 @@ auto PrecedenceGroup::ForLeading(Lex::TokenKind kind) switch (kind) { case Lex::TokenKind::Star: case Lex::TokenKind::Amp: + case Lex::TokenKind::Expand: return PrecedenceGroup(TermPrefix); case Lex::TokenKind::Not: @@ -249,6 +250,7 @@ auto PrecedenceGroup::ForTrailing(Lex::TokenKind kind, bool infix) // Prefix-only operators. case Lex::TokenKind::Const: + case Lex::TokenKind::Expand: case Lex::TokenKind::MinusMinus: case Lex::TokenKind::Not: case Lex::TokenKind::Partial: diff --git a/toolchain/parse/state.def b/toolchain/parse/state.def index 2bc83e61156d..fa08dc0ecd9d 100644 --- a/toolchain/parse/state.def +++ b/toolchain/parse/state.def @@ -17,10 +17,10 @@ // // The comments before each state describe the portion of the grammar that the // state is implementing, by giving an example of each kind of token sequence -// that this state handles. In these examples, `...` indicates a sequence of -// tokens handled by some other state, and `???` indicates a sequence of invalid -// tokens. A trailing `??? ;` indicates an attempt to skip to the end of the -// declaration, which may or may not actually find a `;` token. +// that this state handles. In these examples, `<...>` indicates a sequence of +// tokens handled by some other state, and `` indicates a sequence of +// invalid tokens. A trailing ` ;` indicates an attempt to skip to the end +// of the declaration, which may or may not actually find a `;` token. // // The position in the token stream before the state is indicated by the caret // `^` on the line below the example, and all tokens consumed by the state are @@ -101,25 +101,25 @@ CARBON_PARSE_STATE(ArrayExprFinish) // Handles the start of a form literal. // -// form ( ... +// form ( <...> // ^~~~~~ // 1. PrimitiveForm // 2. FormLiteralFinish // -// form ??? +// form // ^~~~ // 1. FormLiteralFinish CARBON_PARSE_STATE(FormLiteral) // Handles the category modifier and type of a form literal. // -// form ( val ... +// form ( val <...> // ^~~ -// form ( var ... +// form ( var <...> // ^~~ -// form ( ref ... +// form ( ref <...> // ^~~ -// form ( ??? +// form ( // ^ // 1. Expr // 2. PrimitiveFormFinish @@ -127,19 +127,19 @@ CARBON_PARSE_STATE(PrimitiveForm) // Finishes handling of PrimitiveForm. // -// form ( ... ) +// form ( <...> ) +// ^ +// form // ^ -// form ??? -// ^ CARBON_PARSE_STATE(PrimitiveFormFinish) // Handles the end of a form literal. // -// form ( ... ) -// ^ -// form ( ??? ) -// ^~~~~ -// form ??? +// form ( <...> ) +// ^ +// form ( ) +// ^~~~~~~ +// form // ^ // (state done) CARBON_PARSE_STATE(FormLiteralFinish) @@ -165,7 +165,7 @@ CARBON_PARSE_STATE(TypeOfExprFinish) // ^ // 1. BraceExprFinishAsUnknown // -// { ... } +// { <...> } // ^ // 1. BraceExprParamAsUnknown // 2. BraceExprFinishAsUnknown @@ -175,12 +175,12 @@ CARBON_PARSE_STATE(BraceExpr) // but should be known after the first valid parameter. All later inconsistent // parameters are invalid. // -// { .foo ... } +// { .foo <...> } // ^ // 1. PeriodAsStruct // 2. BraceExprParamAfterDesignatorAs(Type|Value|Unknown) // -// { ??? +// { // ^ // 1. BraceExprParamFinishAs(Type|Value|Unknown) CARBON_PARSE_STATE_VARIANTS3(BraceExprParam, Type, Value, Unknown) @@ -188,17 +188,17 @@ CARBON_PARSE_STATE_VARIANTS3(BraceExprParam, Type, Value, Unknown) // Handles a brace expression parameter after the initial designator. This // should be at a `:` or `=`, depending on whether it's a type or value literal. // -// { .foo = bar ... } +// { .foo = bar <...> } // ^ // 1. Expr // 2. BraceExprParamFinishAsValue // -// { .foo: bar ... } +// { .foo: bar <...> } // ^ // 1. Expr // 2. BraceExprParamFinishAsType // -// { .foo ??? +// { .foo // ^ // 1. BraceExprParamFinishAs(Type|Value|Unknown) CARBON_PARSE_STATE_VARIANTS3(BraceExprParamAfterDesignator, Type, Value, @@ -206,27 +206,27 @@ CARBON_PARSE_STATE_VARIANTS3(BraceExprParamAfterDesignator, Type, Value, // Handles the end of a brace expression parameter. // -// { ... } -// ^ +// { <...> } +// ^ // (state done) // -// { .foo = bar, ... } +// { .foo = bar, <...> } // ^ // 1. BraceExprParamAsValue // -// { .foo: bar, ... } +// { .foo: bar, <...> } // ^ // 1. BraceExprParamAsType // -// { ??? , ... } -// ^ +// { , <...> } +// ^ // 1. BraceExprParamAsUnknown CARBON_PARSE_STATE_VARIANTS3(BraceExprParamFinish, Type, Value, Unknown) // Handles the `}` of a brace expression. // -// { ... } -// ^ +// { <...> } +// ^ // (state done) CARBON_PARSE_STATE_VARIANTS3(BraceExprFinish, Type, Value, Unknown) @@ -236,7 +236,7 @@ CARBON_PARSE_STATE_VARIANTS3(BraceExprFinish, Type, Value, Unknown) // ^ // 1. CallExprFinish // -// F( ... +// F( <...> // ^ // 1. Expr // 2. TupleLiteralElementFinish @@ -257,7 +257,7 @@ CARBON_PARSE_STATE(CallExprFinish) // 1. StatementScopeLoop // 2. CodeBlockFinish // -// if (cond) ??? +// if (cond) // ^ // 1. Statement // 2. CodeBlockFinish @@ -266,32 +266,32 @@ CARBON_PARSE_STATE(CodeBlock) // Handles processing at the `}` on a typical code block, after a statement // scope is done. // -// if (cond) { ... } -// ^ +// if (cond) { <...> } +// ^ // (state done) CARBON_PARSE_STATE(CodeBlockFinish) -// Handles a declaration name and parameters, such as `Foo[...](...)`. +// Handles a declaration name and parameters, such as `Foo[T: type](x: T)`. // -// name . ... +// name . <...> // ^~~~~~ // 1. DeclNameAndParams // -// name [ ... ] +// name [ <...> ] // ^~~~ // 1. PatternListAsImplicit // 2. DeclNameAndParamsAfterImplicit // -// name ( ... ) +// name ( <...> ) // ^~~~ // 1. PatternListAsExplicit // 2. DeclNameAndParamsAfterParams // -// name ... +// name <...> // ^~~~ // (state done) // -// ??? +// // ^ // (state done) CARBON_PARSE_STATE(DeclNameAndParams) @@ -299,25 +299,25 @@ CARBON_PARSE_STATE(DeclNameAndParams) // Inside a declaration, conditionally starts explicit parameter handling. Only // used after implicit parameters. // -// name [ ... ] ( ... ) -// ^ +// name [ <...> ] ( <...> ) +// ^ // 1. PatternListAsExplicit // 2. DeclNameAndParamsAfterParams // -// name [ ... ] ??? -// ^ +// name [ <...> ] +// ^ // (state done) CARBON_PARSE_STATE(DeclNameAndParamsAfterImplicit) // Inside a declaration, conditionally starts another qualified name. Only used // after regular parameters. // -// name [ ... ] ( ... ) . -// ^ +// name [ <...> ] ( <...> ) . +// ^ // 1. DeclNameAndParams // -// name [ ... ] ( ... ) ... -// ^ +// name [ <...> ] ( <...> ) <...> +// ^ // (state done) CARBON_PARSE_STATE(DeclNameAndParamsAfterParams) @@ -346,91 +346,91 @@ CARBON_PARSE_STATE(DeclNameAndParamsAfterParams) // ^~~~~~~ // 1. Decl // -// adapt ... +// adapt <...> // ^~~~~ // 1. AdaptAfterIntroducer // -// alias ... +// alias <...> // ^~~~~ // 1. Alias // -// base : ... +// base : <...> // ^~~~ // 1. BaseAfterIntroducer // -// choice ... +// choice <...> // ^~~~~~ // 1. ChoiceIntroducer // -// class ... +// class <...> // ^~~~~ // 1. TypeAfterIntroducerAsClass // -// constraint ... +// constraint <...> // ^~~~~~~~~~ // 1. TypeAfterIntroducerAsNamedConstraint // -// export ... +// export <...> // ^~~~~~ // 1. ExportName // -// fn ... +// fn <...> // ^~ // 1. FunctionIntroducer // -// friend ... +// friend <...> // ^~~~~~ // 1. FriendDecl // -// impl ... +// impl <...> // ^~~~ // 1. ImplAfterIntroducer // -// import ... (in packaging directives) +// import <...> (in packaging directives) // ^~~~~~ // 1. Import // -// inline ... +// inline <...> // ^~~~~~ // 1. InlineDeclAfterIntroducer (variant is Regular) // -// interface ... +// interface <...> // ^~~~~~~~~ // 1. TypeAfterIntroducerAsInterface // -// let ... (variant is Regular) +// let <...> (variant is Regular) // ^~~ // 1. Let // -// let ... (variant is Interface) +// let <...> (variant is Interface) // ^~~ // 1. AssociatedConstant // -// library ... (in packaging directives) +// library <...> (in packaging directives) // ^~~~~~~ // 1. Library // -// match_first ... +// match_first <...> // ^~~~~~~~~ // 1. MatchFirst // -// namespace ... +// namespace <...> // ^~~~~~~~~ // 1. Namespace // -// package ... (in packaging directives) +// package <...> (in packaging directives) // ^~~~~~~ // 1. Package // -// require ... +// require <...> // ^~~~~~~ // 1. RequireAfterIntroducer // -// observe ... +// observe <...> // ^~~~~~~ // 1. ObserveAfterIntroducer // -// var ... (variant is Regular) +// var <...> (variant is Regular) // ^~~ // 1. VarAsRegular // @@ -438,8 +438,8 @@ CARBON_PARSE_STATE(DeclNameAndParamsAfterParams) // ^ // (state done) // -// ??? ; -// ^~~~~ +// ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE_VARIANTS3(Decl, Class, Interface, Regular) @@ -452,7 +452,7 @@ CARBON_PARSE_STATE_VARIANTS3(Decl, Class, Interface, Regular) // ^ // (state done) // -// ... +// <...> // ^ // 1. DeclAs(Class|Interface|Regular) // 2. DeclScopeLoopAs(Class|Interface|Regular) @@ -484,18 +484,18 @@ CARBON_PARSE_STATE(InlineDeclAfterIntroducer) // ^~~~~~ // -> base (variant is not Decl) // ^~~~~~~ -// . ??? (??? consumed if it is a keyword) +// . ( consumed if it is a keyword) // ^ -// -> ??? (??? consumed if it is a keyword) +// -> ( consumed if it is a keyword) // ^~ // (state done) // -// expr . ( ... ) +// expr . ( <...> ) // ^ // 1. OnlyParenExpr // 2. CompoundMemberAccess // -// expr -> ( ... ) +// expr -> ( <...> ) // ^~ // 1. OnlyParenExpr // 2. CompoundPointerMemberAccess @@ -520,25 +520,25 @@ CARBON_PARSE_STATE(CompoundPointerMemberAccess) // ^~~~~~~ // (state done) // -// -> ??? (??? consumed if it is a keyword) +// -> ( consumed if it is a keyword) // ^~ // (state done) CARBON_PARSE_STATE(ArrowExpr) // Handles processing of an expression. // -// if ... +// if <...> // ^~ // 1. Expr // 2. IfExprCondition // 3. IfExprFinish // -// ... +// <...> // ^~~~~~~~~~~~~~~~~ // 1. Expr // 2. ExprLoopForPrefix // -// ... +// <...> // ^ // 1. ExprInPostfix // 2. ExprLoop @@ -577,7 +577,7 @@ CARBON_PARSE_STATE(Expr) // 1. FormExpr // 2. ExprInPostfixLoop // -// ??? +// // ^ // (state done) CARBON_PARSE_STATE(ExprInPostfix) @@ -585,34 +585,34 @@ CARBON_PARSE_STATE(ExprInPostfix) // Handles looping through elements following the initial postfix expression, // such as designators or parenthesized parameters. // -// expr . ... +// expr . <...> // ^ // 1. PeriodAsExpr // 2. ExprInPostfixLoop // -// expr -> ... +// expr -> <...> // ^ // 1. ArrowExpr // 2. ExprInPostfixLoop // -// expr ( ... ) +// expr ( <...> ) // ^ // 1. CallExpr // 2. ExprInPostfixLoop // -// expr [ ... ] +// expr [ <...> ] // ^ // 1. IndexExprStart // 2. ExprInPostfixLoop // -// ... +// <...> // ^ // (state done) CARBON_PARSE_STATE(ExprInPostfixLoop) // Handles processing of an expression. // -// expr ... +// expr <...> // ^~~~~~~~~~~~~~~~ // 1. Expr // 2. ExprLoopForBinary @@ -621,12 +621,12 @@ CARBON_PARSE_STATE(ExprInPostfixLoop) // ^~~~~~~~~~~~~~~~~~ // 1. ExprLoop // -// expr ... +// expr <...> // ^~~~~~~~~~~~~~~~~~~~~~~~ // 1. Expr // 2. ExprLoopForShortCircuitOperator // -// expr ... +// expr <...> // ^ // (state done) CARBON_PARSE_STATE(ExprLoop) @@ -634,7 +634,7 @@ CARBON_PARSE_STATE(ExprLoop) // Completes an ExprLoop pass by adding an infix operator, then goes back // to ExprLoop. // -// expr expr ... +// expr expr <...> // ^ // 1. ExprLoop CARBON_PARSE_STATE(ExprLoopForInfixOperator) @@ -642,7 +642,7 @@ CARBON_PARSE_STATE(ExprLoopForInfixOperator) // Completes an ExprLoop pass by adding a prefix operator, then goes back // to ExprLoop. // -// expr ... +// expr <...> // ^ // 1. ExprLoop CARBON_PARSE_STATE(ExprLoopForPrefixOperator) @@ -650,19 +650,19 @@ CARBON_PARSE_STATE(ExprLoopForPrefixOperator) // Completes an ExprLoop pass by adding a short circuit operator, then goes back // to ExprLoop. // -// expr expr ... +// expr expr <...> // ^ // 1. ExprLoop CARBON_PARSE_STATE_VARIANTS2(ExprLoopForShortCircuitOperator, And, Or) // Completes the condition of an `if` expression and handles the `then` token. // -// if expr then ... +// if expr then <...> // ^~~~ // 1. Expr // 2. IfExprFinishThen // -// if expr ??? +// if expr // ^ // (state done) CARBON_PARSE_STATE(IfExprFinishCondition) @@ -670,12 +670,12 @@ CARBON_PARSE_STATE(IfExprFinishCondition) // Completes the first alternative in an `if` expression and handles the `else` // token. // -// if expr then expr else ... +// if expr then expr else <...> // ^~~~ // 1. Expr // 2. IfExprFinishElse // -// if expr then expr ??? +// if expr then expr // ^ // (state done) CARBON_PARSE_STATE(IfExprFinishThen) @@ -691,8 +691,8 @@ CARBON_PARSE_STATE(IfExprFinishElse) // // if expr then expr else expr // ^ -// if ??? -// ^ +// if +// ^ // (state done) CARBON_PARSE_STATE(IfExprFinish) @@ -700,11 +700,11 @@ CARBON_PARSE_STATE(IfExprFinish) // an expression. // TODO: Also a `require` declaration? // -// expr where .designator = ... +// expr where .designator = <...> // ^~~~~~~~~~~~~ // 1. Expr // 2. RequirementOperatorFinish -// expr where ... +// expr where <...> // ^ // 1. Expr // 2. RequirementOperator @@ -712,11 +712,11 @@ CARBON_PARSE_STATE(RequirementBegin) // Handles a requirement operator in a `where` expression. // -// expr where expr impls ... +// expr where expr impls <...> // ^~~~ -// expr where expr = ... +// expr where expr = <...> // ^ -// expr where expr == ... +// expr where expr == <...> // ^~ // 1. Expr // 2. RequirementOperatorFinish @@ -752,8 +752,8 @@ CARBON_PARSE_STATE(WhereFinish) // // expr ; // ^ -// expr ??? ; -// ^~~~~ +// expr ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(ExprStatementFinish) @@ -768,7 +768,7 @@ CARBON_PARSE_STATE(FriendDecl) // Handles a function's introducer. // -// fn ... +// fn <...> // ^ // 1. DeclNameAndParams // 2. FunctionAfterParams @@ -776,7 +776,7 @@ CARBON_PARSE_STATE(FunctionIntroducer) // Handles a lambda's introducer. // -// fn ... +// fn <...> // ^ // 1. LambdaIntroducer // 2. LambdaAfterIntroducer @@ -784,70 +784,70 @@ CARBON_PARSE_STATE(LambdaIntroducer) // Handles processing of a lambda after the introducer. // -// fn [ ... ] ... +// fn [ <...> ] <...> // ^ // 1. PatternListAsImplicit // 2. LambdaAfterImplicitParams // -// fn ( ... ) ... +// fn ( <...> ) <...> // ^ // 1. PatternListAsExplicit // 2. LambdaAfterParams // -// fn ... +// fn <...> // ^ // 1. LambdaAfterParams CARBON_PARSE_STATE(LambdaAfterIntroducer) // Handles processing of a lambda after implicit parameters. // -// fn [ ... ] ( ... ) ... -// ^ +// fn [ <...> ] ( <...> ) <...> +// ^ // 1. PatternListAsExplicit // 2. LambdaAfterParams // -// fn [ ... ] ... -// ^ +// fn [ <...> ] <...> +// ^ // 1. LambdaAfterParams CARBON_PARSE_STATE(LambdaAfterImplicitParams) // Handles processing of a lambda after optional parameters. // -// fn ... -> ... -// ^ +// fn <...> -> <...> +// ^ // 1. FunctionReturnTypeFinish (Reused) // 2. LambdaBody // -// fn ... => ... -// ^ +// fn <...> => <...> +// ^ // 1. Expr // 2. LambdaBodyFinish // -// fn ... { ... } -// ^ +// fn <...> { <...> } +// ^ // 1. StatementScopeLoop // 2. LambdaBodyFinish CARBON_PARSE_STATE(LambdaAfterParams) // Handles processing of a lambda body. // -// fn ... -> ... { ... } -// ^ +// fn <...> -> <...> { <...> } +// ^ // 1. StatementScopeLoop // 2. LambdaBodyFinish // -// fn ... -> ... => ... -// ^ +// fn <...> -> <...> => <...> +// ^ // 1. Expr // 2. LambdaBodyFinish CARBON_PARSE_STATE(LambdaBody) // Finishes a lambda expression. // -// fn ... } -// ^ -// fn ... => expr -// ^ +// fn <...> } +// ^ +// fn <...> => expr +// ^ // (state done) CARBON_PARSE_STATE(LambdaBodyFinish) @@ -855,67 +855,67 @@ CARBON_PARSE_STATE(LambdaBodyFinish) // possibility a `->` return type is there. Always enqueues signature finish // handling. // -// fn F(...) -> ... -// ^~ +// fn F(<...>) -> <...> +// ^~ // 1. Expr // 2. FunctionReturnTypeFinish // 3. FunctionSignatureFinish // -// fn F(...) ->? ... -// ^~~ +// fn F(<...>) ->? <...> +// ^~~ // 1. Expr // 2. FunctionReturnFormFinish // 3. FunctionSignatureFinish // -// fn F(...) ... -// ^ +// fn F(<...>) <...> +// ^ // 1. FunctionSignatureFinish CARBON_PARSE_STATE(FunctionAfterParams) // Finishes a function return type. // -// fn F(...) -> expr ... -// ^ +// fn F(<...>) -> expr <...> +// ^ // (state done) CARBON_PARSE_STATE(FunctionReturnTypeFinish) // Finishes a function return form. // -// fn F(...) ->? expr ... -// ^ +// fn F(<...>) ->? expr <...> +// ^ // (state done) CARBON_PARSE_STATE(FunctionReturnFormFinish) // Finishes a function signature. If it's a declaration, the function is done; // otherwise, this also starts definition processing. // -// fn ... ; -// ^ +// fn <...> ; +// ^ // (state done) // -// fn ... { -// ^ +// fn <...> { +// ^ // 1. StatementScopeLoop // 2. FunctionDefinitionFinish // -// fn ... ??? ; -// ^~~~~ +// fn <...> ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(FunctionSignatureFinish) // Finishes a function definition. // -// fn ... } -// ^ -// fn ... ; -// ^ +// fn <...> } +// ^ +// fn <...> ; +// ^ // (state done) CARBON_PARSE_STATE(FunctionDefinitionFinish) // Finishes a function with a terse body. // -// fn ... => expr ; -// ^ +// fn <...> => expr ; +// ^ // (state done) CARBON_PARSE_STATE(FunctionTerseBodyFinish) @@ -940,8 +940,8 @@ CARBON_PARSE_STATE(ExportNameFinish) // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // import library "libname" ; // ^~~~~~~~~~~~~~~~~~~ -// import ??? ; -// ^~~~~ +// import ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(Import) @@ -949,14 +949,14 @@ CARBON_PARSE_STATE(Import) // // library "libname" ; // ^~~~~~~~~~~ -// library ??? ; -// ^~~~~ +// library ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(Library) // Handles `match_first` and opens the block. // -// match_first { ... +// match_first { <...> // ^~~~~~~~~~~~~ // 1. DeclScopeLoopAsRegular // 2. MatchFirstFinish @@ -964,14 +964,14 @@ CARBON_PARSE_STATE(MatchFirst) // Handles closing the `match_first` block. // -// match_first { ... } -// ^ +// match_first { <...> } +// ^ // (state done) CARBON_PARSE_STATE(MatchFirstFinish) // Handles `namespace`. // -// namespace ... +// namespace <...> // ^ // 1. DeclNameAndParams // 2. NamespaceFinish @@ -979,10 +979,10 @@ CARBON_PARSE_STATE(Namespace) // Handles `namespace` after the name. // -// namespace ... ; -// ^ -// namespace ... ??? ; -// ^~~~~ +// namespace <...> ; +// ^ +// namespace <...> ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(NamespaceFinish) @@ -990,14 +990,14 @@ CARBON_PARSE_STATE(NamespaceFinish) // // package pkgname [library "libname"] ; // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// package ??? ; -// ^~~~~ +// package ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(Package) // Handles `alias` after the introducer. // -// alias ... +// alias <...> // ^ // 1. DeclNameAndParams // 2. AliasInitializer @@ -1005,21 +1005,21 @@ CARBON_PARSE_STATE(Alias) // Handles `alias` after the name. // -// alias ... = ... ; -// ^ +// alias <...> = <...> ; +// ^ // 1. Expr // 2. AliasFinish // -// alias ??? +// alias // ^ // (state done) CARBON_PARSE_STATE(AliasAfterName) // Handles `alias` at the end. // -// alias ... ; -// ^ -// alias ??? +// alias <...> ; +// ^ +// alias // ^ // (state done) CARBON_PARSE_STATE(AliasFinish) @@ -1028,20 +1028,20 @@ CARBON_PARSE_STATE(AliasFinish) // whether it is part of an implicit parameter list, struct pattern or a tuple // pattern. // -// ... +// <...> // ^ // 1. Pattern // 2. PatternListElementCheckForDefaultValue // 2. PatternListElementFinishAs(Tuple|Struct|Explicit|Implicit) // -// .foo = ... (variant is Struct) +// .foo = <...> (variant is Struct) // ^ // 1. PeriodAsStruct // 2. StructPatternFieldAfterDesignator // 3. PatternListElementCheckForDefaultValue // 4. PatternListElementFinishAsStruct // -// _ ... (variant is Struct) +// _ <...> (variant is Struct) // ^ // 1. StructPatternUnderscore // 2. PatternListElementFinishAsStruct @@ -1052,21 +1052,21 @@ CARBON_PARSE_STATE_VARIANTS4(PatternListElement, Tuple, Struct, Explicit, // this state checks for the `=` and if present parses it before moving on // to finish the list element. // -// ... = ... -// ^ +// <...> = <...> +// ^ // 1. Expr // 2. PatternListElementFinishDefaultValue // -// ... -// ^ +// <...> +// ^ // (state done) CARBON_PARSE_STATE(PatternListElementCheckForDefaultValue) // After parsing the default value Expr this state attaches that Expr // as a default value to the pattern. // -// ... = ... -// ^ +// <...> = <...> +// ^ // (state done) CARBON_PARSE_STATE(PatternListElementFinishDefaultValue) @@ -1074,26 +1074,26 @@ CARBON_PARSE_STATE(PatternListElementFinishDefaultValue) // optional trailing `,`. If there are more patterns, enqueues another // pattern parsing state. // -// ... , ) (variant is Tuple) -// ^ +// <...> , ) (variant is Tuple) +// ^ // (state done) // SPECIAL: parent becomes PatternListFinishAsTuple // -// ... , } (variant is Struct) -// ^ +// <...> , } (variant is Struct) +// ^ // (state done) // -// ... , ] (variant is Implicit) -// ^ +// <...> , ] (variant is Implicit) +// ^ // (state done) // -// ... , ... -// ^ +// <...> , <...> +// ^ // 1. PatternListElementAs(Tuple|Struct|Explicit|Implicit) // SPECIAL (variant is Tuple): parent becomes PatternListFinishAsTuple // -// ... -// ^ +// <...> +// ^ // (state done) CARBON_PARSE_STATE_VARIANTS4(PatternListElementFinish, Tuple, Struct, Explicit, Implicit) @@ -1109,19 +1109,19 @@ CARBON_PARSE_STATE_VARIANTS4(PatternListElementFinish, Tuple, Struct, Explicit, // ^ // 1. PatternListFinishAs(Tuple|Struct|Explicit|Implicit) // -// ( ... ) (variant is Explicit) +// ( <...> ) (variant is Explicit) // ^ -// [ ... ] (variant is Implicit) +// [ <...> ] (variant is Implicit) // ^ // 1. PatternListElementAs(Explicit|Implicit) // 2. PatternListFinishAs(Explicit|Implicit) // -// ( ... ) (variant is Tuple) +// ( <...> ) (variant is Tuple) // ^ // 1. PatternListElementAsTuple // 2. PatternListFinishAsParen (SPECIAL: may be replaced) // -// { ... } (variant is Struct) +// { <...> } (variant is Struct) // ^ // 1. PatternListElementAsStruct // 2. PatternListFinishAsStruct @@ -1129,43 +1129,43 @@ CARBON_PARSE_STATE_VARIANTS4(PatternList, Tuple, Struct, Explicit, Implicit) // Handles processing of a parameter list `]`, `)` or `}`. // -// ( ... ) (variant is Paren, Tuple or Explicit) -// ^ -// [ ... ] (variant is Implicit) -// ^ -// { ... } (variant is Struct) -// ^ +// ( <...> ) (variant is Paren, Tuple or Explicit) +// ^ +// [ <...> ] (variant is Implicit) +// ^ +// { <...> } (variant is Struct) +// ^ // (state done) CARBON_PARSE_STATE_VARIANTS5(PatternListFinish, Paren, Tuple, Struct, Explicit, Implicit) // -// ... , -// ^ +// <...> , +// ^ // (state done) // -// ... } -// ^ +// <...> } +// ^ // (state done) CARBON_PARSE_STATE(StructPatternDesignatedFieldFinish) // Handles a struct pattern parameter after the initial designator. -// .foo = ... +// .foo = <...> // ^ // 1. Pattern // 2. StructPatternDesignatedFieldFinish // -// .foo ??? = ... -// ^~~~~ +// .foo = <...> +// ^~~~~~~ // 1. Pattern // 2. StructPatternDesignatedFieldFinish // -// .foo ??? , ... -// ^~~~ +// .foo , <...> +// ^~~~~~ // 1. StructPatternDesignatedFieldFinish // -// .foo ??? } ... -// ^~~~ +// .foo } <...> +// ^~~~~~ // 1. StructPatternDesignatedFieldFinish CARBON_PARSE_STATE(StructPatternFieldAfterDesignator) @@ -1174,11 +1174,11 @@ CARBON_PARSE_STATE(StructPatternFieldAfterDesignator) // ^ // (state done) // -// _ : ??? +// _ : // ^ // 1. BindingPattern // -// _ :? ??? +// _ :? // ^ // 1. BindingPattern CARBON_PARSE_STATE(StructPatternUnderscore) @@ -1189,9 +1189,9 @@ CARBON_PARSE_STATE(StructPatternUnderscore) // ^ // 1. ParenConditionAs(If|While|Match)Finish // -// if/while/match ( ... ) +// if/while/match ( <...> ) // ^ -// if/while/match ??? +// if/while/match // ^ // 1. Expr // 2. ParenConditionAs(If|While|Match)Finish @@ -1203,23 +1203,23 @@ CARBON_PARSE_STATE_VARIANTS3(ParenCondition, If, While, Match) // ^ // if/while/match { // ^ -// if/while/match ??? { -// ^ +// if/while/match { +// ^ // (state done) CARBON_PARSE_STATE_VARIANTS3(ParenConditionFinish, If, While, Match) // Handles compound member access `(` after `->` or `.` // -// ( ... ) +// ( <...> ) // ^ // 1. Expr // 2. OnlyParenExprFinish CARBON_PARSE_STATE(OnlyParenExpr) -// Handles the `)` after `->(`... or `.(`... +// Handles the `)` after `->(` <...> or `.(` <...> // -// ( ... ) -// ^ +// ( <...> ) +// ^ CARBON_PARSE_STATE(OnlyParenExprFinish) // Handles the `(` of an expression that's presumed to be a parenthesized @@ -1229,7 +1229,7 @@ CARBON_PARSE_STATE(OnlyParenExprFinish) // ^ // 1. TupleLiteralFinish // -// ( ... ) +// ( <...> ) // ^ // 1. Expr // 2. ExprAfterOpenParenFinish @@ -1238,77 +1238,77 @@ CARBON_PARSE_STATE(ParenExpr) // Handles the `)` of a tuple literal. // -// ( ... ) -// ^ +// ( <...> ) +// ^ // (state done) CARBON_PARSE_STATE(TupleLiteralFinish) // Handles the end of an expression following an open parenthesis. // -// ( ... , ) -// ^ +// ( <...> , ) +// ^ // (state done) // SPECIAL: parent becomes TupleLiteralFinish // -// ( ... , ... ) -// ^ +// ( <...> , <...> ) +// ^ // 1. Expr // 2. TupleLiteralElementFinish // SPECIAL: parent becomes TupleLiteralFinish // -// ( ... ) -// ^ +// ( <...> ) +// ^ // (state done) CARBON_PARSE_STATE(ExprAfterOpenParenFinish) // Handles the end of an expression that is known to be an element of a tuple // literal expression. // -// ( ... , ) -// ^ +// ( <...> , ) +// ^ // (state done) // -// ( ... , ... ) -// ^ +// ( <...> , <...> ) +// ^ // 1. Expr // 2. TupleLiteralElementFinish // -// ( ... ) -// ^ +// ( <...> ) +// ^ // (state done) CARBON_PARSE_STATE(TupleLiteralElementFinish) // Handles the `)` of a parenthesized single expression. // -// ( ... ) -// ^ +// ( <...> ) +// ^ // (state done) CARBON_PARSE_STATE(ParenExprFinish) // Handles processing of a pattern. // -// ( ... ) +// ( <...> ) // ^ // 1. PatternListAsTuple // -// var ... +// var <...> // ^ // // 1. VariablePattern // -// unused ... +// unused <...> // ^ // 1. UnusedPattern // // [identifier|self] [:|:!|:?] // ^ -// template ... +// template <...> // ^ -// ref ... +// ref <...> // ^ // 1. BindingPattern // -// ... +// <...> // ^ // 1. Expr // 2. ExprPattern @@ -1316,7 +1316,7 @@ CARBON_PARSE_STATE(Pattern) // Tracks that we are parsing an expression as an expression pattern. // -// ... +// <...> // ^ // (state done) CARBON_PARSE_STATE(ExprPattern) @@ -1327,34 +1327,34 @@ CARBON_PARSE_STATE(ExprPattern) // TODO: treat `ref` as a unary pattern operator in order to avoid ambiguity // with `ref` in expression patterns. See issue #6342. // -// [ref] name: ... +// [ref] name: <...> // ^~~~~~~~~~~ -// [ref] self: ... +// [ref] self: <...> // ^~~~~~~~~~~ -// [ref] _: ... +// [ref] _: <...> // ^~~~~~~~ // 1. Expr // 2. BindingPatternFinishAsRegular // -// [template] name:! ... +// [template] name:! <...> // ^~~~~~~~~~~~~~~~~ -// [template] self:! ... +// [template] self:! <...> // ^~~~~~~~~~~~~~~~~ -// [template] _:! ... +// [template] _:! <...> // ^~~~~~~~~~~~~~ // 1. Expr // 2. BindingPatternFinishAsGeneric // -// name:? ... +// name:? <...> // ^~~~~~ -// self:? ... +// self:? <...> // ^~~~~~ -// _:? ... +// _:? <...> // ^~~ // 1. Expr // 2. BindingPatternFinishAsForm // -// ??? +// // ^ // 1. BindingPatternFinishAsRegular CARBON_PARSE_STATE(BindingPattern) @@ -1368,7 +1368,7 @@ CARBON_PARSE_STATE_VARIANTS3(BindingPatternFinish, Generic, Regular, Form) // Handles `var` in a pattern context. // -// var ... +// var <...> // ^~~ // 1. Pattern // 2. FinishVariablePattern @@ -1376,14 +1376,14 @@ CARBON_PARSE_STATE(VariablePattern) // Finishes `var` in a pattern context. // -// var ... -// ^ +// var <...> +// ^ // (state done) CARBON_PARSE_STATE(FinishVariablePattern) // Handles `unused` in a pattern context. // -// unused ... +// unused <...> // ^~~~~~ // 1. Pattern // 2. FinishUnusedPattern @@ -1391,8 +1391,8 @@ CARBON_PARSE_STATE(UnusedPattern) // Finishes `unused` in a pattern context. // -// unused ... -// ^ +// unused <...> +// ^ // (state done) CARBON_PARSE_STATE(FinishUnusedPattern) @@ -1400,44 +1400,49 @@ CARBON_PARSE_STATE(FinishUnusedPattern) // can also be used for error recovery where we expect a statement block and // are missing braces. // -// break ... +// break <...> // ^~~~~ // 1. StatementBreakFinish // -// continue ... +// continue <...> // ^~~~~~~~ // 1. StatementContinueFinish // -// for ... +// for <...> // ^~~ // 1. StatementForHeader // 2. StatementForFinish // -// if ... +// if <...> // ^ // 1. StatementIf // -// return ... +// return <...> // ^ // 1. StatementReturn // -// returned ... +// returned <...> // ^ // 1. VarAsReturned // -// while ... +// while <...> // ^ // 1. StatementWhile // -// ... +// <...> // ^ // 1. Expr // 2. ExprStatementFinish // -// match ... +// match <...> // ^ // 1. MatchIntroducer // +// ... <...> +// ^~~ +// 1. Statement +// 2. StatementPackExpansionFinish +// // // ^ // 1. Decl @@ -1459,9 +1464,9 @@ CARBON_PARSE_STATE(StatementContinueFinish) // Handles `for` processing of `(`, proceeding to a pattern before continuing. // -// for ( ... ) +// for ( <...> ) // ^ -// for ??? +// for // ^ // 1. Pattern // 2. StatementForHeaderIn @@ -1470,33 +1475,33 @@ CARBON_PARSE_STATE(StatementForHeader) // Handles `for` processing of `in`, proceeding to an expression before // continuing. // -// for ( ... in ... ) -// ^~ -// for ( ... : ... ) -// ^ -// for ( ... ??? ) -// ^ +// for ( <...> in <...> ) +// ^~ +// for ( <...> : <...> ) +// ^ +// for ( <...> ) +// ^ // 1. Expr // 2. StatementForHeaderFinish CARBON_PARSE_STATE(StatementForHeaderIn) // Handles `for` processing of `)`, proceeding to the statement block. // -// for ( ... ) ... -// ^ +// for ( <...> ) <...> +// ^ // 1. CodeBlock CARBON_PARSE_STATE(StatementForHeaderFinish) // Handles `for` processing after the final `}`. // -// for ( ... ) { ... } -// ^ +// for ( <...> ) { <...> } +// ^ // (state done) CARBON_PARSE_STATE(StatementForFinish) // Handles `if` processing at the start. // -// if ... +// if <...> // ^~ // 1. ParenConditionAsIf // 2. StatementIfConditionFinish @@ -1505,8 +1510,8 @@ CARBON_PARSE_STATE(StatementIf) // Handles `if` processing between the condition and start of the first code // block. // -// if ( ... ) ... -// ^ +// if ( <...> ) <...> +// ^ // 1. CodeBlock // 2. StatementIfThenBlockFinish CARBON_PARSE_STATE(StatementIfConditionFinish) @@ -1514,24 +1519,24 @@ CARBON_PARSE_STATE(StatementIfConditionFinish) // Handles `if` processing after the end of the first code block, with the // optional `else`. // -// if ( ... ) { ... } else if ... -// ^~~~ +// if ( <...> ) { <...> } else if <...> +// ^~~~ // 1. StatementIf // 2. StatementIfElseBlockFinish // -// if ( ... ) { ... } else ... -// ^~~~ +// if ( <...> ) { <...> } else <...> +// ^~~~ // 1. CodeBlock // 2. StatementIfElseBlockFinish // -// if ( ... ) { ... } ... +// if ( <...> ) { <...> } <...> // (state done) CARBON_PARSE_STATE(StatementIfThenBlockFinish) // Handles `if` processing after a provided `else` code block. // -// if ( ... ) { ... } else { ... } -// ^ +// if ( <...> ) { <...> } else { <...> } +// ^ // (state done) CARBON_PARSE_STATE(StatementIfElseBlockFinish) @@ -1541,11 +1546,11 @@ CARBON_PARSE_STATE(StatementIfElseBlockFinish) // ^~~~~~ // 1. StatementReturnFinish // -// return var ... +// return var <...> // ^~~~~~~~~~ // 1. StatementReturnFinish // -// return ... +// return <...> // ^~~~~~ // 1. Expr // 2. StatementReturnFinish @@ -1553,26 +1558,33 @@ CARBON_PARSE_STATE(StatementReturn) // Handles `return` processing at the `;`. // -// return ... ; -// ^ +// return <...> ; +// ^ // (state done) CARBON_PARSE_STATE(StatementReturnFinish) +// Handles a pack expansion statement after its body. +// +// ... +// ^ +// (state done) +CARBON_PARSE_STATE(StatementPackExpansionFinish) + // Handles processing of statements within a scope. // -// { ... } -// ^ +// { <...> } +// ^ // (state done) // -// { ... ... } -// ^ +// { <...> <...> } +// ^ // 1. Statement // 2. StatementScopeLoop CARBON_PARSE_STATE(StatementScopeLoop) // Handles `while` processing. // -// while ... +// while <...> // ^~~~~ // 1. ParenConditionAsWhile // 2. StatementWhileConditionFinish @@ -1580,30 +1592,30 @@ CARBON_PARSE_STATE(StatementWhile) // Handles `while` processing between the condition and start of the code block. // -// while ( ... ) ... -// ^ +// while ( <...> ) <...> +// ^ // 1. CodeBlock // 2. StatementWhileBlockFinish CARBON_PARSE_STATE(StatementWhileConditionFinish) // Handles `while` processing after the end of the code block. // -// while ( ... ) { ... } -// ^ +// while ( <...> ) { <...> } +// ^ // (state done) CARBON_PARSE_STATE(StatementWhileBlockFinish) // Handles parsing after the declaration scope of a type. // -// class/impl/interface/constraint ... { ... } -// ^ +// class/impl/interface/constraint <...> { <...> } +// ^ // (state done) CARBON_PARSE_STATE_VARIANTS4(DeclDefinitionFinish, Class, Impl, Interface, NamedConstraint) // Handles processing of a type after its introducer. // -// class/interface/constraint ... +// class/interface/constraint <...> // ^ // 1. DeclNameAndParams // 2. DeclOrDefinitionAs(Class|Interface|NamedConstraint) @@ -1612,15 +1624,15 @@ CARBON_PARSE_STATE_VARIANTS3(TypeAfterIntroducer, Class, Interface, // Handles processing of a type after its optional parameters. // -// class/impl/interface/constraint name ( ... ) { -// ^ +// class/impl/interface/constraint name ( <...> ) { +// ^ // 1. DeclScopeLoopAs(Class|Regular) // 2. DeclDefinitionFinishAs(Class|Impl|Interface|NamedConstraint) // -// class/impl/interface/constraint name ( ... ) ; -// ^ -// class/impl/interface/constraint name ( ... ) ??? -// ^ +// class/impl/interface/constraint name ( <...> ) ; +// ^ +// class/impl/interface/constraint name ( <...> ) +// ^ // (state done) CARBON_PARSE_STATE_VARIANTS4(DeclOrDefinition, Class, Impl, Interface, NamedConstraint) @@ -1637,8 +1649,8 @@ CARBON_PARSE_STATE(AdaptAfterIntroducer) // // adapt T ; // ^ -// adapt T ??? ; -// ^~~~~ +// adapt T ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(AdaptDecl) @@ -1648,8 +1660,8 @@ CARBON_PARSE_STATE(AdaptDecl) // ^ // 1. Expr // 2. BaseDecl -// base ??? ; -// ^~~ +// base ; +// ^~~~~ // (state done) CARBON_PARSE_STATE(BaseAfterIntroducer) @@ -1657,23 +1669,23 @@ CARBON_PARSE_STATE(BaseAfterIntroducer) // // base: B ; // ^ -// base: B ??? ; -// ^~~~~ +// base: B ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(BaseDecl) // Handles processing of an `impl...as` declaration after the introducer. // -// impl forall [ ... +// impl forall [ <...> // ^~~~~~ // 1. PatternListAsImplicit // 2. ImplAfterForall // 3. DeclOrDefinitionAsImpl -// impl as ... +// impl as <...> // ^~ // 1. Expr // 2. DeclOrDefinitionAsImpl -// impl TypeExpression as ... +// impl TypeExpression as <...> // ^ // 1. Expr // 2. ImplBeforeAs @@ -1683,11 +1695,11 @@ CARBON_PARSE_STATE(ImplAfterIntroducer) // Handles processing of an `impl forall` declaration after the implicit // parameter list. // -// impl forall [ ... ] as ... -// ^~ +// impl forall [ <...> ] as <...> +// ^~ // 1. Expr -// impl forall [ ... ] TypeExpression as ... -// ^ +// impl forall [ <...> ] TypeExpression as <...> +// ^ // 1. Expr // 2. ImplBeforeAs CARBON_PARSE_STATE(ImplAfterForall) @@ -1695,18 +1707,18 @@ CARBON_PARSE_STATE(ImplAfterForall) // Handles processing of the `as` in an `impl` declaration after the type // expression. // -// impl TypeExpression as ... +// impl TypeExpression as <...> // ^~ // 1. Expr CARBON_PARSE_STATE(ImplBeforeAs) // Handles processing of a `require...impls` declaration after the introducer. // -// require impls ... +// require impls <...> // ^~~~~ // 1. Expr // 2. RequireDecl -// require TypeExpression impls ... +// require TypeExpression impls <...> // ^ // 1. Expr // 2. RequireBeforeImpls @@ -1716,7 +1728,7 @@ CARBON_PARSE_STATE(RequireAfterIntroducer) // Handles processing of the `impls` in a `require` declaration after the type // expression. // -// require TypeExpression impls ... +// require TypeExpression impls <...> // ^~~~~ // 1. Expr CARBON_PARSE_STATE(RequireBeforeImpls) @@ -1730,7 +1742,7 @@ CARBON_PARSE_STATE(RequireDecl) // Handles processing of an `observe` declaration after the introducer. // -// observe TypeExpression ... +// observe TypeExpression <...> // ^ // 1. Expr // 2. ObserveOperator @@ -1738,11 +1750,11 @@ CARBON_PARSE_STATE(ObserveAfterIntroducer) // Handles processing of an operator in an `observe` declaration. // -// observe TypeExpression == TypeExpression ... +// observe TypeExpression == TypeExpression <...> // ^~ // 1. Expr // 2. ObserveFinishOperator -// observe TypeExpression impls ... +// observe TypeExpression impls <...> // ^~~~~ // 1. Expr // 2. ObserveFinishOperator @@ -1750,7 +1762,7 @@ CARBON_PARSE_STATE(ObserveOperator) // Finishes an operator in an `observe` declaration. // -// observe TypeExpression == TypeExpression ... +// observe TypeExpression == TypeExpression <...> // ^ // 1. ObserveOperator // observe TypeExpression == TypeExpression ; @@ -1760,56 +1772,56 @@ CARBON_PARSE_STATE(ObserveFinishOperator) // Handles processing of a completed `observe` declaration. // -// observe ... ; -// ^ +// observe <...> ; +// ^ // (state done) CARBON_PARSE_STATE(ObserveDecl) // Handles the start of a `var` or `returned var` in a non-class context. // -// var ... (variant is Regular) +// var <...> (variant is Regular) // ^ // 1. Pattern // 2. VarAfterPattern // 3. VarFinish // -// returned var ... (variant is Returned) +// returned var <...> (variant is Returned) // ^~~~~~~~~~~~ // 1. Pattern // 2. VarAfterPattern // 3. VarFinish // -// returned ??? ; (variant is Returned) -// ^~~~~~~~~~~~~~ +// returned ; (variant is Returned) +// ^~~~~~~~~~~~~~~~ // (state done) CARBON_PARSE_STATE_VARIANTS2(Var, Regular, Returned) // Handles `var` after the pattern, either followed by an initializer or the // semicolon. // -// var ... = ... -// ^ -// var ... ??? = ... -// ^~~~~ +// var <...> = <...> +// ^ +// var <...> = <...> +// ^~~~~~~ // 1. Expr // -// var ... ... -// ^ +// var <...> <...> +// ^ // (state done) CARBON_PARSE_STATE(VarAfterPattern) // Handles `var` parsing at the end. // -// var ... ; -// ^ -// var ... ??? ; -// ^~~~~ +// var <...> ; +// ^ +// var <...> ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE(VarFinish) // Handles the start of a `let`. // -// let ... +// let <...> // ^ // 1. Pattern // 2. LetAfterPattern @@ -1820,44 +1832,44 @@ CARBON_PARSE_STATE(Let) // initializer is required except in an associated constant declaration, but // that is enforced by check. // -// let ... = ... -// ^ -// let ... ??? = ... -// ^~~~~ +// let <...> = <...> +// ^ +// let <...> = <...> +// ^~~~~~~ // 1. Expr // -// let ... ; -// ^ -// let ... ??? ; -// ^~~ +// let <...> ; +// ^ +// let <...> ; +// ^~~~~ // (state done) CARBON_PARSE_STATE_VARIANTS2(LetAfterPattern, Regular, AssociatedConstant) // Handles `let` parsing at the end. // -// let ... ; -// ^ -// let ... ??? ; -// ^~~~~ +// let <...> ; +// ^ +// let <...> ; +// ^~~~~~~ // (state done) CARBON_PARSE_STATE_VARIANTS2(LetFinish, Regular, AssociatedConstant) // Handles the start of an associated constant declaration (`let` in an // interface context). // -// let name :! ... +// let name :! <...> // ^~~~~~~ // 1. AssociatedConstantFinish -// let ??? ; -// ^~~~~ -// let name ??? ; -// ^~~~~~~~~ +// let ; +// ^~~~~~~ +// let name ; +// ^~~~~~~~~~~~ // (state done) CARBON_PARSE_STATE(AssociatedConstant) // Handles a choice's introducer. // -// choice ... +// choice <...> // ^~~~~~ // 1. DeclNameAndParams // 2. ChoiceDefinitionStart @@ -1866,26 +1878,26 @@ CARBON_PARSE_STATE(ChoiceIntroducer) // Handles processing of a choice after its optional parameters. // -// choice name ... {} -// ^ +// choice name <...> {} +// ^ // (state done) // -// choice name ... { ... } -// ^ +// choice name <...> { <...> } +// ^ // 1. ChoiceAlternative // -// choice name ... ??? -// ^ +// choice name <...> +// ^ // (state done) CARBON_PARSE_STATE(ChoiceDefinitionStart) // Starts alternative parsing. // -// name( ... ) +// name( <...> ) // ^~~~ // 1. ParamListAsRegular // 2. ChoiceAlternativeFinish -// name ... +// name <...> // ^~~~ // 1. ChoiceAlternativeFinish CARBON_PARSE_STATE(ChoiceAlternative) @@ -1893,29 +1905,29 @@ CARBON_PARSE_STATE(ChoiceAlternative) // Finishes parsing a choice's alternative, including the optional trailing `,`. // If there are more alternatives, enqueues another alternative parsing state. // -// ... , } -// ^ +// <...> , } +// ^ // (state done) // -// ... , ... -// ^ +// <...> , <...> +// ^ // 1. ChoiceAlternative // -// ... -// ^ +// <...> +// ^ // (state done) CARBON_PARSE_STATE(ChoiceAlternativeFinish) // Finishes a choice definition. // -// choice ... } -// ^ +// choice <...> } +// ^ // (state done) CARBON_PARSE_STATE(ChoiceDefinitionFinish) // Handles `match` introducer. // -// match ... +// match <...> // ^~~~~ // 1. ParenConditionAsMatch // 2. MatchConditionFinish @@ -1923,43 +1935,43 @@ CARBON_PARSE_STATE(MatchIntroducer) // Handles `match` cases block start after the condition. // -// match (...) { ... } -// ^ +// match (<...>) { <...> } +// ^ // 1. MatchCaseLoop // 2. MatchStatementFinish // -// match (...) ??? -// ^ +// match (<...>) +// ^ // (state done) CARBON_PARSE_STATE(MatchConditionFinish) // Handles `match` cases. // -// match (...) { case ...} -// ^ +// match (<...>) { case <...>} +// ^ // 1. MatchCaseIntroducer // 2. MatchCaseLoop -// match (...) { default ...} -// ^ +// match (<...>) { default <...>} +// ^ // 1. MatchDefaultIntroducer // 2. MatchCaseLoopAfterDefault CARBON_PARSE_STATE(MatchCaseLoop) // Handles `match` `case` introducer. // -// match (...) { case ...} -// ^~~~ +// match (<...>) { case <...>} +// ^~~~ // 1. Pattern // 2. MatchCaseAfterPattern CARBON_PARSE_STATE(MatchCaseIntroducer) // Handles `match` case after pattern. // -// match (...) { case ... => ... } -// ^ +// match (<...>) { case <...> => <...> } +// ^ // 1. MatchCaseStart -// match (...) { case ... if (...) } -// ^~~~ +// match (<...>) { case <...> if (<...>) } +// ^~~~ // 1. Expr // 2. MatchCaseGuardFinish // 3. MatchCaseStart @@ -1967,73 +1979,73 @@ CARBON_PARSE_STATE(MatchCaseAfterPattern) // Handles `match` case guard closing parenthesis. // -// match (...) { case ... if (...) => ... } -// ^ +// match (<...>) { case <...> if (<...>) => <...> } +// ^ // (state done) CARBON_PARSE_STATE(MatchCaseGuardFinish) // Handles `match` case `=>` and `{` opening statements block. // -// match (...) { case ... => {...} } -// ^~~~ +// match (<...>) { case <...> => {<...>} } +// ^~~~ // 1. StatementScopeLoop // 2. MatchHandlerFinish // -// match (...) { case ... ??? } -// ^ +// match (<...>) { case <...> } +// ^ // (state done) // -// match (...) { case ... => ??? } -// ^ +// match (<...>) { case <...> => } +// ^ // (state done) CARBON_PARSE_STATE(MatchCaseStart) // Handles `match` default introducer, `=>` and `{` opening statements block. // -// match (...) { default => {...} } -// ^~~~~~~~~~~~ +// match (<...>) { default => {<...>} } +// ^~~~~~~~~~~~ // 1. StatementScopeLoop // 2. MatchHandlerFinish // -// match (...) { default ??? } -// ^ +// match (<...>) { default } +// ^ // (state done) // -// match (...) { default => ??? } -// ^ +// match (<...>) { default => } +// ^ // (state done) CARBON_PARSE_STATE(MatchDefaultIntroducer) // Handles `match` handler block closing `}`. // -// match (...) { case ... => {...} } -// ^ +// match (<...>) { case <...> => {<...>} } +// ^ // (state done) // -// match (...) { default => {...} } -// ^ +// match (<...>) { default => {<...>} } +// ^ // (state done) CARBON_PARSE_STATE(MatchHandlerFinish) // Handles `match` cases after the `default` case. // -// match (...) { default => {...} case ... } -// ^~~~ +// match (<...>) { default => {<...>} case <...> } +// ^~~~ // 1. MatchCaseLoopAfterDefault // -// match (...) { default => {...} default ... } -// ^~~~~~~ +// match (<...>) { default => {<...>} default <...> } +// ^~~~~~~ // 1. MatchCaseLoopAfterDefault // -// match (...) { default => {...} } -// ^ +// match (<...>) { default => {<...>} } +// ^ // (state done) CARBON_PARSE_STATE(MatchCaseLoopAfterDefault) // Finishes `match` statement. // -// match (...) {...} -// ^ +// match (<...>) {<...>} +// ^ // (state done) CARBON_PARSE_STATE(MatchStatementFinish) diff --git a/toolchain/parse/testdata/variadics/expand.carbon b/toolchain/parse/testdata/variadics/expand.carbon new file mode 100644 index 000000000000..73da37cf1611 --- /dev/null +++ b/toolchain/parse/testdata/variadics/expand.carbon @@ -0,0 +1,196 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/variadics/expand.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/variadics/expand.carbon + +// --- basic.carbon + +var a: auto = expand x; + +// --- precedence.carbon + +// `expand` has the same precedence as prefix `*`. +var a: auto = expand x.y; +var b: auto = expand x.(0); +var c: auto = expand F(); +var d: auto = expand x + 1; +var e: auto = expand x * 2; +var f: auto = expand *x; +var g: auto = *expand x; +var h: auto = expand expand x; +var i: auto = -expand x; + +// --- fail_under_not.carbon + +// Like prefix `*`, `expand` requires parentheses under `not`. +// CHECK:STDERR: fail_under_not.carbon:[[@LINE+4]]:19: error: parentheses are required around this unary `expand` operator [UnaryOperatorRequiresParentheses] +// CHECK:STDERR: var a: auto = not expand x; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +var a: auto = not expand x; + +// --- fail_as_postfix.carbon + +// CHECK:STDERR: fail_as_postfix.carbon:[[@LINE+4]]:17: error: `var` declarations must end with a `;` [ExpectedDeclSemi] +// CHECK:STDERR: var a: auto = x expand; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +var a: auto = x expand; + +// CHECK:STDOUT: - filename: basic.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'a' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: precedence.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'a' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ├─IdentifierNameNotBeforeSignature 'y' +// CHECK:STDOUT: │ │ ╭─MemberAccessExpr '.' +// CHECK:STDOUT: │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'b' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ │ ╭─ParenExprStart '(' +// CHECK:STDOUT: │ │ │ ├─IntLiteral '0' +// CHECK:STDOUT: │ │ ├─ParenExpr ')' +// CHECK:STDOUT: │ │ ╭─MemberAccessExpr '.' +// CHECK:STDOUT: │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'c' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'F' +// CHECK:STDOUT: │ │ ╭─CallExprStart '(' +// CHECK:STDOUT: │ │ ╭─CallExpr ')' +// CHECK:STDOUT: │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'd' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ ├─IntLiteral '1' +// CHECK:STDOUT: │ ├─InfixOperatorPlus '+' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'e' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ ├─IntLiteral '2' +// CHECK:STDOUT: │ ├─InfixOperatorStar '*' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'f' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorStar '*' +// CHECK:STDOUT: │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'g' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ ├─PrefixOperatorStar '*' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'h' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'i' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ ├─PrefixOperatorMinus '-' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: fail_under_not.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'a' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ ╭─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ ├─PrefixOperatorNot 'not' +// CHECK:STDOUT: ├─VariableDecl ';' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: fail_as_postfix.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ ╭─IdentifierNameNotBeforeSignature 'a' +// CHECK:STDOUT: │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ ├─IdentifierNameExpr 'x' +// CHECK:STDOUT: ├─VariableDecl ';' has_error +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) diff --git a/toolchain/parse/testdata/variadics/pack_expansion_statement.carbon b/toolchain/parse/testdata/variadics/pack_expansion_statement.carbon new file mode 100644 index 000000000000..3fc999e60208 --- /dev/null +++ b/toolchain/parse/testdata/variadics/pack_expansion_statement.carbon @@ -0,0 +1,197 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/variadics/pack_expansion_statement.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/variadics/pack_expansion_statement.carbon + +// --- expr_statement.carbon + +fn F() { + ... G(expand x); +} + +// --- var_statement.carbon + +fn F() { + ... var y: auto = expand x; +} + +// --- compound_statements.carbon + +fn F() { + ... if (expand c) { + G(expand x); + } else { + H(expand y); + } + ... while (expand c) {} + ... return; +} + +// --- nested.carbon + +fn F() { + ... ... G(expand x); +} + +// --- fail_missing_statement.carbon + +fn F() { + ... +// CHECK:STDERR: fail_missing_statement.carbon:[[@LINE+4]]:1: error: expected expression [ExpectedExpr] +// CHECK:STDERR: } +// CHECK:STDERR: ^ +// CHECK:STDERR: +} + +// --- fail_missing_semi.carbon + +fn F() { + ... G() +// CHECK:STDERR: fail_missing_semi.carbon:[[@LINE+4]]:1: error: expected `;` after expression statement [ExpectedExprSemi] +// CHECK:STDERR: } +// CHECK:STDERR: ^ +// CHECK:STDERR: +} + +// CHECK:STDOUT: - filename: expr_statement.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn' +// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F' +// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '(' +// CHECK:STDOUT: │ ├─ExplicitParamList ')' +// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─IdentifierNameExpr 'G' +// CHECK:STDOUT: │ │ │ ╭─CallExprStart '(' +// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ │ ╭─CallExpr ')' +// CHECK:STDOUT: │ │ ├─ExprStatement ';' +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: ├─FunctionDefinition '}' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: var_statement.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn' +// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F' +// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '(' +// CHECK:STDOUT: │ ├─ExplicitParamList ')' +// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─VariableIntroducer 'var' +// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'y' +// CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':' +// CHECK:STDOUT: │ │ │ │ ├─AutoTypeLiteral 'auto' +// CHECK:STDOUT: │ │ │ │ ╭─VarBindingPattern ':' +// CHECK:STDOUT: │ │ │ ├─VariablePattern 'var' +// CHECK:STDOUT: │ │ │ ├─VariableInitializer '=' +// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ ├─VariableDecl ';' +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: ├─FunctionDefinition '}' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: compound_statements.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn' +// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F' +// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '(' +// CHECK:STDOUT: │ ├─ExplicitParamList ')' +// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─IfConditionStart '(' +// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameExpr 'c' +// CHECK:STDOUT: │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ │ ╭─IfCondition ')' +// CHECK:STDOUT: │ │ │ │ ╭─CodeBlockStart '{' +// CHECK:STDOUT: │ │ │ │ │ ╭─IdentifierNameExpr 'G' +// CHECK:STDOUT: │ │ │ │ │ ╭─CallExprStart '(' +// CHECK:STDOUT: │ │ │ │ │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ │ │ │ ╭─CallExpr ')' +// CHECK:STDOUT: │ │ │ │ ├─ExprStatement ';' +// CHECK:STDOUT: │ │ │ ├─CodeBlock '}' +// CHECK:STDOUT: │ │ │ ├─IfStatementElse 'else' +// CHECK:STDOUT: │ │ │ │ ╭─CodeBlockStart '{' +// CHECK:STDOUT: │ │ │ │ │ ╭─IdentifierNameExpr 'H' +// CHECK:STDOUT: │ │ │ │ │ ╭─CallExprStart '(' +// CHECK:STDOUT: │ │ │ │ │ │ ╭─IdentifierNameExpr 'y' +// CHECK:STDOUT: │ │ │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ │ │ │ ╭─CallExpr ')' +// CHECK:STDOUT: │ │ │ │ ├─ExprStatement ';' +// CHECK:STDOUT: │ │ │ ├─CodeBlock '}' +// CHECK:STDOUT: │ │ ├─IfStatement 'if' +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─WhileConditionStart '(' +// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameExpr 'c' +// CHECK:STDOUT: │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ │ ╭─WhileCondition ')' +// CHECK:STDOUT: │ │ │ │ ╭─CodeBlockStart '{' +// CHECK:STDOUT: │ │ │ ├─CodeBlock '}' +// CHECK:STDOUT: │ │ ├─WhileStatement 'while' +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─ReturnStatementStart 'return' +// CHECK:STDOUT: │ │ ├─ReturnStatement ';' +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: ├─FunctionDefinition '}' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: nested.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn' +// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F' +// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '(' +// CHECK:STDOUT: │ ├─ExplicitParamList ')' +// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameExpr 'G' +// CHECK:STDOUT: │ │ │ │ ╭─CallExprStart '(' +// CHECK:STDOUT: │ │ │ │ │ ╭─IdentifierNameExpr 'x' +// CHECK:STDOUT: │ │ │ │ ├─PrefixOperatorExpand 'expand' +// CHECK:STDOUT: │ │ │ │ ╭─CallExpr ')' +// CHECK:STDOUT: │ │ │ ├─ExprStatement ';' +// CHECK:STDOUT: │ │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: ├─FunctionDefinition '}' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: fail_missing_statement.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn' +// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F' +// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '(' +// CHECK:STDOUT: │ ├─ExplicitParamList ')' +// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─InvalidParse '}' has_error +// CHECK:STDOUT: │ │ ├─ExprStatement '...' has_error +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: ├─FunctionDefinition '}' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) +// CHECK:STDOUT: - filename: fail_missing_semi.carbon +// CHECK:STDOUT: ╭─FileStart '' +// CHECK:STDOUT: │ ╭─FunctionIntroducer 'fn' +// CHECK:STDOUT: │ ├─IdentifierNameMaybeBeforeSignature 'F' +// CHECK:STDOUT: │ │ ╭─ExplicitParamListStart '(' +// CHECK:STDOUT: │ ├─ExplicitParamList ')' +// CHECK:STDOUT: │ ╭─FunctionDefinitionStart '{' +// CHECK:STDOUT: │ │ ╭─PackExpansionStart '...' +// CHECK:STDOUT: │ │ │ ╭─IdentifierNameExpr 'G' +// CHECK:STDOUT: │ │ │ ╭─CallExprStart '(' +// CHECK:STDOUT: │ │ │ ╭─CallExpr ')' +// CHECK:STDOUT: │ │ ├─ExprStatement ')' has_error +// CHECK:STDOUT: │ ├─PackExpansionStatement '...' +// CHECK:STDOUT: ├─FunctionDefinition '}' +// CHECK:STDOUT: ├─FileEnd '' +// CHECK:STDOUT: (root) diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index 55c46b6bd393..b2d50d323e7d 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -954,6 +954,25 @@ struct WhileStatement { CodeBlockId body; }; +// The start of a pack expansion: `...`. This marks the beginning of the +// expanded region. +using PackExpansionStart = + LeafNode; + +// A statement pack expansion: `... statement`. +struct PackExpansionStatement { + static constexpr auto Kind = NodeKind::PackExpansionStatement.Define( + {.category = NodeCategory::Statement, + .bracketed_by = PackExpansionStart::Kind, + .child_count = 2}); + + PackExpansionStartId start; + AnyStatementId body; + // This is a virtual token. The `...` token is owned by the + // PackExpansionStart node. + Lex::PeriodPeriodPeriodTokenIndex token; +}; + using MatchConditionStart = LeafNode;