From dd43bb92b5f0595bc1627ca2e85c1b5469dcb64e Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Mon, 4 Nov 2024 08:06:57 -0800 Subject: [PATCH] Refactor struct literal parse nodes. (#4470) Split StructComma into StructLiteralComma and StructTypeLiteralComma in order to easily differentiate handling (remains the same in this PR). Add "Literal" to StructField and StructTypeField because it feels inconsistent versus the other non-shared things. StructFieldDesignator remains shared between value literals and type literals. Note I probably would've made StructFieldDesignator non-shared too, but that'd require either a lookahead of 2 (to see the separator`) or a writeback after parsing the separator, neither of which felt especially crucial for this, when what I'm really trying to do is split type literal handling a little further. --- toolchain/check/handle_struct.cpp | 13 +++++++++--- toolchain/check/node_stack.h | 7 ++++--- toolchain/check/param_and_arg_refs_stack.h | 6 +++--- toolchain/docs/parse.md | 2 +- toolchain/parse/handle_brace_expr.cpp | 20 +++++++++++-------- toolchain/parse/node_kind.def | 13 +++++++----- .../basics/fail_bracket_recovery.carbon | 4 ++-- toolchain/parse/testdata/class/adapt.carbon | 6 +++--- .../testdata/class/fn_definitions.carbon | 2 +- .../testdata/struct/fail_comma_only.carbon | 2 +- .../struct/fail_comma_repeat_in_type.carbon | 6 +++--- .../struct/fail_comma_repeat_in_value.carbon | 6 +++--- .../struct/fail_extra_token_in_type.carbon | 4 ++-- .../struct/fail_extra_token_in_value.carbon | 4 ++-- .../struct/fail_mix_type_and_value.carbon | 4 ++-- .../struct/fail_mix_value_and_type.carbon | 4 ++-- .../struct/fail_mix_with_unknown.carbon | 12 +++++------ .../struct/fail_period_string_colon.carbon | 4 ++-- .../struct/fail_period_string_equals.carbon | 4 ++-- .../testdata/struct/one_entry_no_comma.carbon | 4 ++-- .../struct/one_entry_with_comma.carbon | 8 ++++---- .../parse/testdata/struct/two_entries.carbon | 12 +++++------ toolchain/parse/typed_nodes.h | 19 +++++++++++------- 23 files changed, 93 insertions(+), 73 deletions(-) diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index ea72270a1a14..657068319de9 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -34,13 +34,20 @@ auto HandleParseNode(Context& context, return true; } -auto HandleParseNode(Context& context, Parse::StructCommaId /*node_id*/) +auto HandleParseNode(Context& context, Parse::StructLiteralCommaId /*node_id*/) -> bool { context.param_and_arg_refs_stack().ApplyComma(); return true; } -auto HandleParseNode(Context& context, Parse::StructFieldId node_id) -> bool { +auto HandleParseNode(Context& context, + Parse::StructTypeLiteralCommaId /*node_id*/) -> bool { + context.param_and_arg_refs_stack().ApplyComma(); + return true; +} + +auto HandleParseNode(Context& context, Parse::StructLiteralFieldId node_id) + -> bool { auto value_inst_id = context.node_stack().PopExpr(); auto [name_node, name_id] = context.node_stack().PopNameWithNodeId(); @@ -56,7 +63,7 @@ auto HandleParseNode(Context& context, Parse::StructFieldId node_id) -> bool { return true; } -auto HandleParseNode(Context& context, Parse::StructTypeFieldId node_id) +auto HandleParseNode(Context& context, Parse::StructTypeLiteralFieldId node_id) -> bool { auto [type_node, type_id] = context.node_stack().PopExprWithNodeId(); SemIR::TypeId cast_type_id = ExprAsType(context, type_node, type_id).type_id; diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 0b06975b2a74..6a5642925d60 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -423,8 +423,8 @@ class NodeStack { case Parse::NodeKind::ReturnType: case Parse::NodeKind::ShortCircuitOperandAnd: case Parse::NodeKind::ShortCircuitOperandOr: - case Parse::NodeKind::StructField: - case Parse::NodeKind::StructTypeField: + case Parse::NodeKind::StructLiteralField: + case Parse::NodeKind::StructTypeLiteralField: case Parse::NodeKind::WhereOperand: return Id::KindFor(); case Parse::NodeKind::IfCondition: @@ -631,8 +631,9 @@ class NodeStack { case Parse::NodeKind::ShortCircuitOperatorOr: case Parse::NodeKind::StringLiteral: case Parse::NodeKind::StringTypeLiteral: - case Parse::NodeKind::StructComma: + case Parse::NodeKind::StructLiteralComma: case Parse::NodeKind::StructFieldDesignator: + case Parse::NodeKind::StructTypeLiteralComma: case Parse::NodeKind::StructLiteral: case Parse::NodeKind::StructTypeLiteral: case Parse::NodeKind::Template: diff --git a/toolchain/check/param_and_arg_refs_stack.h b/toolchain/check/param_and_arg_refs_stack.h index dbdfa516fedd..1905926572b1 100644 --- a/toolchain/check/param_and_arg_refs_stack.h +++ b/toolchain/check/param_and_arg_refs_stack.h @@ -30,8 +30,8 @@ class ParamAndArgRefsStack { // On a comma, pushes the most recent instruction, becoming param or arg ref. // This also pops the NodeStack, meaning its top will remain start_kind. auto ApplyComma() -> void { - // Support expressions, parameters, and other nodes like `StructField` - // that produce InstIds. + // Support expressions, parameters, and other nodes like + // `StructLiteralField` that produce InstIds. stack_.AddInstId(node_stack_->Pop()); } @@ -43,7 +43,7 @@ class ParamAndArgRefsStack { auto EndNoPop(Parse::NodeKind start_kind) -> void { if (!node_stack_->PeekIs(start_kind)) { // Support expressions, parameters, and other nodes like - // `StructField` that produce InstIds. + // `StructLiteralField` that produce InstIds. stack_.AddInstId(node_stack_->Pop()); } } diff --git a/toolchain/docs/parse.md b/toolchain/docs/parse.md index 50465bdf994a..1a2b5eba114c 100644 --- a/toolchain/docs/parse.md +++ b/toolchain/docs/parse.md @@ -156,7 +156,7 @@ have two children: the lhs and rhs expressions. Many nodes have a child count of Because the tree structure is always valid, these are treated as contracts. Some nodes exist only to be used to construct valid tree structures for invalid -input, such as `StructFieldUnknown`. +input, such as `InvalidParse`. Although each subtree's size is also tracked as part of the node, we're currently trying to avoid relying on it and may eliminate it if it turns out to diff --git a/toolchain/parse/handle_brace_expr.cpp b/toolchain/parse/handle_brace_expr.cpp index 3956ab2caa9e..ebedfa55ab75 100644 --- a/toolchain/parse/handle_brace_expr.cpp +++ b/toolchain/parse/handle_brace_expr.cpp @@ -149,8 +149,9 @@ auto HandleBraceExprParamAfterDesignatorAsUnknown(Context& context) -> void { } // Handles BraceExprParamFinishAs(Type|Value|Unknown). -static auto HandleBraceExprParamFinish(Context& context, NodeKind node_kind, - State param_state) -> void { +static auto HandleBraceExprParamFinish(Context& context, NodeKind field_kind, + NodeKind comma_kind, State param_state) + -> void { auto state = context.PopState(); if (state.has_error) { @@ -158,28 +159,31 @@ static auto HandleBraceExprParamFinish(Context& context, NodeKind node_kind, /*has_error=*/true); context.ReturnErrorOnState(); } else { - context.AddNode(node_kind, state.token, /*has_error=*/false); + context.AddNode(field_kind, state.token, /*has_error=*/false); } - if (context.ConsumeListToken( - NodeKind::StructComma, Lex::TokenKind::CloseCurlyBrace, - state.has_error) == Context::ListTokenKind::Comma) { + if (context.ConsumeListToken(comma_kind, Lex::TokenKind::CloseCurlyBrace, + state.has_error) == + Context::ListTokenKind::Comma) { context.PushState(param_state); } } auto HandleBraceExprParamFinishAsType(Context& context) -> void { - HandleBraceExprParamFinish(context, NodeKind::StructTypeField, + HandleBraceExprParamFinish(context, NodeKind::StructTypeLiteralField, + NodeKind::StructTypeLiteralComma, State::BraceExprParamAsType); } auto HandleBraceExprParamFinishAsValue(Context& context) -> void { - HandleBraceExprParamFinish(context, NodeKind::StructField, + HandleBraceExprParamFinish(context, NodeKind::StructLiteralField, + NodeKind::StructLiteralComma, State::BraceExprParamAsValue); } auto HandleBraceExprParamFinishAsUnknown(Context& context) -> void { HandleBraceExprParamFinish(context, NodeKind::InvalidParse, + NodeKind::InvalidParse, State::BraceExprParamAsUnknown); } diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index 1a6c9bb6ee6b..dafb04ed2522 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -287,13 +287,16 @@ CARBON_PARSE_NODE_KIND(IfExprIf) CARBON_PARSE_NODE_KIND(IfExprThen) CARBON_PARSE_NODE_KIND(IfExprElse) -CARBON_PARSE_NODE_KIND(StructLiteralStart) -CARBON_PARSE_NODE_KIND(StructTypeLiteralStart) CARBON_PARSE_NODE_KIND(StructFieldDesignator) -CARBON_PARSE_NODE_KIND(StructField) -CARBON_PARSE_NODE_KIND(StructTypeField) -CARBON_PARSE_NODE_KIND(StructComma) + +CARBON_PARSE_NODE_KIND(StructLiteralStart) +CARBON_PARSE_NODE_KIND(StructLiteralField) +CARBON_PARSE_NODE_KIND(StructLiteralComma) CARBON_PARSE_NODE_KIND(StructLiteral) + +CARBON_PARSE_NODE_KIND(StructTypeLiteralStart) +CARBON_PARSE_NODE_KIND(StructTypeLiteralField) +CARBON_PARSE_NODE_KIND(StructTypeLiteralComma) CARBON_PARSE_NODE_KIND(StructTypeLiteral) CARBON_PARSE_NODE_KIND(ExternModifierWithLibrary) diff --git a/toolchain/parse/testdata/basics/fail_bracket_recovery.carbon b/toolchain/parse/testdata/basics/fail_bracket_recovery.carbon index 324904ea47d3..11c86138fda7 100644 --- a/toolchain/parse/testdata/basics/fail_bracket_recovery.carbon +++ b/toolchain/parse/testdata/basics/fail_bracket_recovery.carbon @@ -63,7 +63,7 @@ fn F() { // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'TupleLiteralStart', text: '('}, // CHECK:STDOUT: {kind: 'TupleLiteral', text: ')', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 5}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 7}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 9}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, @@ -74,7 +74,7 @@ fn F() { // CHECK:STDOUT: {kind: 'TupleLiteralStart', text: '('}, // CHECK:STDOUT: {kind: 'TupleLiteral', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ParenExpr', text: ')', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 7}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 9}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 21}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 46}, diff --git a/toolchain/parse/testdata/class/adapt.carbon b/toolchain/parse/testdata/class/adapt.carbon index abd3c34a942c..4fddc6bf0fd4 100644 --- a/toolchain/parse/testdata/class/adapt.carbon +++ b/toolchain/parse/testdata/class/adapt.carbon @@ -108,12 +108,12 @@ fn F() { // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 11}, // CHECK:STDOUT: {kind: 'AdaptDecl', text: ';', subtree_size: 14}, // CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 18}, diff --git a/toolchain/parse/testdata/class/fn_definitions.carbon b/toolchain/parse/testdata/class/fn_definitions.carbon index 32739f84b689..6c6bd02efff2 100644 --- a/toolchain/parse/testdata/class/fn_definitions.carbon +++ b/toolchain/parse/testdata/class/fn_definitions.carbon @@ -34,7 +34,7 @@ class Foo { // CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 6}, // CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 8}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16}, diff --git a/toolchain/parse/testdata/struct/fail_comma_only.carbon b/toolchain/parse/testdata/struct/fail_comma_only.carbon index bb5786e7ef73..9ad63657858c 100644 --- a/toolchain/parse/testdata/struct/fail_comma_only.carbon +++ b/toolchain/parse/testdata/struct/fail_comma_only.carbon @@ -20,7 +20,7 @@ var x: {,} = {}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'x'}, // CHECK:STDOUT: {kind: 'StructLiteralStart', text: '{'}, // CHECK:STDOUT: {kind: 'InvalidParse', text: ',', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: ','}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 4}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 6}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, diff --git a/toolchain/parse/testdata/struct/fail_comma_repeat_in_type.carbon b/toolchain/parse/testdata/struct/fail_comma_repeat_in_type.carbon index 136422c3963f..cea1e9bc5dd9 100644 --- a/toolchain/parse/testdata/struct/fail_comma_repeat_in_type.carbon +++ b/toolchain/parse/testdata/struct/fail_comma_repeat_in_type.carbon @@ -22,10 +22,10 @@ var x: {.a: i32,,} = {}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'InvalidParse', text: ',', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 9}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 11}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, diff --git a/toolchain/parse/testdata/struct/fail_comma_repeat_in_value.carbon b/toolchain/parse/testdata/struct/fail_comma_repeat_in_value.carbon index 9fe559449dbe..d689fb301a8c 100644 --- a/toolchain/parse/testdata/struct/fail_comma_repeat_in_value.carbon +++ b/toolchain/parse/testdata/struct/fail_comma_repeat_in_value.carbon @@ -22,10 +22,10 @@ var x: {.a = 0,,} = {}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'InvalidParse', text: ',', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 9}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 11}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, diff --git a/toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon b/toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon index a7787b2207b4..de396645218e 100644 --- a/toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon +++ b/toolchain/parse/testdata/struct/fail_extra_token_in_type.carbon @@ -22,7 +22,7 @@ var x: {.a: i32 banana} = {.a = 0}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 6}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 8}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, @@ -30,7 +30,7 @@ var x: {.a: i32 banana} = {.a = 0}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 6}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 17}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon b/toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon index 7159d8272144..f53bf5a97130 100644 --- a/toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon +++ b/toolchain/parse/testdata/struct/fail_extra_token_in_value.carbon @@ -22,7 +22,7 @@ var x: {.a: i32} = {.a = 0 banana}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 6}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 8}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, @@ -30,7 +30,7 @@ var x: {.a: i32} = {.a = 0 banana}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 6}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 17}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/struct/fail_mix_type_and_value.carbon b/toolchain/parse/testdata/struct/fail_mix_type_and_value.carbon index 39d2128cbdcb..ce1693cf5873 100644 --- a/toolchain/parse/testdata/struct/fail_mix_type_and_value.carbon +++ b/toolchain/parse/testdata/struct/fail_mix_type_and_value.carbon @@ -22,8 +22,8 @@ var x: {.a: i32, .b = 0} = {}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'InvalidParse', text: '.', has_error: yes}, diff --git a/toolchain/parse/testdata/struct/fail_mix_value_and_type.carbon b/toolchain/parse/testdata/struct/fail_mix_value_and_type.carbon index 2e3e9bce2400..57b317dc6c7d 100644 --- a/toolchain/parse/testdata/struct/fail_mix_value_and_type.carbon +++ b/toolchain/parse/testdata/struct/fail_mix_value_and_type.carbon @@ -22,8 +22,8 @@ var x: {.a = 0, b: i32} = {}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'InvalidParse', text: 'b', has_error: yes}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 8}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 10}, diff --git a/toolchain/parse/testdata/struct/fail_mix_with_unknown.carbon b/toolchain/parse/testdata/struct/fail_mix_with_unknown.carbon index cdefbcaeb202..7ca9f0fc5ad6 100644 --- a/toolchain/parse/testdata/struct/fail_mix_with_unknown.carbon +++ b/toolchain/parse/testdata/struct/fail_mix_with_unknown.carbon @@ -39,12 +39,12 @@ var x: i32 = {.a: i32, .b, .c = 1}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '1'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'InvalidParse', text: '.', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'c'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'InvalidParse', text: '.', has_error: yes}, @@ -59,12 +59,12 @@ var x: i32 = {.a: i32, .b, .c = 1}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'InvalidParse', text: '.', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'c'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'InvalidParse', text: '.', has_error: yes}, diff --git a/toolchain/parse/testdata/struct/fail_period_string_colon.carbon b/toolchain/parse/testdata/struct/fail_period_string_colon.carbon index ebf6bfc331fe..01dbc0b72178 100644 --- a/toolchain/parse/testdata/struct/fail_period_string_colon.carbon +++ b/toolchain/parse/testdata/struct/fail_period_string_colon.carbon @@ -23,11 +23,11 @@ var x: {."hello": i32, .y: i32} = {}; // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, // CHECK:STDOUT: {kind: 'InvalidParse', text: ':', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'y'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', has_error: yes, subtree_size: 11}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 13}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, diff --git a/toolchain/parse/testdata/struct/fail_period_string_equals.carbon b/toolchain/parse/testdata/struct/fail_period_string_equals.carbon index b04cba089f97..9f8dc29de4b2 100644 --- a/toolchain/parse/testdata/struct/fail_period_string_equals.carbon +++ b/toolchain/parse/testdata/struct/fail_period_string_equals.carbon @@ -23,11 +23,11 @@ var x: {."hello" = 0, .y = 4} = {}; // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '0'}, // CHECK:STDOUT: {kind: 'InvalidParse', text: '=', has_error: yes}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'y'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', has_error: yes, subtree_size: 11}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 13}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, diff --git a/toolchain/parse/testdata/struct/one_entry_no_comma.carbon b/toolchain/parse/testdata/struct/one_entry_no_comma.carbon index 4f699b4a906e..62c1ecc0a3e7 100644 --- a/toolchain/parse/testdata/struct/one_entry_no_comma.carbon +++ b/toolchain/parse/testdata/struct/one_entry_no_comma.carbon @@ -19,7 +19,7 @@ var z: {.n: i32} = {.n = 4}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'n'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 6}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 8}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, @@ -27,7 +27,7 @@ var z: {.n: i32} = {.n = 4}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'n'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 6}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 17}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/struct/one_entry_with_comma.carbon b/toolchain/parse/testdata/struct/one_entry_with_comma.carbon index fdc5c65539a7..b4f12ba42b50 100644 --- a/toolchain/parse/testdata/struct/one_entry_with_comma.carbon +++ b/toolchain/parse/testdata/struct/one_entry_with_comma.carbon @@ -19,8 +19,8 @@ var z: {.n: i32,} = {.n = 4,}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'n'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 7}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 9}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, @@ -28,8 +28,8 @@ var z: {.n: i32,} = {.n = 4,}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'n'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 7}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 19}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/struct/two_entries.carbon b/toolchain/parse/testdata/struct/two_entries.carbon index e1de95f683a7..9176a98b9981 100644 --- a/toolchain/parse/testdata/struct/two_entries.carbon +++ b/toolchain/parse/testdata/struct/two_entries.carbon @@ -19,12 +19,12 @@ var x: {.a: i32, .b: i32} = {.a = 1, .b = 2}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, -// CHECK:STDOUT: {kind: 'StructTypeField', text: ':', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructTypeLiteralField', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 11}, // CHECK:STDOUT: {kind: 'BindingPattern', text: ':', subtree_size: 13}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '='}, @@ -32,12 +32,12 @@ var x: {.a: i32, .b: i32} = {.a = 1, .b = 2}; // CHECK:STDOUT: {kind: 'IdentifierName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '1'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructComma', text: ','}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralComma', text: ','}, // CHECK:STDOUT: {kind: 'IdentifierName', text: 'b'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IntLiteral', text: '2'}, -// CHECK:STDOUT: {kind: 'StructField', text: '=', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'StructLiteralField', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 11}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 27}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index 607cd1d8b939..6b08c2ef88b3 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -1122,9 +1122,14 @@ using StructLiteralStart = using StructTypeLiteralStart = LeafNode; // `,` -using StructComma = LeafNode; +using StructLiteralComma = + LeafNode; +using StructTypeLiteralComma = + LeafNode; // `.a` +// This is shared for struct literals and type literals in order to reduce +// lookahead for parse (the `=` versus `:` would require lookahead of 2). struct StructFieldDesignator { static constexpr auto Kind = NodeKind::StructFieldDesignator.Define({.child_count = 1}); @@ -1134,8 +1139,8 @@ struct StructFieldDesignator { }; // `.a = 0` -struct StructField { - static constexpr auto Kind = NodeKind::StructField.Define( +struct StructLiteralField { + static constexpr auto Kind = NodeKind::StructLiteralField.Define( {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2}); StructFieldDesignatorId designator; @@ -1144,8 +1149,8 @@ struct StructField { }; // `.a: i32` -struct StructTypeField { - static constexpr auto Kind = NodeKind::StructTypeField.Define( +struct StructTypeLiteralField { + static constexpr auto Kind = NodeKind::StructTypeLiteralField.Define( {.bracketed_by = StructFieldDesignator::Kind, .child_count = 2}); StructFieldDesignatorId designator; @@ -1160,7 +1165,7 @@ struct StructLiteral { .bracketed_by = StructLiteralStart::Kind}); StructLiteralStartId start; - CommaSeparatedList fields; + CommaSeparatedList fields; Lex::CloseCurlyBraceTokenIndex token; }; @@ -1171,7 +1176,7 @@ struct StructTypeLiteral { .bracketed_by = StructTypeLiteralStart::Kind}); StructTypeLiteralStartId start; - CommaSeparatedList fields; + CommaSeparatedList fields; Lex::CloseCurlyBraceTokenIndex token; };