From c165ab6c2b3f7f8531eb65a4a5f4fff6f3052c3b Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Tue, 15 Nov 2022 22:44:57 -0800 Subject: [PATCH] Change StructLiteral and StructTypeLiteral parsing to use an ambiguous start. (#2396) This is necessary in order to use a bracketing approach; parsing doesn't know the contained format until it parses the first element, which we don't want to do look-ahead for. I think the bracketing is higher value than knowing the format before adding the node. --- toolchain/parser/parse_node_kind.def | 2 +- toolchain/parser/parser.cpp | 12 ++++------ .../parser/testdata/basics/structs.carbon | 24 +++++++++---------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/toolchain/parser/parse_node_kind.def b/toolchain/parser/parse_node_kind.def index 16dffa020bb2..cec0bec11edb 100644 --- a/toolchain/parser/parse_node_kind.def +++ b/toolchain/parser/parse_node_kind.def @@ -77,10 +77,10 @@ CARBON_PARSE_NODE_KIND(PostfixOperator) // Struct literals. CARBON_PARSE_NODE_KIND(StructLiteral) CARBON_PARSE_NODE_KIND(StructTypeLiteral) +CARBON_PARSE_NODE_KIND(StructLiteralOrTypeLiteralStart) CARBON_PARSE_NODE_KIND(StructFieldDesignator) CARBON_PARSE_NODE_KIND(StructFieldValue) CARBON_PARSE_NODE_KIND(StructFieldType) CARBON_PARSE_NODE_KIND(StructComma) -CARBON_PARSE_NODE_KIND(StructEnd) #undef CARBON_PARSE_NODE_KIND diff --git a/toolchain/parser/parser.cpp b/toolchain/parser/parser.cpp index b3e494a878e6..8b9b467ba86b 100644 --- a/toolchain/parser/parser.cpp +++ b/toolchain/parser/parser.cpp @@ -429,12 +429,9 @@ auto Parser::HandleBraceExpressionState() -> void { state.state = ParserState::BraceExpressionFinishAsUnknown(); PushState(state); - // TODO: When swapping {} start/end, this should AddLeafNode the open before - // continuing. - - // Advance past the open brace. - CARBON_CHECK(PositionIs(TokenKind::OpenCurlyBrace())); - ++position_; + CARBON_CHECK(ConsumeAndAddLeafNodeIf( + TokenKind::OpenCurlyBrace(), + ParseNodeKind::StructLiteralOrTypeLiteralStart())); if (!PositionIs(TokenKind::CloseCurlyBrace())) { PushState(ParserState::BraceExpressionParameterAsUnknown()); } @@ -612,10 +609,9 @@ auto Parser::HandleBraceExpressionParameterFinishAsUnknownState() -> void { auto Parser::HandleBraceExpressionFinish(BraceExpressionKind kind) -> void { auto state = PopState(); - AddLeafNode(ParseNodeKind::StructEnd(), Consume()); AddNode(kind == BraceExpressionKind::Type ? ParseNodeKind::StructTypeLiteral() : ParseNodeKind::StructLiteral(), - state.token, state.subtree_start, state.has_error); + Consume(), state.subtree_start, state.has_error); } auto Parser::HandleBraceExpressionFinishAsTypeState() -> void { diff --git a/toolchain/parser/testdata/basics/structs.carbon b/toolchain/parser/testdata/basics/structs.carbon index 0098bf66310b..823531013f1c 100644 --- a/toolchain/parser/testdata/basics/structs.carbon +++ b/toolchain/parser/testdata/basics/structs.carbon @@ -6,6 +6,7 @@ // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ // CHECK:STDOUT: {kind: 'DeclaredName', text: 'x'}, +// CHECK:STDOUT: {kind: 'StructLiteralOrTypeLiteralStart', text: '{'}, // CHECK:STDOUT: {kind: 'DesignatedName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'Literal', text: 'i32'}, @@ -15,9 +16,9 @@ // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'Literal', text: 'i32'}, // CHECK:STDOUT: {kind: 'StructFieldType', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructEnd', text: '}'}, -// CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '{', subtree_size: 11}, +// CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 11}, // CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 13}, +// CHECK:STDOUT: {kind: 'StructLiteralOrTypeLiteralStart', text: '{'}, // CHECK:STDOUT: {kind: 'DesignatedName', text: 'a'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'Literal', text: '1'}, @@ -27,36 +28,35 @@ // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'Literal', text: '2'}, // CHECK:STDOUT: {kind: 'StructFieldValue', text: '=', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructEnd', text: '}'}, -// CHECK:STDOUT: {kind: 'StructLiteral', text: '{', subtree_size: 11}, +// CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 11}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '=', subtree_size: 12}, // CHECK:STDOUT: {kind: 'DeclarationEnd', text: ';'}, // CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 27}, // CHECK:STDOUT: {kind: 'DeclaredName', text: 'y'}, -// CHECK:STDOUT: {kind: 'StructEnd', text: '}'}, -// CHECK:STDOUT: {kind: 'StructLiteral', text: '{', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'StructLiteralOrTypeLiteralStart', text: '{'}, +// CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 2}, // CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'StructEnd', text: '}'}, -// CHECK:STDOUT: {kind: 'StructLiteral', text: '{', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'StructLiteralOrTypeLiteralStart', text: '{'}, +// CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 2}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '=', subtree_size: 3}, // CHECK:STDOUT: {kind: 'DeclarationEnd', text: ';'}, // CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 9}, // CHECK:STDOUT: {kind: 'DeclaredName', text: 'z'}, +// CHECK:STDOUT: {kind: 'StructLiteralOrTypeLiteralStart', text: '{'}, // CHECK:STDOUT: {kind: 'DesignatedName', text: 'n'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'Literal', text: 'i32'}, // CHECK:STDOUT: {kind: 'StructFieldType', text: ':', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructComma', text: ','}, -// CHECK:STDOUT: {kind: 'StructEnd', text: '}'}, -// CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '{', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'StructTypeLiteral', text: '}', subtree_size: 7}, // CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 9}, +// CHECK:STDOUT: {kind: 'StructLiteralOrTypeLiteralStart', text: '{'}, // CHECK:STDOUT: {kind: 'DesignatedName', text: 'n'}, // CHECK:STDOUT: {kind: 'StructFieldDesignator', text: '.', subtree_size: 2}, // CHECK:STDOUT: {kind: 'Literal', text: '4'}, // CHECK:STDOUT: {kind: 'StructFieldValue', text: '=', subtree_size: 4}, // CHECK:STDOUT: {kind: 'StructComma', text: ','}, -// CHECK:STDOUT: {kind: 'StructEnd', text: '}'}, -// CHECK:STDOUT: {kind: 'StructLiteral', text: '{', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'StructLiteral', text: '}', subtree_size: 7}, // CHECK:STDOUT: {kind: 'VariableInitializer', text: '=', subtree_size: 8}, // CHECK:STDOUT: {kind: 'DeclarationEnd', text: ';'}, // CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 19},