diff --git a/toolchain/README.md b/toolchain/README.md index 7569ba3eb907..416bcf34016d 100644 --- a/toolchain/README.md +++ b/toolchain/README.md @@ -73,7 +73,7 @@ Other return values indicate that parsing was either successful or that any encountered errors have been recovered from, so the caller can create a valid parse tree node. -The produced `ParseTree` is in reverse postorder. For example, given the code: +The produced `ParseTree` is in postorder. For example, given the code: ```carbon fn foo() -> f64 { @@ -84,23 +84,29 @@ fn foo() -> f64 { The node order is (with indentation to indicate nesting): ``` - Index 0: kind DeclaredName - Index 1: kind ParameterListEnd - Index 2: kind ParameterList - Index 3: kind Literal - Index 4: kind ReturnType - Index 5: kind Literal - Index 6: kind StatementEnd - Index 7: kind ReturnStatement - Index 8: kind CodeBlockEnd - Index 9: kind CodeBlock -Index 10: kind FunctionDeclaration -Index 11: kind FileEnd + {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'} + {node_index: 1, kind: 'DeclaredName', text: 'foo'} + {node_index: 2, kind: 'ParameterListEnd', text: ')'} + {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2} + {node_index: 4, kind: 'Literal', text: 'f64'} + {node_index: 5, kind: 'ReturnType', text: '->', subtree_size: 2} + {node_index: 6, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7} + {node_index: 7, kind: 'Literal', text: '42'} + {node_index: 8, kind: 'StatementEnd', text: ';'} + {node_index: 9, kind: 'ReturnStatement', text: 'return', subtree_size: 3} +{node_index: 10, kind: 'FunctionDefinition', text: '}', subtree_size: 11} +{node_index: 11, kind: 'FileEnd', text: ''} ``` -This is done this way in order to allow for more efficient processing of a file. -As a consequence, the `SemanticsIR` does a lot of reversal of the ParseTree -ordering in order to visit code in source order. +This ordering is focused on efficient translation into the SemanticsIR. +Non-template code should be type-checked as soon as nodes are encountered, +decreasing SemanticsIR mutations. + +While sometimes the beginning of the grammatical construct will be the parent, +where introducer keywords are used, it will often be the _end_ of the +grammatical construct that is the parent: this is so that a postorder traversal +of the tree can see the kind of grammatical construct being built first, and +handle child nodes taking that into account. ### Stack overflow diff --git a/toolchain/lexer/tokenized_buffer.h b/toolchain/lexer/tokenized_buffer.h index 6d891ab9b763..2991b690da89 100644 --- a/toolchain/lexer/tokenized_buffer.h +++ b/toolchain/lexer/tokenized_buffer.h @@ -47,7 +47,7 @@ class TokenizedBufferToken { public: using Token = TokenizedBufferToken; - TokenizedBufferToken() = default; + TokenizedBufferToken() : TokenizedBufferToken(-1) {} friend auto operator==(Token lhs, Token rhs) -> bool { return lhs.index_ == rhs.index_; diff --git a/toolchain/parser/parse_node_kind.def b/toolchain/parser/parse_node_kind.def index ba3a481f2458..355c9cfbfd01 100644 --- a/toolchain/parser/parse_node_kind.def +++ b/toolchain/parser/parse_node_kind.def @@ -24,10 +24,13 @@ CARBON_PARSE_NODE_KIND(PackageImpl) CARBON_PARSE_NODE_KIND(PackageLibrary) CARBON_PARSE_NODE_KIND(PackageEnd) +CARBON_PARSE_NODE_KIND(FunctionIntroducer) CARBON_PARSE_NODE_KIND(FunctionDeclaration) +CARBON_PARSE_NODE_KIND(FunctionDefinition) +CARBON_PARSE_NODE_KIND(FunctionDefinitionStart) CARBON_PARSE_NODE_KIND(ParameterList) -CARBON_PARSE_NODE_KIND(ParameterListComma) CARBON_PARSE_NODE_KIND(ParameterListEnd) +CARBON_PARSE_NODE_KIND(ParameterListComma) CARBON_PARSE_NODE_KIND(PatternBinding) CARBON_PARSE_NODE_KIND(ReturnType) CARBON_PARSE_NODE_KIND(VariableDeclaration) @@ -35,8 +38,8 @@ CARBON_PARSE_NODE_KIND(VariableInitializer) CARBON_PARSE_NODE_KIND(FileEnd) // Statements. -CARBON_PARSE_NODE_KIND(CodeBlockEnd) CARBON_PARSE_NODE_KIND(CodeBlock) +CARBON_PARSE_NODE_KIND(CodeBlockStart) CARBON_PARSE_NODE_KIND(ExpressionStatement) CARBON_PARSE_NODE_KIND(IfStatement) CARBON_PARSE_NODE_KIND(IfStatementElse) diff --git a/toolchain/parser/parse_tree_fuzzer.cpp b/toolchain/parser/parse_tree_fuzzer.cpp index 1c94b97420a6..4f12dac3258c 100644 --- a/toolchain/parser/parse_tree_fuzzer.cpp +++ b/toolchain/parser/parse_tree_fuzzer.cpp @@ -35,16 +35,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, // Now parse it into a tree. Note that parsing will (when asserts are enabled) // walk the entire tree to verify it so we don't have to do that here. - ParseTree tree = ParseTree::Parse(tokens, NullDiagnosticConsumer()); - if (tree.has_errors()) { - return 0; - } - - // In the absence of parse errors, we should have exactly as many nodes as - // tokens. - CARBON_CHECK(tree.size() == tokens.size()) - << "Unexpected number of tree nodes!"; - + ParseTree::Parse(tokens, NullDiagnosticConsumer()); return 0; } diff --git a/toolchain/parser/parse_tree_test.cpp b/toolchain/parser/parse_tree_test.cpp index a23868933352..807bda3d9803 100644 --- a/toolchain/parser/parse_tree_test.cpp +++ b/toolchain/parser/parse_tree_test.cpp @@ -155,34 +155,34 @@ TEST_F(ParseTreeTest, PrintingAsYAML) { tree.Print(print_stream); print_stream.flush(); - EXPECT_THAT( - Yaml::Value::FromText(print_output), - ElementsAre(Yaml::SequenceValue{ - Yaml::MappingValue{ - {"node_index", "4"}, - {"kind", "FunctionDeclaration"}, - {"text", "fn"}, - {"subtree_size", "5"}, - {"children", - Yaml::SequenceValue{ - Yaml::MappingValue{{"node_index", "0"}, - {"kind", "DeclaredName"}, - {"text", "F"}}, - Yaml::MappingValue{{"node_index", "2"}, - {"kind", "ParameterList"}, - {"text", "("}, - {"subtree_size", "2"}, - {"children", // - Yaml::SequenceValue{Yaml::MappingValue{ - {"node_index", "1"}, - {"kind", "ParameterListEnd"}, - {"text", ")"}}}}}, - Yaml::MappingValue{{"node_index", "3"}, - {"kind", "DeclarationEnd"}, - {"text", ";"}}}}}, - Yaml::MappingValue{{"node_index", "5"}, // - {"kind", "FileEnd"}, - {"text", ""}}})); + auto parameter_list = Yaml::SequenceValue{ + Yaml::MappingValue{ + {"node_index", "2"}, {"kind", "ParameterListEnd"}, {"text", ")"}}, + }; + + auto function_decl = Yaml::SequenceValue{ + Yaml::MappingValue{ + {"node_index", "0"}, {"kind", "FunctionIntroducer"}, {"text", "fn"}}, + Yaml::MappingValue{ + {"node_index", "1"}, {"kind", "DeclaredName"}, {"text", "F"}}, + Yaml::MappingValue{{"node_index", "3"}, + {"kind", "ParameterList"}, + {"text", "("}, + {"subtree_size", "2"}, + {"children", parameter_list}}, + }; + + auto file = Yaml::SequenceValue{ + Yaml::MappingValue{{"node_index", "4"}, + {"kind", "FunctionDeclaration"}, + {"text", ";"}, + {"subtree_size", "5"}, + {"children", function_decl}}, + Yaml::MappingValue{ + {"node_index", "5"}, {"kind", "FileEnd"}, {"text", ""}}, + }; + + EXPECT_THAT(Yaml::Value::FromText(print_output), ElementsAre(file)); } TEST_F(ParseTreeTest, RecursionLimit) { diff --git a/toolchain/parser/parser_impl.cpp b/toolchain/parser/parser_impl.cpp index 8b2eec72b263..3a459e4c634f 100644 --- a/toolchain/parser/parser_impl.cpp +++ b/toolchain/parser/parser_impl.cpp @@ -95,9 +95,9 @@ auto ParseTree::Parser::Parse(TokenizedBuffer& tokens, TokenDiagnosticEmitter& emitter) -> ParseTree { ParseTree tree(tokens); - // We expect to have a 1:1 correspondence between tokens and tree nodes, so - // reserve the space we expect to need here to avoid allocation and copying - // overhead. + // Reserve the space we expect to need for nodes in order to avoid allocation + // and copying overhead. This should be a one-to-one correspondence in an + // error-free tree. tree.node_impls_.reserve(tokens.size()); Parser parser(tree, tokens, emitter); @@ -111,6 +111,9 @@ auto ParseTree::Parser::Parse(TokenizedBuffer& tokens, parser.AddLeafNode(ParseNodeKind::FileEnd(), *parser.position_); + CARBON_CHECK(tree.has_errors() || tree.size() == tokens.size()) + << "Failed to correctly calculate size: expected " << tokens.size() + << ", got " << tree.size(); CARBON_CHECK(tree.Verify()) << "Parse tree built but does not verify!"; return tree; } @@ -135,9 +138,13 @@ auto ParseTree::Parser::ConsumeIf(TokenKind kind) } auto ParseTree::Parser::AddLeafNode(ParseNodeKind kind, - TokenizedBuffer::Token token) -> Node { + TokenizedBuffer::Token token, + bool has_error) -> Node { Node n(tree_.node_impls_.size()); tree_.node_impls_.push_back(NodeImpl(kind, token, /*subtree_size_arg=*/1)); + if (has_error) { + MarkNodeError(n); + } return n; } @@ -229,9 +236,8 @@ auto ParseTree::Parser::FindNextOf( } } -auto ParseTree::Parser::SkipPastLikelyEnd(TokenizedBuffer::Token skip_root, - SemiHandler on_semi) - -> llvm::Optional { +auto ParseTree::Parser::SkipPastLikelyEnd(TokenizedBuffer::Token skip_root) + -> llvm::Optional { if (AtEndOfFile()) { return llvm::None; } @@ -261,7 +267,7 @@ auto ParseTree::Parser::SkipPastLikelyEnd(TokenizedBuffer::Token skip_root, // We assume that a semicolon is always intended to be the end of the // current construct. if (auto semi = ConsumeIf(TokenKind::Semi())) { - return on_semi(*semi); + return semi; } // Skip over any matching group of tokens_. @@ -408,44 +414,53 @@ auto ParseTree::Parser::ParseFunctionSignature() -> bool { } } - return params.hasValue(); + return params.has_value(); } auto ParseTree::Parser::ParseCodeBlock() -> llvm::Optional { + return ParseCodeBlock(GetSubtreeStartPosition(), + ParseNodeKind::CodeBlockStart(), + ParseNodeKind::CodeBlock()); +} + +auto ParseTree::Parser::ParseCodeBlock(SubtreeStart subtree_start, + ParseNodeKind start_kind, + ParseNodeKind end_kind) + -> llvm::Optional { CARBON_RETURN_IF_STACK_LIMITED(llvm::None); - llvm::Optional maybe_open_curly = + llvm::Optional open_curly = ConsumeIf(TokenKind::OpenCurlyBrace()); - if (!maybe_open_curly) { + if (!open_curly) { // Recover by parsing a single statement. CARBON_DIAGNOSTIC(ExpectedCodeBlock, Error, "Expected braced code block."); emitter_.Emit(*position_, ExpectedCodeBlock); - return ParseStatement(); + // Use the unexpected token for the block start and end. + TokenizedBuffer::Token recovery_start = *position_; + AddNode(start_kind, recovery_start, subtree_start, /*has_error=*/true); + ParseStatement(); + return AddNode(end_kind, recovery_start, subtree_start, /*has_error=*/true); } - TokenizedBuffer::Token open_curly = *maybe_open_curly; - auto start = GetSubtreeStartPosition(); - - bool has_errors = false; + AddNode(start_kind, *open_curly, subtree_start); // Loop over all the different possibly nested elements in the code block. + bool has_error = false; while (!NextTokenIs(TokenKind::CloseCurlyBrace())) { if (!ParseStatement()) { - // We detected and diagnosed an error of some kind. We can trivially skip - // to the actual close curly brace from here. + // We detected and diagnosed an error of some kind. We can trivially + // skip to the actual close curly brace from here. // TODO: It would be better to skip to the next semicolon, or the next // token at the start of a line with the same indent as this one. - SkipTo(tokens_.GetMatchedClosingToken(open_curly)); - has_errors = true; + SkipTo(tokens_.GetMatchedClosingToken(*open_curly)); + has_error = true; break; } } // We always reach here having set our position in the token stream to the // close curly brace. - AddLeafNode(ParseNodeKind::CodeBlockEnd(), - Consume(TokenKind::CloseCurlyBrace())); - - return AddNode(ParseNodeKind::CodeBlock(), open_curly, start, has_errors); + return AddNode(end_kind, Consume(TokenKind::CloseCurlyBrace()), subtree_start, + /*has_error=*/has_error); } auto ParseTree::Parser::ParsePackageDirective() -> Node { @@ -460,9 +475,9 @@ auto ParseTree::Parser::ParsePackageDirective() -> Node { CARBON_RETURN_IF_STACK_LIMITED(create_error_node()); auto exit_on_parse_error = [&]() { - SkipPastLikelyEnd(package_intro_token, [&](TokenizedBuffer::Token semi) { - return AddLeafNode(ParseNodeKind::PackageEnd(), semi); - }); + if (auto semi_token = SkipPastLikelyEnd(package_intro_token)) { + AddLeafNode(ParseNodeKind::PackageEnd(), *semi_token); + } return create_error_node(); }; @@ -530,30 +545,34 @@ auto ParseTree::Parser::ParsePackageDirective() -> Node { } auto ParseTree::Parser::ParseFunctionDeclaration() -> Node { - TokenizedBuffer::Token function_intro_token = Consume(TokenKind::Fn()); auto start = GetSubtreeStartPosition(); + TokenizedBuffer::Token function_intro_token = Consume(TokenKind::Fn()); + AddLeafNode(ParseNodeKind::FunctionIntroducer(), function_intro_token); - auto add_error_function_node = [&] { + // When handling errors before the start of the definition, treat it as a + // declaration. Recover to a semicolon when it makes sense as a possible + // function end, otherwise use the fn token for the error. + auto add_error_function_node = [&](bool skip_past_likely_end) { + if (skip_past_likely_end) { + if (auto semi_token = SkipPastLikelyEnd(function_intro_token)) { + return AddNode(ParseNodeKind::FunctionDeclaration(), *semi_token, start, + /*has_error=*/true); + } + } return AddNode(ParseNodeKind::FunctionDeclaration(), function_intro_token, start, /*has_error=*/true); }; - CARBON_RETURN_IF_STACK_LIMITED(add_error_function_node()); + CARBON_RETURN_IF_STACK_LIMITED(add_error_function_node(false)); - auto handle_semi_in_error_recovery = [&](TokenizedBuffer::Token semi) { - return AddLeafNode(ParseNodeKind::DeclarationEnd(), semi); - }; - - auto name_n = ConsumeAndAddLeafNodeIf(TokenKind::Identifier(), - ParseNodeKind::DeclaredName()); - if (!name_n) { + if (!ConsumeAndAddLeafNodeIf(TokenKind::Identifier(), + ParseNodeKind::DeclaredName())) { CARBON_DIAGNOSTIC(ExpectedFunctionName, Error, "Expected function name after `fn` keyword."); emitter_.Emit(*position_, ExpectedFunctionName); // TODO: We could change the lexer to allow us to synthesize certain // kinds of tokens and try to "recover" here, but unclear that this is // really useful. - SkipPastLikelyEnd(function_intro_token, handle_semi_in_error_recovery); - return add_error_function_node(); + return add_error_function_node(true); } TokenizedBuffer::Token open_paren = *position_; @@ -561,40 +580,39 @@ auto ParseTree::Parser::ParseFunctionDeclaration() -> Node { CARBON_DIAGNOSTIC(ExpectedFunctionParams, Error, "Expected `(` after function name."); emitter_.Emit(open_paren, ExpectedFunctionParams); - SkipPastLikelyEnd(function_intro_token, handle_semi_in_error_recovery); - return add_error_function_node(); + return add_error_function_node(true); } TokenizedBuffer::Token close_paren = tokens_.GetMatchedClosingToken(open_paren); if (!ParseFunctionSignature()) { - // Don't try to parse more of the function declaration, but consume a - // declaration ending semicolon if found (without going to a new line). - SkipPastLikelyEnd(function_intro_token, handle_semi_in_error_recovery); - return add_error_function_node(); + return add_error_function_node(true); } - // See if we should parse a definition which is represented as a code block. - if (NextTokenIs(TokenKind::OpenCurlyBrace())) { - if (!ParseCodeBlock()) { - return add_error_function_node(); + switch (NextTokenKind()) { + case TokenKind::OpenCurlyBrace(): { + // Parse a definition which is represented as a code block. + if (auto node = + ParseCodeBlock(start, ParseNodeKind::FunctionDefinitionStart(), + ParseNodeKind::FunctionDefinition())) { + return *node; + } + return add_error_function_node(false); } - } else if (!ConsumeAndAddLeafNodeIf(TokenKind::Semi(), - ParseNodeKind::DeclarationEnd())) { - CARBON_DIAGNOSTIC( - ExpectedFunctionBodyOrSemi, Error, - "Expected function definition or `;` after function declaration."); - emitter_.Emit(*position_, ExpectedFunctionBodyOrSemi); - if (tokens_.GetLine(*position_) == tokens_.GetLine(close_paren)) { + case TokenKind::Semi(): { + return AddNode(ParseNodeKind::FunctionDeclaration(), + Consume(TokenKind::Semi()), start); + } + default: { + CARBON_DIAGNOSTIC( + ExpectedFunctionBodyOrSemi, Error, + "Expected function definition or `;` after function declaration."); + emitter_.Emit(*position_, ExpectedFunctionBodyOrSemi); // Only need to skip if we've not already found a new line. - SkipPastLikelyEnd(function_intro_token, handle_semi_in_error_recovery); + return add_error_function_node(tokens_.GetLine(*position_) == + tokens_.GetLine(close_paren)); } - return add_error_function_node(); } - - // Successfully parsed the function, add that node. - return AddNode(ParseNodeKind::FunctionDeclaration(), function_intro_token, - start); } auto ParseTree::Parser::ParseVariableDeclaration() -> Node { @@ -625,9 +643,10 @@ auto ParseTree::Parser::ParseVariableDeclaration() -> Node { ParseNodeKind::DeclarationEnd()); if (!semi) { emitter_.Emit(*position_, ExpectedSemiAfterExpression); - SkipPastLikelyEnd(var_token, [&](TokenizedBuffer::Token semi) { - return AddLeafNode(ParseNodeKind::DeclarationEnd(), semi); - }); + if (auto semi_token = SkipPastLikelyEnd(var_token)) { + semi = AddLeafNode(ParseNodeKind::DeclarationEnd(), *semi_token, + /*has_error=*/true); + } } return AddNode(ParseNodeKind::VariableDeclaration(), var_token, start, @@ -665,12 +684,9 @@ auto ParseTree::Parser::ParseDeclaration() -> llvm::Optional { // Skip forward past any end of a declaration we simply didn't understand so // that we can find the start of the next declaration or the end of a scope. - if (auto found_semi_n = - SkipPastLikelyEnd(*position_, [&](TokenizedBuffer::Token semi) { - return AddLeafNode(ParseNodeKind::EmptyDeclaration(), semi); - })) { - MarkNodeError(*found_semi_n); - return *found_semi_n; + if (auto semi_token = SkipPastLikelyEnd(*position_)) { + return AddLeafNode(ParseNodeKind::EmptyDeclaration(), *semi_token, + /*has_error=*/true); } // Nothing, not even a semicolon found. @@ -759,8 +775,8 @@ auto ParseTree::Parser::ParseBraceExpression() -> llvm::Optional { } kind = elem_kind; - // Struct type fields and value fields use the same grammar except that - // one has a `:` separator and the other has an `=` separator. + // Struct type fields and value fields use the same grammar except + // that one has a `:` separator and the other has an `=` separator. auto equal_or_colon_token = Consume(kind == Type ? TokenKind::Colon() : TokenKind::Equal()); auto type_or_value = ParseExpression(); @@ -877,8 +893,8 @@ auto ParseTree::Parser::ParsePostfixExpression() -> llvm::Optional { default: return expression; } - // This is subject to an infinite loop if a child call fails, so monitor for - // stalling. + // This is subject to an infinite loop if a child call fails, so monitor + // for stalling. if (last_position == position_) { CARBON_CHECK(expression == llvm::None); return expression; @@ -895,8 +911,8 @@ static auto IsAssumedStartOfOperand(TokenKind kind) -> bool { TokenKind::StringLiteral()}); } -// Determines whether the given token is considered to be the end of an operand -// according to the rules for infix operator parsing. +// Determines whether the given token is considered to be the end of an +// operand according to the rules for infix operator parsing. static auto IsAssumedEndOfOperand(TokenKind kind) -> bool { return kind.IsOneOf({TokenKind::CloseParen(), TokenKind::CloseCurlyBrace(), TokenKind::CloseSquareBracket(), TokenKind::Identifier(), @@ -904,9 +920,9 @@ static auto IsAssumedEndOfOperand(TokenKind kind) -> bool { TokenKind::StringLiteral()}); } -// Determines whether the given token could possibly be the start of an operand. -// This is conservatively correct, and will never incorrectly return `false`, -// but can incorrectly return `true`. +// Determines whether the given token could possibly be the start of an +// operand. This is conservatively correct, and will never incorrectly return +// `false`, but can incorrectly return `true`. static auto IsPossibleStartOfOperand(TokenKind kind) -> bool { return !kind.IsOneOf({TokenKind::CloseParen(), TokenKind::CloseCurlyBrace(), TokenKind::CloseSquareBracket(), TokenKind::Comma(), @@ -1113,12 +1129,9 @@ auto ParseTree::Parser::ParseExpressionStatement() -> llvm::Optional { emitter_.Emit(*position_, ExpectedSemiAfterExpression); } - if (auto recovery_node = - SkipPastLikelyEnd(start_token, [&](TokenizedBuffer::Token semi) { - return AddNode(ParseNodeKind::ExpressionStatement(), semi, start, - true); - })) { - return recovery_node; + if (auto semi_token = SkipPastLikelyEnd(start_token)) { + return AddNode(ParseNodeKind::ExpressionStatement(), *semi_token, start, + /*has_error=*/true); } // Found junk not even followed by a `;`. @@ -1196,11 +1209,11 @@ auto ParseTree::Parser::ParseForStatement() -> llvm::Optional { "not implemented yet!", TokenKind); emitter_.Emit(*position_, ExpectedParenAfter, TokenKind::For()); - // TODO: A proper recovery strategy is needed here. For now, I assume that - // all brackets are properly balanced (i.e. each open bracket has a + // TODO: A proper recovery strategy is needed here. For now, I assume + // that all brackets are properly balanced (i.e. each open bracket has a // closing one). - // This is temporary until we come to a conclusion regarding the recovery - // tokens strategy. + // This is temporary until we come to a conclusion regarding the + // recovery tokens strategy. return llvm::None; } @@ -1224,8 +1237,8 @@ auto ParseTree::Parser::ParseForStatement() -> llvm::Optional { } // A separator is either an `in` or a `:`. Even though `:` is incorrect, - // accidentally typing it by a C++ programmer might be a common mistake that - // warrants special handling. + // accidentally typing it by a C++ programmer might be a common mistake + // that warrants special handling. bool separator_parsed = false; bool in_parsed = false; diff --git a/toolchain/parser/parser_impl.h b/toolchain/parser/parser_impl.h index b6470303c08d..04cadefbd011 100644 --- a/toolchain/parser/parser_impl.h +++ b/toolchain/parser/parser_impl.h @@ -64,7 +64,8 @@ class ParseTree::Parser { // // This sets up the next sibling of the node to be the next node in the parse // tree's preorder sequence. - auto AddLeafNode(ParseNodeKind kind, TokenizedBuffer::Token token) -> Node; + auto AddLeafNode(ParseNodeKind kind, TokenizedBuffer::Token token, + bool has_error = false) -> Node; // Composes `ConsumeIf` and `AddLeafNode`, propagating the failure case // through the optional. @@ -123,11 +124,10 @@ class ParseTree::Parser { // less indentation, there is likely a missing semicolon. Continued // declarations or statements across multiple lines should be indented. // - // If we find a semicolon based on this skipping, we call `on_semi_` to try - // to build a parse node to represent it, and will return that node. + // If we find a semicolon based on this skipping, we return that token. // Otherwise we will return an empty optional. - auto SkipPastLikelyEnd(TokenizedBuffer::Token skip_root, SemiHandler on_semi) - -> llvm::Optional; + auto SkipPastLikelyEnd(TokenizedBuffer::Token skip_root) + -> llvm::Optional; // Parses a close paren token corresponding to the given open paren token, // possibly skipping forward and diagnosing if necessary. Creates and returns @@ -164,10 +164,16 @@ class ParseTree::Parser { // Parses a block of code: `{ ... }`. // - // These can form the definition for a function or be nested within a function - // definition. These contain variable declarations and statements. + // These contain variable declarations and statements. auto ParseCodeBlock() -> llvm::Optional; + // Similar to ParseCodeBlock(), but supports different ParseNodeKinds because + // function definitions are represented differently from other code blocks. + // If subtree_start is before start_kind, earlier nodes will be treated as + // children of the start_kind node. + auto ParseCodeBlock(SubtreeStart subtree_start, ParseNodeKind start_kind, + ParseNodeKind end_kind) -> llvm::Optional; + // Parses a function declaration with an optional definition. Returns the // function parse node which is based on the `fn` introducer keyword. auto ParseFunctionDeclaration() -> Node; diff --git a/toolchain/parser/testdata/basics/fail_invalid_designators.carbon b/toolchain/parser/testdata/basics/fail_invalid_designators.carbon index 7d7e68928144..132e4b4345d5 100644 --- a/toolchain/parser/testdata/basics/fail_invalid_designators.carbon +++ b/toolchain/parser/testdata/basics/fail_invalid_designators.carbon @@ -5,22 +5,22 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 15, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 14, kind: 'CodeBlock', text: '{', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'ExpressionStatement', text: ';', has_error: yes, subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'DesignatorExpression', text: '.', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}]}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'ExpressionStatement', text: ';', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'DesignatorExpression', text: '.', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 7, kind: 'DesignatedName', text: 'fn', has_error: yes}]}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'ExpressionStatement', text: ';', has_error: yes, subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'DesignatorExpression', text: '.', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'a'}]}]}, -// CHECK:STDOUT: {node_index: 13, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 15, kind: 'FunctionDefinition', text: '}', subtree_size: 16, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 7, kind: 'ExpressionStatement', text: ';', has_error: yes, subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'DesignatorExpression', text: '.', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}]}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'ExpressionStatement', text: ';', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 10, kind: 'DesignatorExpression', text: '.', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 9, kind: 'DesignatedName', text: 'fn', has_error: yes}]}]}, +// CHECK:STDOUT: {node_index: 14, kind: 'ExpressionStatement', text: ';', has_error: yes, subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'DesignatorExpression', text: '.', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'a'}]}]}]}, // CHECK:STDOUT: {node_index: 16, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/basics/function_call.carbon b/toolchain/parser/testdata/basics/function_call.carbon index 5294b6809343..fe55b71ba1b2 100644 --- a/toolchain/parser/testdata/basics/function_call.carbon +++ b/toolchain/parser/testdata/basics/function_call.carbon @@ -5,31 +5,31 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 24, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 25, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: '{', subtree_size: 21, children: [ -// CHECK:STDOUT: {node_index: 21, kind: 'ExpressionStatement', text: ';', subtree_size: 19, children: [ -// CHECK:STDOUT: {node_index: 20, kind: 'CallExpression', text: '(', subtree_size: 18, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'DesignatorExpression', text: '.', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 16, kind: 'CallExpression', text: '(', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'DesignatorExpression', text: '.', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'DesignatorExpression', text: '.', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'DesignatedName', text: 'b'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'DesignatedName', text: 'f'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'DesignatorExpression', text: '.', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'c'}, -// CHECK:STDOUT: {node_index: 9, kind: 'DesignatedName', text: 'd'}]}, -// CHECK:STDOUT: {node_index: 11, kind: 'CallExpressionComma', text: ','}, -// CHECK:STDOUT: {node_index: 14, kind: 'ParenExpression', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'e'}, -// CHECK:STDOUT: {node_index: 13, kind: 'ParenExpressionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'CallExpressionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'DesignatedName', text: 'g'}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 24, kind: 'FunctionDefinition', text: '}', subtree_size: 25, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'ExpressionStatement', text: ';', subtree_size: 19, children: [ +// CHECK:STDOUT: {node_index: 22, kind: 'CallExpression', text: '(', subtree_size: 18, children: [ +// CHECK:STDOUT: {node_index: 20, kind: 'DesignatorExpression', text: '.', subtree_size: 16, children: [ +// CHECK:STDOUT: {node_index: 18, kind: 'CallExpression', text: '(', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'DesignatorExpression', text: '.', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'DesignatorExpression', text: '.', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'DesignatedName', text: 'b'}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'DesignatedName', text: 'f'}]}, +// CHECK:STDOUT: {node_index: 12, kind: 'DesignatorExpression', text: '.', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'c'}, +// CHECK:STDOUT: {node_index: 11, kind: 'DesignatedName', text: 'd'}]}, +// CHECK:STDOUT: {node_index: 13, kind: 'CallExpressionComma', text: ','}, +// CHECK:STDOUT: {node_index: 16, kind: 'ParenExpression', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'e'}, +// CHECK:STDOUT: {node_index: 15, kind: 'ParenExpressionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 17, kind: 'CallExpressionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'DesignatedName', text: 'g'}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'CallExpressionEnd', text: ')'}]}]}]}, // CHECK:STDOUT: {node_index: 25, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/basics/return.carbon b/toolchain/parser/testdata/basics/return.carbon index 4780a5ef9223..5ea95624f6ab 100644 --- a/toolchain/parser/testdata/basics/return.carbon +++ b/toolchain/parser/testdata/basics/return.carbon @@ -5,34 +5,34 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 13, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlock', text: '{', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'c'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'ReturnStatement', text: 'return', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'StatementEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 27, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'DeclaredName', text: 'G'}, -// CHECK:STDOUT: {node_index: 19, kind: 'ParameterList', text: '(', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 17, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'DeclaredName', text: 'x'}, -// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'Foo'}]}, -// CHECK:STDOUT: {node_index: 18, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 21, kind: 'ReturnType', text: '->', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 20, kind: 'NameReference', text: 'Foo'}]}, -// CHECK:STDOUT: {node_index: 26, kind: 'CodeBlock', text: '{', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 24, kind: 'ReturnStatement', text: 'return', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 23, kind: 'StatementEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 25, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 13, kind: 'FunctionDefinition', text: '}', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 12, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'c'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ReturnStatement', text: 'return', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'StatementEnd', text: ';'}]}]}]}]}, +// CHECK:STDOUT: {node_index: 27, kind: 'FunctionDefinition', text: '}', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 23, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 15, kind: 'DeclaredName', text: 'G'}, +// CHECK:STDOUT: {node_index: 20, kind: 'ParameterList', text: '(', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 18, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'DeclaredName', text: 'x'}, +// CHECK:STDOUT: {node_index: 17, kind: 'NameReference', text: 'Foo'}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'ParameterListEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 22, kind: 'ReturnType', text: '->', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 21, kind: 'NameReference', text: 'Foo'}]}]}, +// CHECK:STDOUT: {node_index: 26, kind: 'ReturnStatement', text: 'return', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 24, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 25, kind: 'StatementEnd', text: ';'}]}]}, // CHECK:STDOUT: {node_index: 28, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/basics/var.carbon b/toolchain/parser/testdata/basics/var.carbon index c84898fd165b..36a0761080ab 100644 --- a/toolchain/parser/testdata/basics/var.carbon +++ b/toolchain/parser/testdata/basics/var.carbon @@ -17,19 +17,19 @@ // CHECK:STDOUT: {node_index: 7, kind: 'DeclaredName', text: 'w'}, // CHECK:STDOUT: {node_index: 8, kind: 'Literal', text: 'i32'}]}, // CHECK:STDOUT: {node_index: 10, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 24, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 13, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 14, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: '{', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 21, kind: 'VariableDeclaration', text: 'var', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 17, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'DeclaredName', text: 's'}, -// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'String'}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'VariableInitializer', text: '=', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'Literal', text: '"hello"'}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 24, kind: 'FunctionDefinition', text: '}', subtree_size: 13, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 13, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 15, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'VariableDeclaration', text: 'var', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 19, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'DeclaredName', text: 's'}, +// CHECK:STDOUT: {node_index: 18, kind: 'NameReference', text: 'String'}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'VariableInitializer', text: '=', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 20, kind: 'Literal', text: '"hello"'}]}, +// CHECK:STDOUT: {node_index: 22, kind: 'DeclarationEnd', text: ';'}]}]}, // CHECK:STDOUT: {node_index: 25, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon b/toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon index 907e134f880a..864af413d9d8 100644 --- a/toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon +++ b/toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon @@ -5,27 +5,27 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 20, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 21, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlock', text: '{', subtree_size: 17, children: [ -// CHECK:STDOUT: {node_index: 17, kind: 'ForStatement', text: 'for', subtree_size: 15, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'x'}, -// CHECK:STDOUT: {node_index: 4, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'NameReference', text: 'y'}, -// CHECK:STDOUT: {node_index: 8, kind: 'ForHeaderEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'Print'}, -// CHECK:STDOUT: {node_index: 11, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 12, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 18, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 20, kind: 'FunctionDefinition', text: '}', subtree_size: 21, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'ForStatement', text: 'for', subtree_size: 15, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'DeclaredName', text: 'x'}, +// CHECK:STDOUT: {node_index: 6, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'y'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ForHeaderEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 17, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'Print'}, +// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 15, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 21, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/for/fail_missing_in.carbon b/toolchain/parser/testdata/for/fail_missing_in.carbon index 1dfcd75aeefb..fd764e3b343f 100644 --- a/toolchain/parser/testdata/for/fail_missing_in.carbon +++ b/toolchain/parser/testdata/for/fail_missing_in.carbon @@ -5,26 +5,26 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 19, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 20, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 18, kind: 'CodeBlock', text: '{', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 16, kind: 'ForStatement', text: 'for', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'x'}, -// CHECK:STDOUT: {node_index: 4, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'ForHeaderEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'Print'}, -// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 11, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 14, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'FunctionDefinition', text: '}', subtree_size: 20, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'ForStatement', text: 'for', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 10, kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'DeclaredName', text: 'x'}, +// CHECK:STDOUT: {node_index: 6, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'ForHeaderEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 16, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 15, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'Print'}, +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 14, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 20, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/for/fail_missing_var.carbon b/toolchain/parser/testdata/for/fail_missing_var.carbon index c8720cae7d31..6affddd41096 100644 --- a/toolchain/parser/testdata/for/fail_missing_var.carbon +++ b/toolchain/parser/testdata/for/fail_missing_var.carbon @@ -5,24 +5,24 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 17, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 18, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlock', text: '{', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'ForStatement', text: 'for', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'ForIn', text: 'in'}, -// CHECK:STDOUT: {node_index: 4, kind: 'NameReference', text: 'y'}, -// CHECK:STDOUT: {node_index: 5, kind: 'ForHeaderEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 13, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'NameReference', text: 'Print'}, -// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 9, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 17, kind: 'FunctionDefinition', text: '}', subtree_size: 18, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 16, kind: 'ForStatement', text: 'for', subtree_size: 12, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'ForIn', text: 'in'}, +// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'y'}, +// CHECK:STDOUT: {node_index: 7, kind: 'ForHeaderEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 14, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'Print'}, +// CHECK:STDOUT: {node_index: 11, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 12, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 18, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/for/nested.carbon b/toolchain/parser/testdata/for/nested.carbon index 849b3ff723d3..eb41d9b35dfa 100644 --- a/toolchain/parser/testdata/for/nested.carbon +++ b/toolchain/parser/testdata/for/nested.carbon @@ -5,39 +5,39 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 32, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 33, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 31, kind: 'CodeBlock', text: '{', subtree_size: 29, children: [ -// CHECK:STDOUT: {node_index: 29, kind: 'ForStatement', text: 'for', subtree_size: 27, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'ForHeader', text: '(', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'y'}, -// CHECK:STDOUT: {node_index: 4, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'ForIn', text: 'in'}, -// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 9, kind: 'ForHeaderEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 28, kind: 'CodeBlock', text: '{', subtree_size: 18, children: [ -// CHECK:STDOUT: {node_index: 26, kind: 'ForStatement', text: 'for', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'ForHeader', text: '(', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'DeclaredName', text: 'z'}, -// CHECK:STDOUT: {node_index: 12, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'ForIn', text: 'in'}, -// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'y'}, -// CHECK:STDOUT: {node_index: 17, kind: 'ForHeaderEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 25, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 23, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 19, kind: 'NameReference', text: 'Print'}, -// CHECK:STDOUT: {node_index: 20, kind: 'NameReference', text: 'z'}, -// CHECK:STDOUT: {node_index: 21, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 27, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 30, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 32, kind: 'FunctionDefinition', text: '}', subtree_size: 33, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 31, kind: 'ForStatement', text: 'for', subtree_size: 27, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'ForHeader', text: '(', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'DeclaredName', text: 'y'}, +// CHECK:STDOUT: {node_index: 6, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'ForIn', text: 'in'}, +// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 11, kind: 'ForHeaderEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 30, kind: 'CodeBlock', text: '}', subtree_size: 18, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 29, kind: 'ForStatement', text: 'for', subtree_size: 16, children: [ +// CHECK:STDOUT: {node_index: 21, kind: 'ForHeader', text: '(', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'DeclaredName', text: 'z'}, +// CHECK:STDOUT: {node_index: 15, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'ForIn', text: 'in'}, +// CHECK:STDOUT: {node_index: 19, kind: 'NameReference', text: 'y'}, +// CHECK:STDOUT: {node_index: 20, kind: 'ForHeaderEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 28, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 27, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 26, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 23, kind: 'NameReference', text: 'Print'}, +// CHECK:STDOUT: {node_index: 24, kind: 'NameReference', text: 'z'}, +// CHECK:STDOUT: {node_index: 25, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 33, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/for/simple.carbon b/toolchain/parser/testdata/for/simple.carbon index fae5d92f2aa1..a3d6749b9a70 100644 --- a/toolchain/parser/testdata/for/simple.carbon +++ b/toolchain/parser/testdata/for/simple.carbon @@ -5,28 +5,28 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 21, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 22, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlock', text: '{', subtree_size: 18, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'ForStatement', text: 'for', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'ForHeader', text: '(', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'x'}, -// CHECK:STDOUT: {node_index: 4, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'ForIn', text: 'in'}, -// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'y'}, -// CHECK:STDOUT: {node_index: 9, kind: 'ForHeaderEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'NameReference', text: 'Print'}, -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 13, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'FunctionDefinition', text: '}', subtree_size: 22, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 20, kind: 'ForStatement', text: 'for', subtree_size: 16, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'ForHeader', text: '(', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'VariableDeclaration', text: 'var', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'DeclaredName', text: 'x'}, +// CHECK:STDOUT: {node_index: 6, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'ForIn', text: 'in'}, +// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'y'}, +// CHECK:STDOUT: {node_index: 11, kind: 'ForHeaderEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 18, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'Print'}, +// CHECK:STDOUT: {node_index: 15, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 16, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 22, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/basic.carbon b/toolchain/parser/testdata/function/declaration/basic.carbon index c587ded55d19..3ae6a53a6b12 100644 --- a/toolchain/parser/testdata/function/declaration/basic.carbon +++ b/toolchain/parser/testdata/function/declaration/basic.carbon @@ -5,11 +5,11 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 3, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, // CHECK:STDOUT: {node_index: 5, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon b/toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon index d1f527659c90..1d5461a9479b 100644 --- a/toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon @@ -5,9 +5,9 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 2, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 1, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 2, kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}]}, // CHECK:STDOUT: {node_index: 3, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_missing_name.carbon b/toolchain/parser/testdata/function/declaration/fail_missing_name.carbon index 87ceefa60631..6ace8443a129 100644 --- a/toolchain/parser/testdata/function/declaration/fail_missing_name.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_missing_name.carbon @@ -5,8 +5,8 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, // CHECK:STDOUT: {node_index: 2, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon b/toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon index ed0c9443971d..daf433c5a47a 100644 --- a/toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon @@ -5,9 +5,10 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}]}, -// CHECK:STDOUT: {node_index: 2, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: {node_index: 2, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}]}, +// CHECK:STDOUT: {node_index: 3, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon:[[@LINE+1]]:7: Expected `(` after function name. diff --git a/toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon b/toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon index 2bc5c00b82aa..74be1a2fd4b2 100644 --- a/toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon @@ -5,8 +5,8 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, // CHECK:STDOUT: {node_index: 2, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon b/toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon index 1efb9a7c1cf9..bb9da47ed263 100644 --- a/toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon @@ -5,8 +5,8 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, // CHECK:STDOUT: {node_index: 2, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon b/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon index 78f4bef3853d..7e8eb26186f1 100644 --- a/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon @@ -5,13 +5,14 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 0, kind: 'FunctionDeclaration', text: 'fn', has_error: yes}, -// CHECK:STDOUT: {node_index: 5, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 5, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 7, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon:[[@LINE+1]]:6: Expected function name after `fn` keyword. diff --git a/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon b/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon index 6dfe690724df..e49ab0451cf5 100644 --- a/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon @@ -5,13 +5,13 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 2, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 5, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 5, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'ParameterListEnd', text: ')'}]}]}, // CHECK:STDOUT: {node_index: 7, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon b/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon index a37fe5148d85..189734b7c2bb 100644 --- a/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon @@ -5,13 +5,14 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 0, kind: 'FunctionDeclaration', text: 'fn', has_error: yes}, -// CHECK:STDOUT: {node_index: 5, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 5, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 7, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon:[[@LINE+1]]:4: Expected function name after `fn` keyword. diff --git a/toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon b/toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon index 0d97c5bd2940..cdd83ef0fdbe 100644 --- a/toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon @@ -5,13 +5,14 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 0, kind: 'FunctionDeclaration', text: 'fn', has_error: yes}, -// CHECK:STDOUT: {node_index: 5, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 3, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 5, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 7, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon:[[@LINE+1]]:4: Expected function name after `fn` keyword. diff --git a/toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon b/toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon index badc7570fdcc..c476e8d00ae2 100644 --- a/toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon @@ -5,11 +5,11 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 3, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, // CHECK:STDOUT: {node_index: 5, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon b/toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon index 65dd48d1582e..d048694346f7 100644 --- a/toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon @@ -5,11 +5,11 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 3, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDeclaration', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, // CHECK:STDOUT: {node_index: 5, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon b/toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon index a00978bb14a4..fc42886f609b 100644 --- a/toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon +++ b/toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon @@ -5,8 +5,8 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 1, kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}]}, // CHECK:STDOUT: {node_index: 2, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/with_params.carbon b/toolchain/parser/testdata/function/declaration/with_params.carbon index d43e26e477e0..0d3b8afbdf3f 100644 --- a/toolchain/parser/testdata/function/declaration/with_params.carbon +++ b/toolchain/parser/testdata/function/declaration/with_params.carbon @@ -5,18 +5,18 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 9, kind: 'ParameterList', text: '(', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'bar'}, -// CHECK:STDOUT: {node_index: 2, kind: 'Literal', text: 'i32'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'ParameterListComma', text: ','}, -// CHECK:STDOUT: {node_index: 7, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'DeclaredName', text: 'baz'}, -// CHECK:STDOUT: {node_index: 6, kind: 'Literal', text: 'i32'}]}, -// CHECK:STDOUT: {node_index: 8, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDeclaration', text: ';', subtree_size: 12, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ParameterList', text: '(', subtree_size: 9, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'DeclaredName', text: 'bar'}, +// CHECK:STDOUT: {node_index: 3, kind: 'Literal', text: 'i32'}]}, +// CHECK:STDOUT: {node_index: 5, kind: 'ParameterListComma', text: ','}, +// CHECK:STDOUT: {node_index: 8, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'DeclaredName', text: 'baz'}, +// CHECK:STDOUT: {node_index: 7, kind: 'Literal', text: 'i32'}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'ParameterListEnd', text: ')'}]}]}, // CHECK:STDOUT: {node_index: 12, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/declaration/with_return_type.carbon b/toolchain/parser/testdata/function/declaration/with_return_type.carbon index 0e9e64dc7eb8..10754d9893f0 100644 --- a/toolchain/parser/testdata/function/declaration/with_return_type.carbon +++ b/toolchain/parser/testdata/function/declaration/with_return_type.carbon @@ -5,13 +5,13 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'ReturnType', text: '->', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'Literal', text: 'u32'}]}, -// CHECK:STDOUT: {node_index: 5, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: ';', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 5, kind: 'ReturnType', text: '->', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'Literal', text: 'u32'}]}]}, // CHECK:STDOUT: {node_index: 7, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/definition/basic.carbon b/toolchain/parser/testdata/function/definition/basic.carbon index 2cd063314cbc..f7e2360707b3 100644 --- a/toolchain/parser/testdata/function/definition/basic.carbon +++ b/toolchain/parser/testdata/function/definition/basic.carbon @@ -5,12 +5,12 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 5, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'CodeBlock', text: '{', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 5, kind: 'FunctionDefinition', text: '}', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}]}, // CHECK:STDOUT: {node_index: 6, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon b/toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon index 27818a2d4b8f..13085d6a1897 100644 --- a/toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon +++ b/toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon @@ -5,13 +5,13 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 5, kind: 'CodeBlock', text: '{', has_error: yes, subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'bar'}, -// CHECK:STDOUT: {node_index: 4, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDefinition', text: '}', has_error: yes, subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'bar'}]}, // CHECK:STDOUT: {node_index: 7, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/definition/with_params.carbon b/toolchain/parser/testdata/function/definition/with_params.carbon index e310d9cad081..4b422c1fb09a 100644 --- a/toolchain/parser/testdata/function/definition/with_params.carbon +++ b/toolchain/parser/testdata/function/definition/with_params.carbon @@ -5,28 +5,28 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 21, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 22, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 9, kind: 'ParameterList', text: '(', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'bar'}, -// CHECK:STDOUT: {node_index: 2, kind: 'Literal', text: 'i64'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'ParameterListComma', text: ','}, -// CHECK:STDOUT: {node_index: 7, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'DeclaredName', text: 'baz'}, -// CHECK:STDOUT: {node_index: 6, kind: 'Literal', text: 'i64'}]}, -// CHECK:STDOUT: {node_index: 8, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlock', text: '{', subtree_size: 11, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'ExpressionStatement', text: ';', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 17, kind: 'CallExpression', text: '(', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'foo'}, -// CHECK:STDOUT: {node_index: 11, kind: 'NameReference', text: 'baz'}, -// CHECK:STDOUT: {node_index: 12, kind: 'CallExpressionComma', text: ','}, -// CHECK:STDOUT: {node_index: 15, kind: 'InfixOperator', text: '+', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'bar'}, -// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'baz'}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'FunctionDefinition', text: '}', subtree_size: 22, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 12, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ParameterList', text: '(', subtree_size: 9, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'DeclaredName', text: 'bar'}, +// CHECK:STDOUT: {node_index: 3, kind: 'Literal', text: 'i64'}]}, +// CHECK:STDOUT: {node_index: 5, kind: 'ParameterListComma', text: ','}, +// CHECK:STDOUT: {node_index: 8, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'DeclaredName', text: 'baz'}, +// CHECK:STDOUT: {node_index: 7, kind: 'Literal', text: 'i64'}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 20, kind: 'ExpressionStatement', text: ';', subtree_size: 9, children: [ +// CHECK:STDOUT: {node_index: 19, kind: 'CallExpression', text: '(', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'foo'}, +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'baz'}, +// CHECK:STDOUT: {node_index: 14, kind: 'CallExpressionComma', text: ','}, +// CHECK:STDOUT: {node_index: 17, kind: 'InfixOperator', text: '+', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 15, kind: 'NameReference', text: 'bar'}, +// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'baz'}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'CallExpressionEnd', text: ')'}]}]}]}, // CHECK:STDOUT: {node_index: 22, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/function/definition/with_return_type.carbon b/toolchain/parser/testdata/function/definition/with_return_type.carbon index 71480193c9ae..3c2455401ff5 100644 --- a/toolchain/parser/testdata/function/definition/with_return_type.carbon +++ b/toolchain/parser/testdata/function/definition/with_return_type.carbon @@ -5,17 +5,17 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 10, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 11, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'foo'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 4, kind: 'ReturnType', text: '->', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'Literal', text: 'f64'}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlock', text: '{', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'ReturnStatement', text: 'return', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Literal', text: '42'}, -// CHECK:STDOUT: {node_index: 6, kind: 'StatementEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 10, kind: 'FunctionDefinition', text: '}', subtree_size: 11, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'foo'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 5, kind: 'ReturnType', text: '->', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'Literal', text: 'f64'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'ReturnStatement', text: 'return', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Literal', text: '42'}, +// CHECK:STDOUT: {node_index: 8, kind: 'StatementEnd', text: ';'}]}]}, // CHECK:STDOUT: {node_index: 11, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/if/basic.carbon b/toolchain/parser/testdata/if/basic.carbon index fe40ac995f86..63968f849d4c 100644 --- a/toolchain/parser/testdata/if/basic.carbon +++ b/toolchain/parser/testdata/if/basic.carbon @@ -5,32 +5,32 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 25, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 26, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlock', text: '{', subtree_size: 22, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'IfStatement', text: 'if', subtree_size: 20, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 21, kind: 'CodeBlock', text: '{', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 19, kind: 'IfStatement', text: 'if', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}, -// CHECK:STDOUT: {node_index: 7, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 18, kind: 'CodeBlock', text: '{', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 16, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'c'}, -// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'd'}]}, -// CHECK:STDOUT: {node_index: 14, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 25, kind: 'FunctionDefinition', text: '}', subtree_size: 26, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 24, kind: 'IfStatement', text: 'if', subtree_size: 20, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: '}', subtree_size: 16, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 22, kind: 'IfStatement', text: 'if', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'b'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'CodeBlock', text: '}', subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 20, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 15, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'c'}, +// CHECK:STDOUT: {node_index: 14, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 18, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'NameReference', text: 'd'}]}]}]}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 26, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/if/else.carbon b/toolchain/parser/testdata/if/else.carbon index d11507a63585..24298892d188 100644 --- a/toolchain/parser/testdata/if/else.carbon +++ b/toolchain/parser/testdata/if/else.carbon @@ -5,67 +5,67 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 60, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 61, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 59, kind: 'CodeBlock', text: '{', subtree_size: 57, children: [ -// CHECK:STDOUT: {node_index: 26, kind: 'IfStatement', text: 'if', subtree_size: 24, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlock', text: '{', subtree_size: 15, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'IfStatement', text: 'if', subtree_size: 13, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}, -// CHECK:STDOUT: {node_index: 7, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'c'}]}, -// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlockEnd', text: '}'}]}, -// CHECK:STDOUT: {node_index: 13, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'd'}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlockEnd', text: '}'}]}, -// CHECK:STDOUT: {node_index: 21, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 25, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 23, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'NameReference', text: 'e'}]}, -// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 57, kind: 'IfStatement', text: 'if', subtree_size: 31, children: [ -// CHECK:STDOUT: {node_index: 29, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 27, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 28, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 36, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 34, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 33, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 30, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 31, kind: 'Literal', text: '1'}, -// CHECK:STDOUT: {node_index: 32, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 35, kind: 'CodeBlockEnd', text: '}'}]}, -// CHECK:STDOUT: {node_index: 37, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 56, kind: 'IfStatement', text: 'if', subtree_size: 19, children: [ -// CHECK:STDOUT: {node_index: 40, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 38, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 39, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 47, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 45, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 44, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 41, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 42, kind: 'Literal', text: '2'}, -// CHECK:STDOUT: {node_index: 43, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 46, kind: 'CodeBlockEnd', text: '}'}]}, -// CHECK:STDOUT: {node_index: 48, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 55, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 53, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 52, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 49, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 50, kind: 'Literal', text: '3'}, -// CHECK:STDOUT: {node_index: 51, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 54, kind: 'CodeBlockEnd', text: '}'}]}]}]}, -// CHECK:STDOUT: {node_index: 58, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 60, kind: 'FunctionDefinition', text: '}', subtree_size: 61, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 28, kind: 'IfStatement', text: 'if', subtree_size: 24, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlock', text: '}', subtree_size: 15, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 21, kind: 'IfStatement', text: 'if', subtree_size: 13, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'b'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 14, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'c'}]}]}, +// CHECK:STDOUT: {node_index: 16, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 19, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 18, kind: 'NameReference', text: 'd'}]}]}]}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 27, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 26, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 25, kind: 'NameReference', text: 'e'}]}]}]}, +// CHECK:STDOUT: {node_index: 59, kind: 'IfStatement', text: 'if', subtree_size: 31, children: [ +// CHECK:STDOUT: {node_index: 31, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 29, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 30, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 38, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 32, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 37, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 36, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 33, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 34, kind: 'Literal', text: '1'}, +// CHECK:STDOUT: {node_index: 35, kind: 'CallExpressionEnd', text: ')'}]}]}]}, +// CHECK:STDOUT: {node_index: 39, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 58, kind: 'IfStatement', text: 'if', subtree_size: 19, children: [ +// CHECK:STDOUT: {node_index: 42, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 40, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 41, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 49, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 43, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 48, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 47, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 44, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 45, kind: 'Literal', text: '2'}, +// CHECK:STDOUT: {node_index: 46, kind: 'CallExpressionEnd', text: ')'}]}]}]}, +// CHECK:STDOUT: {node_index: 50, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 57, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 51, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 56, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 55, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 52, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 53, kind: 'Literal', text: '3'}, +// CHECK:STDOUT: {node_index: 54, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 61, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/if/else_unbraced.carbon b/toolchain/parser/testdata/if/else_unbraced.carbon deleted file mode 100644 index a3970a016944..000000000000 --- a/toolchain/parser/testdata/if/else_unbraced.carbon +++ /dev/null @@ -1,79 +0,0 @@ -// 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 -// RUN: %{carbon-run-parser} -// CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 52, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 53, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 51, kind: 'CodeBlock', text: '{', subtree_size: 49, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'IfStatement', text: 'if', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 14, kind: 'IfStatement', text: 'if', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}, -// CHECK:STDOUT: {node_index: 7, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'c'}]}, -// CHECK:STDOUT: {node_index: 11, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 13, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'd'}]}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 17, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'e'}]}]}, -// CHECK:STDOUT: {node_index: 49, kind: 'IfStatement', text: 'if', subtree_size: 31, children: [ -// CHECK:STDOUT: {node_index: 21, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 19, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 20, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 28, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 26, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 25, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 23, kind: 'Literal', text: '1'}, -// CHECK:STDOUT: {node_index: 24, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 27, kind: 'CodeBlockEnd', text: '}'}]}, -// CHECK:STDOUT: {node_index: 29, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 48, kind: 'IfStatement', text: 'if', subtree_size: 19, children: [ -// CHECK:STDOUT: {node_index: 32, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 30, kind: 'NameReference', text: 'x'}, -// CHECK:STDOUT: {node_index: 31, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 39, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 37, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 36, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 33, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 34, kind: 'Literal', text: '2'}, -// CHECK:STDOUT: {node_index: 35, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 38, kind: 'CodeBlockEnd', text: '}'}]}, -// CHECK:STDOUT: {node_index: 40, kind: 'IfStatementElse', text: 'else'}, -// CHECK:STDOUT: {node_index: 47, kind: 'CodeBlock', text: '{', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 45, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 44, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 41, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 42, kind: 'Literal', text: '3'}, -// CHECK:STDOUT: {node_index: 43, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 46, kind: 'CodeBlockEnd', text: '}'}]}]}]}, -// CHECK:STDOUT: {node_index: 50, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 53, kind: 'FileEnd', text: ''}, -// CHECK:STDOUT: ] - -fn F() { - if (a) - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/else_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. - if (b) - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/else_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block. - c; - else - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/else_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block. - d; - else - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/else_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. - e; - if (x) { G(1); } - else if (x) { G(2); } - else { G(3); } -} diff --git a/toolchain/parser/testdata/if/fail_else_unbraced.carbon b/toolchain/parser/testdata/if/fail_else_unbraced.carbon new file mode 100644 index 000000000000..b91e59a6efe2 --- /dev/null +++ b/toolchain/parser/testdata/if/fail_else_unbraced.carbon @@ -0,0 +1,87 @@ +// 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 +// RUN: %{not} %{carbon-run-parser} +// CHECK:STDOUT: [ +// CHECK:STDOUT: {node_index: 60, kind: 'FunctionDefinition', text: '}', subtree_size: 61, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 28, kind: 'IfStatement', text: 'if', subtree_size: 24, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlock', text: 'if', has_error: yes, subtree_size: 15, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: 'if', has_error: yes}, +// CHECK:STDOUT: {node_index: 21, kind: 'IfStatement', text: 'if', subtree_size: 13, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'b'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlock', text: 'c', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockStart', text: 'c', has_error: yes}, +// CHECK:STDOUT: {node_index: 14, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'c'}]}]}, +// CHECK:STDOUT: {node_index: 16, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlock', text: 'd', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlockStart', text: 'd', has_error: yes}, +// CHECK:STDOUT: {node_index: 19, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 18, kind: 'NameReference', text: 'd'}]}]}]}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 27, kind: 'CodeBlock', text: 'e', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlockStart', text: 'e', has_error: yes}, +// CHECK:STDOUT: {node_index: 26, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 25, kind: 'NameReference', text: 'e'}]}]}]}, +// CHECK:STDOUT: {node_index: 59, kind: 'IfStatement', text: 'if', subtree_size: 31, children: [ +// CHECK:STDOUT: {node_index: 31, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 29, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 30, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 38, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 32, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 37, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 36, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 33, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 34, kind: 'Literal', text: '1'}, +// CHECK:STDOUT: {node_index: 35, kind: 'CallExpressionEnd', text: ')'}]}]}]}, +// CHECK:STDOUT: {node_index: 39, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 58, kind: 'IfStatement', text: 'if', subtree_size: 19, children: [ +// CHECK:STDOUT: {node_index: 42, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 40, kind: 'NameReference', text: 'x'}, +// CHECK:STDOUT: {node_index: 41, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 49, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 43, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 48, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 47, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 44, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 45, kind: 'Literal', text: '2'}, +// CHECK:STDOUT: {node_index: 46, kind: 'CallExpressionEnd', text: ')'}]}]}]}, +// CHECK:STDOUT: {node_index: 50, kind: 'IfStatementElse', text: 'else'}, +// CHECK:STDOUT: {node_index: 57, kind: 'CodeBlock', text: '}', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 51, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 56, kind: 'ExpressionStatement', text: ';', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 55, kind: 'CallExpression', text: '(', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 52, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 53, kind: 'Literal', text: '3'}, +// CHECK:STDOUT: {node_index: 54, kind: 'CallExpressionEnd', text: ')'}]}]}]}]}]}]}, +// CHECK:STDOUT: {node_index: 61, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] + +fn F() { + if (a) + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_else_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. + if (b) + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_else_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block. + c; + else + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_else_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block. + d; + else + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_else_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. + e; + if (x) { G(1); } + else if (x) { G(2); } + else { G(3); } +} diff --git a/toolchain/parser/testdata/if/fail_errors.carbon b/toolchain/parser/testdata/if/fail_errors.carbon index 9acd6cedcd07..b9b699c7e560 100644 --- a/toolchain/parser/testdata/if/fail_errors.carbon +++ b/toolchain/parser/testdata/if/fail_errors.carbon @@ -5,32 +5,34 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 24, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 25, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: '{', subtree_size: 21, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'IfStatement', text: 'if', has_error: yes, subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 5, kind: 'CodeBlock', text: '{', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 11, kind: 'IfStatement', text: 'if', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'Condition', text: '(', has_error: yes, subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'CodeBlock', text: '{', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'IfStatement', text: 'if', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'Condition', text: '(', has_error: yes, subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'b'}, -// CHECK:STDOUT: {node_index: 13, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlock', text: '{', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 21, kind: 'IfStatement', text: 'if', has_error: yes, subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 20, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'NameReference', text: 'd'}, -// CHECK:STDOUT: {node_index: 19, kind: 'ConditionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 25, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: {node_index: 26, kind: 'FunctionDefinition', text: '}', subtree_size: 27, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'IfStatement', text: 'if', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 7, kind: 'CodeBlock', text: '}', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'CodeBlockStart', text: '{'}]}]}, +// CHECK:STDOUT: {node_index: 13, kind: 'IfStatement', text: 'if', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 10, kind: 'Condition', text: '(', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlock', text: '}', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlockStart', text: '{'}]}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'IfStatement', text: 'if', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'Condition', text: '(', has_error: yes, subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'b'}, +// CHECK:STDOUT: {node_index: 15, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'CodeBlock', text: '}', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlockStart', text: '{'}]}]}, +// CHECK:STDOUT: {node_index: 25, kind: 'IfStatement', text: 'if', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 22, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 20, kind: 'NameReference', text: 'd'}, +// CHECK:STDOUT: {node_index: 21, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlock', text: '}', has_error: yes, subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlockStart', text: '}', has_error: yes}]}]}]}, +// CHECK:STDOUT: {node_index: 27, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] fn F() { diff --git a/toolchain/parser/testdata/if/fail_unbraced.carbon b/toolchain/parser/testdata/if/fail_unbraced.carbon new file mode 100644 index 000000000000..f0879b9c88ed --- /dev/null +++ b/toolchain/parser/testdata/if/fail_unbraced.carbon @@ -0,0 +1,46 @@ +// 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 +// +// TODO: This should have an error. +// AUTOUPDATE +// RUN: %{not} %{carbon-run-parser} +// CHECK:STDOUT: [ +// CHECK:STDOUT: {node_index: 25, kind: 'FunctionDefinition', text: '}', subtree_size: 26, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 24, kind: 'IfStatement', text: 'if', subtree_size: 20, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: 'if', has_error: yes, subtree_size: 16, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: 'if', has_error: yes}, +// CHECK:STDOUT: {node_index: 22, kind: 'IfStatement', text: 'if', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'b'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'CodeBlock', text: 'if', has_error: yes, subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockStart', text: 'if', has_error: yes}, +// CHECK:STDOUT: {node_index: 20, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 15, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'c'}, +// CHECK:STDOUT: {node_index: 14, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlock', text: 'd', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'CodeBlockStart', text: 'd', has_error: yes}, +// CHECK:STDOUT: {node_index: 18, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'NameReference', text: 'd'}]}]}]}]}]}]}]}]}, +// CHECK:STDOUT: {node_index: 26, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] + +fn F() { + if (a) + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. + if (b) + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_unbraced.carbon:[[@LINE+1]]:7: Expected braced code block. + if (c) + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/fail_unbraced.carbon:[[@LINE+1]]:9: Expected braced code block. + d; +} diff --git a/toolchain/parser/testdata/if/unbraced.carbon b/toolchain/parser/testdata/if/unbraced.carbon deleted file mode 100644 index 12698852827a..000000000000 --- a/toolchain/parser/testdata/if/unbraced.carbon +++ /dev/null @@ -1,40 +0,0 @@ -// 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 -// -// TODO: This should have an error. -// AUTOUPDATE -// RUN: %{carbon-run-parser} -// CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 19, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 20, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 18, kind: 'CodeBlock', text: '{', subtree_size: 16, children: [ -// CHECK:STDOUT: {node_index: 16, kind: 'IfStatement', text: 'if', subtree_size: 14, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 15, kind: 'IfStatement', text: 'if', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}, -// CHECK:STDOUT: {node_index: 7, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 14, kind: 'IfStatement', text: 'if', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'c'}, -// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 13, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'd'}]}]}]}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'FileEnd', text: ''}, -// CHECK:STDOUT: ] - -fn F() { - if (a) - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. - if (b) - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/unbraced.carbon:[[@LINE+1]]:7: Expected braced code block. - if (c) - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/if/unbraced.carbon:[[@LINE+1]]:9: Expected braced code block. - d; -} diff --git a/toolchain/parser/testdata/operators/associative.carbon b/toolchain/parser/testdata/operators/associative.carbon index a84fda725ab5..a181d986388d 100644 --- a/toolchain/parser/testdata/operators/associative.carbon +++ b/toolchain/parser/testdata/operators/associative.carbon @@ -5,18 +5,18 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'CodeBlock', text: '{', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'and', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'InfixOperator', text: 'and', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'NameReference', text: 'b'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'c'}]}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDefinition', text: '}', subtree_size: 12, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 10, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'InfixOperator', text: 'and', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'and', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'c'}]}]}]}, // CHECK:STDOUT: {node_index: 12, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/fail_missing_precedence_and_or.carbon b/toolchain/parser/testdata/operators/fail_missing_precedence_and_or.carbon index bfe852daa0a8..d0b13988719b 100644 --- a/toolchain/parser/testdata/operators/fail_missing_precedence_and_or.carbon +++ b/toolchain/parser/testdata/operators/fail_missing_precedence_and_or.carbon @@ -5,18 +5,18 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'CodeBlock', text: '{', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'or', has_error: yes, subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'InfixOperator', text: 'and', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'NameReference', text: 'b'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'c'}]}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDefinition', text: '}', subtree_size: 12, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 10, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'InfixOperator', text: 'or', has_error: yes, subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'and', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'c'}]}]}]}, // CHECK:STDOUT: {node_index: 12, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/fail_missing_precedence_or_and.carbon b/toolchain/parser/testdata/operators/fail_missing_precedence_or_and.carbon index 1e0daa6efedf..94c1abdd78c5 100644 --- a/toolchain/parser/testdata/operators/fail_missing_precedence_or_and.carbon +++ b/toolchain/parser/testdata/operators/fail_missing_precedence_or_and.carbon @@ -5,18 +5,18 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'CodeBlock', text: '{', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'and', has_error: yes, subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'InfixOperator', text: 'or', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'NameReference', text: 'b'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'c'}]}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDefinition', text: '}', subtree_size: 12, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 10, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'InfixOperator', text: 'and', has_error: yes, subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'or', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'c'}]}]}]}, // CHECK:STDOUT: {node_index: 12, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/fail_variety.carbon b/toolchain/parser/testdata/operators/fail_variety.carbon index f4868f00e9f5..c79fc637c95c 100644 --- a/toolchain/parser/testdata/operators/fail_variety.carbon +++ b/toolchain/parser/testdata/operators/fail_variety.carbon @@ -5,33 +5,33 @@ // AUTOUPDATE // RUN: %{not} %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 26, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 27, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 25, kind: 'CodeBlock', text: '{', subtree_size: 23, children: [ -// CHECK:STDOUT: {node_index: 23, kind: 'ExpressionStatement', text: ';', subtree_size: 21, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'InfixOperator', text: '=', subtree_size: 20, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 21, kind: 'InfixOperator', text: '=', subtree_size: 18, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'InfixOperator', text: '+', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'b'}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'NameReference', text: 'c'}, -// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'd'}]}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'InfixOperator', text: '-', has_error: yes, subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 17, kind: 'InfixOperator', text: '&', has_error: yes, subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'InfixOperator', text: '<<', has_error: yes, subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'NameReference', text: 'd'}, -// CHECK:STDOUT: {node_index: 12, kind: 'NameReference', text: 'd'}]}, -// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'e'}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'f'}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'NameReference', text: 'g'}]}]}]}]}]}, -// CHECK:STDOUT: {node_index: 24, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 26, kind: 'FunctionDefinition', text: '}', subtree_size: 27, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 25, kind: 'ExpressionStatement', text: ';', subtree_size: 21, children: [ +// CHECK:STDOUT: {node_index: 24, kind: 'InfixOperator', text: '=', subtree_size: 20, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 23, kind: 'InfixOperator', text: '=', subtree_size: 18, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'InfixOperator', text: '+', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 7, kind: 'NameReference', text: 'b'}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'c'}, +// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'd'}]}]}, +// CHECK:STDOUT: {node_index: 22, kind: 'InfixOperator', text: '-', has_error: yes, subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 19, kind: 'InfixOperator', text: '&', has_error: yes, subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'InfixOperator', text: '<<', has_error: yes, subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 15, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'NameReference', text: 'd'}, +// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'd'}]}, +// CHECK:STDOUT: {node_index: 16, kind: 'NameReference', text: 'e'}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'NameReference', text: 'f'}]}, +// CHECK:STDOUT: {node_index: 21, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 20, kind: 'NameReference', text: 'g'}]}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 27, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/fixity.carbon b/toolchain/parser/testdata/operators/fixity.carbon index 434f10f69859..68011f14b2a5 100644 --- a/toolchain/parser/testdata/operators/fixity.carbon +++ b/toolchain/parser/testdata/operators/fixity.carbon @@ -5,71 +5,71 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 64, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 65, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 10, kind: 'ParameterList', text: '(', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'PatternBinding', text: ':', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'p'}, -// CHECK:STDOUT: {node_index: 3, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 2, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 5, kind: 'ParameterListComma', text: ','}, -// CHECK:STDOUT: {node_index: 8, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'DeclaredName', text: 'n'}, -// CHECK:STDOUT: {node_index: 7, kind: 'Literal', text: 'i32'}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 63, kind: 'CodeBlock', text: '{', subtree_size: 53, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'VariableDeclaration', text: 'var', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'PatternBinding', text: ':', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'DeclaredName', text: 'q'}, -// CHECK:STDOUT: {node_index: 13, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 12, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 16, kind: 'VariableInitializer', text: '=', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 15, kind: 'NameReference', text: 'p'}]}, -// CHECK:STDOUT: {node_index: 17, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 26, kind: 'VariableDeclaration', text: 'var', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 21, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 19, kind: 'DeclaredName', text: 't'}, -// CHECK:STDOUT: {node_index: 20, kind: 'NameReference', text: 'Type'}]}, -// CHECK:STDOUT: {node_index: 24, kind: 'VariableInitializer', text: '=', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 23, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 22, kind: 'Literal', text: 'i32'}]}]}, -// CHECK:STDOUT: {node_index: 25, kind: 'DeclarationEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 32, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 31, kind: 'InfixOperator', text: '=', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 27, kind: 'NameReference', text: 't'}, -// CHECK:STDOUT: {node_index: 30, kind: 'PostfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 29, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 28, kind: 'NameReference', text: 't'}]}]}]}]}, -// CHECK:STDOUT: {node_index: 38, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 37, kind: 'InfixOperator', text: '=', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 33, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 36, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 34, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 35, kind: 'NameReference', text: 'n'}]}]}]}, -// CHECK:STDOUT: {node_index: 45, kind: 'ExpressionStatement', text: ';', subtree_size: 7, children: [ -// CHECK:STDOUT: {node_index: 44, kind: 'InfixOperator', text: '=', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 39, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 43, kind: 'InfixOperator', text: '*', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 40, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 42, kind: 'PrefixOperator', text: '*', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 41, kind: 'NameReference', text: 'p'}]}]}]}]}, -// CHECK:STDOUT: {node_index: 51, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 50, kind: 'InfixOperator', text: '=', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 46, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 49, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 47, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 48, kind: 'NameReference', text: 'n'}]}]}]}, -// CHECK:STDOUT: {node_index: 61, kind: 'ExpressionStatement', text: ';', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 60, kind: 'CallExpression', text: '(', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 52, kind: 'NameReference', text: 'G'}, -// CHECK:STDOUT: {node_index: 54, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 53, kind: 'Literal', text: 'i32'}]}, -// CHECK:STDOUT: {node_index: 55, kind: 'CallExpressionComma', text: ','}, -// CHECK:STDOUT: {node_index: 58, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 56, kind: 'NameReference', text: 'n'}, -// CHECK:STDOUT: {node_index: 57, kind: 'NameReference', text: 'n'}]}, -// CHECK:STDOUT: {node_index: 59, kind: 'CallExpressionEnd', text: ')'}]}]}, -// CHECK:STDOUT: {node_index: 62, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 64, kind: 'FunctionDefinition', text: '}', subtree_size: 65, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 13, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 11, kind: 'ParameterList', text: '(', subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'PatternBinding', text: ':', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'DeclaredName', text: 'p'}, +// CHECK:STDOUT: {node_index: 4, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 3, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 6, kind: 'ParameterListComma', text: ','}, +// CHECK:STDOUT: {node_index: 9, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'DeclaredName', text: 'n'}, +// CHECK:STDOUT: {node_index: 8, kind: 'Literal', text: 'i32'}]}, +// CHECK:STDOUT: {node_index: 10, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 20, kind: 'VariableDeclaration', text: 'var', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 16, kind: 'PatternBinding', text: ':', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'DeclaredName', text: 'q'}, +// CHECK:STDOUT: {node_index: 15, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 14, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 18, kind: 'VariableInitializer', text: '=', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'NameReference', text: 'p'}]}, +// CHECK:STDOUT: {node_index: 19, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 28, kind: 'VariableDeclaration', text: 'var', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 23, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 21, kind: 'DeclaredName', text: 't'}, +// CHECK:STDOUT: {node_index: 22, kind: 'NameReference', text: 'Type'}]}, +// CHECK:STDOUT: {node_index: 26, kind: 'VariableInitializer', text: '=', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 25, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 24, kind: 'Literal', text: 'i32'}]}]}, +// CHECK:STDOUT: {node_index: 27, kind: 'DeclarationEnd', text: ';'}]}, +// CHECK:STDOUT: {node_index: 34, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 33, kind: 'InfixOperator', text: '=', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 29, kind: 'NameReference', text: 't'}, +// CHECK:STDOUT: {node_index: 32, kind: 'PostfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 31, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 30, kind: 'NameReference', text: 't'}]}]}]}]}, +// CHECK:STDOUT: {node_index: 40, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 39, kind: 'InfixOperator', text: '=', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 35, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 38, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 36, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 37, kind: 'NameReference', text: 'n'}]}]}]}, +// CHECK:STDOUT: {node_index: 47, kind: 'ExpressionStatement', text: ';', subtree_size: 7, children: [ +// CHECK:STDOUT: {node_index: 46, kind: 'InfixOperator', text: '=', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 41, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 45, kind: 'InfixOperator', text: '*', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 42, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 44, kind: 'PrefixOperator', text: '*', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 43, kind: 'NameReference', text: 'p'}]}]}]}]}, +// CHECK:STDOUT: {node_index: 53, kind: 'ExpressionStatement', text: ';', subtree_size: 6, children: [ +// CHECK:STDOUT: {node_index: 52, kind: 'InfixOperator', text: '=', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 48, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 51, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 49, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 50, kind: 'NameReference', text: 'n'}]}]}]}, +// CHECK:STDOUT: {node_index: 63, kind: 'ExpressionStatement', text: ';', subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 62, kind: 'CallExpression', text: '(', subtree_size: 9, children: [ +// CHECK:STDOUT: {node_index: 54, kind: 'NameReference', text: 'G'}, +// CHECK:STDOUT: {node_index: 56, kind: 'PostfixOperator', text: '*', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 55, kind: 'Literal', text: 'i32'}]}, +// CHECK:STDOUT: {node_index: 57, kind: 'CallExpressionComma', text: ','}, +// CHECK:STDOUT: {node_index: 60, kind: 'InfixOperator', text: '*', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 58, kind: 'NameReference', text: 'n'}, +// CHECK:STDOUT: {node_index: 59, kind: 'NameReference', text: 'n'}]}, +// CHECK:STDOUT: {node_index: 61, kind: 'CallExpressionEnd', text: ')'}]}]}]}, // CHECK:STDOUT: {node_index: 65, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/missing_precedence_not.carbon b/toolchain/parser/testdata/operators/missing_precedence_not.carbon index 37cf5c30d437..80ff26e23b77 100644 --- a/toolchain/parser/testdata/operators/missing_precedence_not.carbon +++ b/toolchain/parser/testdata/operators/missing_precedence_not.carbon @@ -5,21 +5,21 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 14, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 15, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 13, kind: 'CodeBlock', text: '{', subtree_size: 11, children: [ -// CHECK:STDOUT: {node_index: 11, kind: 'ExpressionStatement', text: ';', subtree_size: 9, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'InfixOperator', text: 'and', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 7, kind: 'InfixOperator', text: 'and', subtree_size: 5, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}]}, -// CHECK:STDOUT: {node_index: 6, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'b'}]}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'NameReference', text: 'c'}]}]}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 14, kind: 'FunctionDefinition', text: '}', subtree_size: 15, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 13, kind: 'ExpressionStatement', text: ';', subtree_size: 9, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'InfixOperator', text: 'and', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'InfixOperator', text: 'and', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'NameReference', text: 'b'}]}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'PrefixOperator', text: 'not', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 10, kind: 'NameReference', text: 'c'}]}]}]}]}, // CHECK:STDOUT: {node_index: 15, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/postfix_unary.carbon b/toolchain/parser/testdata/operators/postfix_unary.carbon index d37cc99343e4..305503b88089 100644 --- a/toolchain/parser/testdata/operators/postfix_unary.carbon +++ b/toolchain/parser/testdata/operators/postfix_unary.carbon @@ -5,16 +5,16 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 9, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlock', text: '{', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'ExpressionStatement', text: ';', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'PostfixOperator', text: '++', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'PostfixOperator', text: '++', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'n'}]}]}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'FunctionDefinition', text: '}', subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'ExpressionStatement', text: ';', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'PostfixOperator', text: '++', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'PostfixOperator', text: '++', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'n'}]}]}]}]}, // CHECK:STDOUT: {node_index: 10, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/operators/prefix_unary.carbon b/toolchain/parser/testdata/operators/prefix_unary.carbon index 935d96e01e23..e72d7f51a597 100644 --- a/toolchain/parser/testdata/operators/prefix_unary.carbon +++ b/toolchain/parser/testdata/operators/prefix_unary.carbon @@ -5,16 +5,16 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 9, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 10, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlock', text: '{', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'ExpressionStatement', text: ';', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'PrefixOperator', text: '++', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 4, kind: 'PrefixOperator', text: '++', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'n'}]}]}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 9, kind: 'FunctionDefinition', text: '}', subtree_size: 10, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 8, kind: 'ExpressionStatement', text: ';', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'PrefixOperator', text: '++', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 6, kind: 'PrefixOperator', text: '++', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'n'}]}]}]}]}, // CHECK:STDOUT: {node_index: 10, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/while/basic.carbon b/toolchain/parser/testdata/while/basic.carbon index 109751c9c1e3..de0a46f7f05d 100644 --- a/toolchain/parser/testdata/while/basic.carbon +++ b/toolchain/parser/testdata/while/basic.carbon @@ -5,34 +5,34 @@ // AUTOUPDATE // RUN: %{carbon-run-parser} // CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 27, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 28, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 26, kind: 'CodeBlock', text: '{', subtree_size: 24, children: [ -// CHECK:STDOUT: {node_index: 24, kind: 'WhileStatement', text: 'while', subtree_size: 22, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: '{', subtree_size: 18, children: [ -// CHECK:STDOUT: {node_index: 13, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'NameReference', text: 'b'}, -// CHECK:STDOUT: {node_index: 7, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 10, kind: 'BreakStatement', text: 'break', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 9, kind: 'StatementEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 21, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 16, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 14, kind: 'NameReference', text: 'c'}, -// CHECK:STDOUT: {node_index: 15, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlock', text: '{', subtree_size: 4, children: [ -// CHECK:STDOUT: {node_index: 18, kind: 'ContinueStatement', text: 'continue', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 17, kind: 'StatementEnd', text: ';'}]}, -// CHECK:STDOUT: {node_index: 19, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 22, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 25, kind: 'CodeBlockEnd', text: '}'}]}]}, +// CHECK:STDOUT: {node_index: 27, kind: 'FunctionDefinition', text: '}', subtree_size: 28, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 26, kind: 'WhileStatement', text: 'while', subtree_size: 22, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 25, kind: 'CodeBlock', text: '}', subtree_size: 18, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 16, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 11, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'NameReference', text: 'b'}, +// CHECK:STDOUT: {node_index: 10, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 15, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 12, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 14, kind: 'BreakStatement', text: 'break', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 13, kind: 'StatementEnd', text: ';'}]}]}]}, +// CHECK:STDOUT: {node_index: 24, kind: 'IfStatement', text: 'if', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 19, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 17, kind: 'NameReference', text: 'c'}, +// CHECK:STDOUT: {node_index: 18, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 23, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 20, kind: 'CodeBlockStart', text: '{'}, +// CHECK:STDOUT: {node_index: 22, kind: 'ContinueStatement', text: 'continue', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 21, kind: 'StatementEnd', text: ';'}]}]}]}]}]}]}, // CHECK:STDOUT: {node_index: 28, kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parser/testdata/while/fail_unbraced.carbon b/toolchain/parser/testdata/while/fail_unbraced.carbon new file mode 100644 index 000000000000..a5db56bd80b5 --- /dev/null +++ b/toolchain/parser/testdata/while/fail_unbraced.carbon @@ -0,0 +1,30 @@ +// 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 +// +// TODO: This should have an error. +// AUTOUPDATE +// RUN: %{not} %{carbon-run-parser} +// CHECK:STDOUT: [ +// CHECK:STDOUT: {node_index: 13, kind: 'FunctionDefinition', text: '}', subtree_size: 14, children: [ +// CHECK:STDOUT: {node_index: 4, kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5, children: [ +// CHECK:STDOUT: {node_index: 0, kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {node_index: 1, kind: 'DeclaredName', text: 'F'}, +// CHECK:STDOUT: {node_index: 3, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 2, kind: 'ParameterListEnd', text: ')'}]}]}, +// CHECK:STDOUT: {node_index: 12, kind: 'WhileStatement', text: 'while', subtree_size: 8, children: [ +// CHECK:STDOUT: {node_index: 7, kind: 'Condition', text: '(', subtree_size: 3, children: [ +// CHECK:STDOUT: {node_index: 5, kind: 'NameReference', text: 'a'}, +// CHECK:STDOUT: {node_index: 6, kind: 'ConditionEnd', text: ')'}]}, +// CHECK:STDOUT: {node_index: 11, kind: 'CodeBlock', text: 'break', has_error: yes, subtree_size: 4, children: [ +// CHECK:STDOUT: {node_index: 8, kind: 'CodeBlockStart', text: 'break', has_error: yes}, +// CHECK:STDOUT: {node_index: 10, kind: 'BreakStatement', text: 'break', subtree_size: 2, children: [ +// CHECK:STDOUT: {node_index: 9, kind: 'StatementEnd', text: ';'}]}]}]}]}, +// CHECK:STDOUT: {node_index: 14, kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] + +fn F() { + while (a) + // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/while/fail_unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. + break; +} diff --git a/toolchain/parser/testdata/while/unbraced.carbon b/toolchain/parser/testdata/while/unbraced.carbon deleted file mode 100644 index 482f9d6f8678..000000000000 --- a/toolchain/parser/testdata/while/unbraced.carbon +++ /dev/null @@ -1,28 +0,0 @@ -// 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 -// -// TODO: This should have an error. -// AUTOUPDATE -// RUN: %{carbon-run-parser} -// CHECK:STDOUT: [ -// CHECK:STDOUT: {node_index: 11, kind: 'FunctionDeclaration', text: 'fn', subtree_size: 12, children: [ -// CHECK:STDOUT: {node_index: 0, kind: 'DeclaredName', text: 'F'}, -// CHECK:STDOUT: {node_index: 2, kind: 'ParameterList', text: '(', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 1, kind: 'ParameterListEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 10, kind: 'CodeBlock', text: '{', subtree_size: 8, children: [ -// CHECK:STDOUT: {node_index: 8, kind: 'WhileStatement', text: 'while', subtree_size: 6, children: [ -// CHECK:STDOUT: {node_index: 5, kind: 'Condition', text: '(', subtree_size: 3, children: [ -// CHECK:STDOUT: {node_index: 3, kind: 'NameReference', text: 'a'}, -// CHECK:STDOUT: {node_index: 4, kind: 'ConditionEnd', text: ')'}]}, -// CHECK:STDOUT: {node_index: 7, kind: 'BreakStatement', text: 'break', subtree_size: 2, children: [ -// CHECK:STDOUT: {node_index: 6, kind: 'StatementEnd', text: ';'}]}]}, -// CHECK:STDOUT: {node_index: 9, kind: 'CodeBlockEnd', text: '}'}]}]}, -// CHECK:STDOUT: {node_index: 12, kind: 'FileEnd', text: ''}, -// CHECK:STDOUT: ] - -fn F() { - while (a) - // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/while/unbraced.carbon:[[@LINE+1]]:5: Expected braced code block. - break; -} diff --git a/toolchain/semantics/BUILD b/toolchain/semantics/BUILD index e358caac5f3b..740f1f5b4a6e 100644 --- a/toolchain/semantics/BUILD +++ b/toolchain/semantics/BUILD @@ -23,18 +23,6 @@ cc_library( ], ) -cc_library( - name = "parse_subtree_consumer", - srcs = ["parse_subtree_consumer.cpp"], - hdrs = ["parse_subtree_consumer.h"], - deps = [ - "//common:check", - "//toolchain/parser:parse_node_kind", - "//toolchain/parser:parse_tree", - "@llvm-project//llvm:Support", - ], -) - cc_library( name = "semantics_ir", srcs = ["semantics_ir.cpp"], @@ -57,7 +45,6 @@ cc_library( hdrs = ["semantics_ir_factory.h"], deps = [ ":nodes", - ":parse_subtree_consumer", ":semantics_ir", "//common:check", "//toolchain/lexer:token_kind", diff --git a/toolchain/semantics/node_kind.h b/toolchain/semantics/node_kind.h index 8899688710c7..349da6f67ab8 100644 --- a/toolchain/semantics/node_kind.h +++ b/toolchain/semantics/node_kind.h @@ -17,9 +17,6 @@ struct NodeId { void Print(llvm::raw_ostream& out) const { out << "%" << id; } - // Comparison to help tests. - auto operator==(int32_t other) const -> bool { return id == other; } - int32_t id; }; diff --git a/toolchain/semantics/node_ref.h b/toolchain/semantics/node_ref.h index 2f3fadab1581..d30d62aea431 100644 --- a/toolchain/semantics/node_ref.h +++ b/toolchain/semantics/node_ref.h @@ -16,8 +16,6 @@ namespace Carbon::Semantics { struct NodeStoreIndex { explicit NodeStoreIndex(int32_t index) : index(index) {} - explicit operator int32_t() const { return index; } - int32_t index; }; diff --git a/toolchain/semantics/nodes/function.h b/toolchain/semantics/nodes/function.h index d053554dee8c..c4bc8a874fa8 100644 --- a/toolchain/semantics/nodes/function.h +++ b/toolchain/semantics/nodes/function.h @@ -19,15 +19,8 @@ class Function { public: static constexpr NodeKind Kind = NodeKind::Function; - Function(ParseTree::Node node, NodeId id, - // llvm::SmallVector params, - // llvm::SmallVector return_type, - llvm::SmallVector body) - : node_(node), - id_(id), - // params_(std::move(params)), - // return_expr_(return_expr), - body_(std::move(body)) {} + Function(ParseTree::Node node, NodeId id, llvm::SmallVector body) + : node_(node), id_(id), body_(body) {} void Print( llvm::raw_ostream& out, int indent, @@ -43,9 +36,7 @@ class Function { auto node() const -> ParseTree::Node { return node_; } auto id() const -> NodeId { return id_; } - // auto params() const -> llvm::ArrayRef { return params_; } - // auto return_expr() const -> llvm::Optional { return - // return_expr_; } + auto set_body(llvm::SmallVector body) { body_ = std::move(body); } auto body() const -> llvm::ArrayRef { return body_; } private: @@ -55,13 +46,7 @@ class Function { // The function's ID. NodeId id_; - // Regular function parameters. - // llvm::SmallVector params_; - - // The return type expression. - llvm::SmallVector return_type_; - - llvm::SmallVector body_; + llvm::SmallVector body_; }; } // namespace Carbon::Semantics diff --git a/toolchain/semantics/parse_subtree_consumer.cpp b/toolchain/semantics/parse_subtree_consumer.cpp deleted file mode 100644 index f57cc4d4c675..000000000000 --- a/toolchain/semantics/parse_subtree_consumer.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// 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/semantics/parse_subtree_consumer.h" - -#include "common/check.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" -#include "toolchain/parser/parse_node_kind.h" -#include "toolchain/parser/parse_tree.h" - -namespace Carbon { - -auto ParseSubtreeConsumer::ForParent(const ParseTree& parse_tree, - ParseTree::Node parent_node) - -> ParseSubtreeConsumer { - auto range = llvm::reverse(parse_tree.postorder(parent_node)); - // The cursor should be one after the parent. - return ParseSubtreeConsumer(parse_tree, ++range.begin(), range.end()); -} - -auto ParseSubtreeConsumer::ForTree(const ParseTree& parse_tree) - -> ParseSubtreeConsumer { - auto range = llvm::reverse(parse_tree.postorder()); - return ParseSubtreeConsumer(parse_tree, range.begin(), range.end()); -} - -ParseSubtreeConsumer::~ParseSubtreeConsumer() { - CARBON_CHECK(is_done()) << "At index " << (*cursor_).index() << ", unhandled " - << parse_tree_->node_kind(*cursor_); -} - -auto ParseSubtreeConsumer::RequireConsume() -> ParseTree::Node { - CARBON_CHECK(!is_done()) << "Done with subtree, expected more"; - return GetNodeAndAdvance(); -} - -auto ParseSubtreeConsumer::RequireConsume(ParseNodeKind node_kind) - -> ParseTree::Node { - CARBON_CHECK(!is_done()) << "Done with subtree, expected " << node_kind; - auto node = GetNodeAndAdvance(); - CARBON_CHECK(node_kind == parse_tree_->node_kind(node)) - << "At index " << node.index() << ", expected " << node_kind << ", found " - << parse_tree_->node_kind(node); - return node; -} - -auto ParseSubtreeConsumer::TryConsume() -> llvm::Optional { - if (is_done()) { - return llvm::None; - } - return GetNodeAndAdvance(); -} - -auto ParseSubtreeConsumer::TryConsume(ParseNodeKind node_kind) - -> llvm::Optional { - if (is_done() || node_kind != parse_tree_->node_kind(*cursor_)) { - return llvm::None; - } - return GetNodeAndAdvance(); -} - -auto ParseSubtreeConsumer::GetNodeAndAdvance() -> ParseTree::Node { - auto node = *cursor_; - cursor_ += parse_tree_->node_subtree_size(node); - return node; -} - -} // namespace Carbon diff --git a/toolchain/semantics/parse_subtree_consumer.h b/toolchain/semantics/parse_subtree_consumer.h deleted file mode 100644 index 0d09256429be..000000000000 --- a/toolchain/semantics/parse_subtree_consumer.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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 - -#ifndef CARBON_TOOLCHAIN_SEMANTICS_PARSE_SUBTREE_CONSUMER_H_ -#define CARBON_TOOLCHAIN_SEMANTICS_PARSE_SUBTREE_CONSUMER_H_ - -#include - -#include "llvm/ADT/Optional.h" -#include "toolchain/parser/parse_node_kind.h" -#include "toolchain/parser/parse_tree.h" - -namespace Carbon { - -// Consumes a subtree from the parser, returning only its direct children. -// -// This traverses in reverse postorder because the parent of a subtree needs to -// be seen before its children. -class ParseSubtreeConsumer { - public: - using ParseTreeIterator = std::reverse_iterator; - - // Returns a subtree consumer for a particular node in the tree. - static auto ForParent(const ParseTree& parse_tree, - ParseTree::Node parent_node) -> ParseSubtreeConsumer; - - // Returns a subtree consumer for the root of the tree. - static auto ForTree(const ParseTree& parse_tree) -> ParseSubtreeConsumer; - - // Prevent copies because we require completion of parsing in the destructor. - ParseSubtreeConsumer(const ParseSubtreeConsumer&) = delete; - auto operator=(const ParseSubtreeConsumer&) -> ParseSubtreeConsumer& = delete; - - ~ParseSubtreeConsumer(); - - // Returns the next node. - // CHECK-fails on unexpected states. - [[nodiscard]] auto RequireConsume() -> ParseTree::Node; - - // Requires the next node be of the given kind, and returns it. - // CHECK-fails on unexpected states. - [[nodiscard]] auto RequireConsume(ParseNodeKind node_kind) -> ParseTree::Node; - - // Returns the next node if one exists. - [[nodiscard]] auto TryConsume() -> llvm::Optional; - - // Returns the next node if it's of the given kind. - [[nodiscard]] auto TryConsume(ParseNodeKind node_kind) - -> llvm::Optional; - - // Returns true if there are no more nodes to consume. - auto is_done() -> bool { return cursor_ == subtree_end_; } - - private: - // Constructs for a subtree. - ParseSubtreeConsumer(const ParseTree& parse_tree, ParseTreeIterator cursor, - ParseTreeIterator subtree_end) - : parse_tree_(&parse_tree), cursor_(cursor), subtree_end_(subtree_end) {} - - // Advances to the next sibling, returning the current node. - auto GetNodeAndAdvance() -> ParseTree::Node; - - const ParseTree* parse_tree_; - ParseTreeIterator cursor_; - ParseTreeIterator subtree_end_; -}; - -} // namespace Carbon - -#endif // CARBON_TOOLCHAIN_SEMANTICS_PARSE_SUBTREE_CONSUMER_H_ diff --git a/toolchain/semantics/semantics_ir_factory.cpp b/toolchain/semantics/semantics_ir_factory.cpp index 52ce556826b2..05efd2edab46 100644 --- a/toolchain/semantics/semantics_ir_factory.cpp +++ b/toolchain/semantics/semantics_ir_factory.cpp @@ -7,25 +7,15 @@ #include #include "common/check.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/FormatVariadic.h" #include "toolchain/lexer/token_kind.h" #include "toolchain/lexer/tokenized_buffer.h" #include "toolchain/parser/parse_node_kind.h" -//#include "toolchain/semantics/meta_node_block.h" +#include "toolchain/semantics/node_ref.h" #include "toolchain/semantics/nodes/binary_operator.h" -#include "toolchain/semantics/parse_subtree_consumer.h" +#include "toolchain/semantics/nodes/integer_literal.h" namespace Carbon { -// The ParseTree is walked in reverse post order, meaning a lot of nodes are -// added in reverse. This fixes that ordering to be the easier to understand -// code ordering. -template -static void FixReverseOrdering(T& container) { - std::reverse(container.begin(), container.end()); -} - auto SemanticsIRFactory::Build(const TokenizedBuffer& tokens, const ParseTree& parse_tree) -> SemanticsIR { SemanticsIRFactory builder(tokens, parse_tree); @@ -33,129 +23,33 @@ auto SemanticsIRFactory::Build(const TokenizedBuffer& tokens, return builder.semantics_; } -void SemanticsIRFactory::Build() { - auto subtree = ParseSubtreeConsumer::ForTree(parse_tree()); - semantics_.root_block_ = - TransformBlockSubtree(subtree, ParseNodeKind::FileEnd()); -} +// An entry in the stack for traversing the ParseTree. +// TODO: This is badly structured, and a redesign may be able to get rid of +// the need for `sem_ir`. Need to keep thinking about this, but for now +// this setup allows for test consistency. +// Alternately, maybe think about if we can group semantics for multiple nodes +// so that we aren't constantly copying/reallocating vectors of NodeRefs. +struct TraversalStackEntry { + explicit TraversalStackEntry(ParseTree::Node parse_node) + : parse_node(parse_node) {} -void SemanticsIRFactory::RequireNodeEmpty(ParseTree::Node node) { - auto subtree_size = parse_tree().node_subtree_size(node); - CARBON_CHECK(subtree_size == 1) - << "At index " << node.index() << ", expected " - << parse_tree().node_kind(node) - << "would have subtree_size of 1, but was " << subtree_size; -} + TraversalStackEntry(ParseTree::Node parse_node, + llvm::SmallVector sem_ir) + : parse_node(parse_node), sem_ir(std::move(sem_ir)) {} -auto SemanticsIRFactory::TransformBlockSubtree(ParseSubtreeConsumer& subtree, - ParseNodeKind end_kind) - -> llvm::SmallVector { - RequireNodeEmpty(subtree.RequireConsume(end_kind)); + TraversalStackEntry(ParseTree::Node parse_node, + llvm::SmallVector sem_ir, + Semantics::NodeId result_id) + : parse_node(parse_node), + sem_ir(std::move(sem_ir)), + result_id(result_id) {} - llvm::SmallVector nodes; - while (llvm::Optional child = subtree.TryConsume()) { - switch (auto child_kind = parse_tree().node_kind(*child)) { - case ParseNodeKind::FunctionDeclaration(): { - TransformFunctionDeclaration(nodes, *child); - break; - } - // case ParseNodeKind::ExpressionStatement(): - // nodes.push_back(TransformExpressionStatement(*child)); - // break; - case ParseNodeKind::ReturnStatement(): - TransformReturnStatement(nodes, *child); - break; - // case ParseNodeKind::VariableDeclaration(): - // // TODO: Handle. - // break; - default: - CARBON_FATAL() << "At index " << child->index() << ", unexpected " - << child_kind; - } - } - FixReverseOrdering(nodes); - return nodes; -} - -auto SemanticsIRFactory::TransformCodeBlock(ParseTree::Node node) - -> llvm::SmallVector { - CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::CodeBlock()); - - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - return TransformBlockSubtree(subtree, ParseNodeKind::CodeBlockEnd()); -} - -void SemanticsIRFactory::TransformDeclaredName( - llvm::SmallVector& nodes, ParseTree::Node node, - Semantics::NodeId target_id) { - CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::DeclaredName()); - RequireNodeEmpty(node); - - nodes.push_back(semantics_.nodes_.Store( - Semantics::SetName(node, parse_tree().GetNodeText(node), target_id))); -} - -void SemanticsIRFactory::TransformExpression( - llvm::SmallVector& nodes, ParseTree::Node node, - Semantics::NodeId target_id) { - switch (auto node_kind = parse_tree().node_kind(node)) { - case ParseNodeKind::Literal(): { - RequireNodeEmpty(node); - auto token = parse_tree().node_token(node); - switch (auto token_kind = tokens_->GetKind(token)) { - case TokenKind::IntegerLiteral(): { - nodes.push_back(semantics_.nodes_.Store(Semantics::IntegerLiteral( - node, target_id, tokens_->GetIntegerLiteral(token)))); - break; - } - default: - CARBON_FATAL() << "Unhandled kind: " << token_kind.Name(); - } - break; - } - case ParseNodeKind::InfixOperator(): - return TransformInfixOperator(nodes, node, target_id); - default: - CARBON_FATAL() << "At index " << node.index() << ", unexpected " - << node_kind; - } -} - -/* -auto SemanticsIRFactory::TransformExpressionStatement(ParseTree::Node node) - -> Semantics::Statement { - CARBON_CHECK(parse_tree().node_kind(node) == - ParseNodeKind::ExpressionStatement()); - - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::StatementEnd())); - return TransformExpression(subtree.RequireConsume()); -} -*/ - -void SemanticsIRFactory::TransformFunctionDeclaration( - llvm::SmallVector& nodes, ParseTree::Node node) { - CARBON_CHECK(parse_tree().node_kind(node) == - ParseNodeKind::FunctionDeclaration()); - - auto id = next_id(); - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - auto body = - TransformCodeBlock(subtree.RequireConsume(ParseNodeKind::CodeBlock())); - // llvm::Optional return_type_expr; - // if (auto return_type_node = - // subtree.TryConsume(ParseNodeKind::ReturnType())) { - // return_type_expr = TransformReturnType(*return_type_node); - // } - (void)subtree.RequireConsume(ParseNodeKind::ParameterList()); - // auto params = TransformParameterList( - // subtree.RequireConsume(ParseNodeKind::ParameterList())); - TransformDeclaredName( - nodes, subtree.RequireConsume(ParseNodeKind::DeclaredName()), id); - nodes.push_back( - semantics_.nodes_.Store(Semantics::Function(node, id, std::move(body)))); -} + ParseTree::Node parse_node; + llvm::SmallVector sem_ir; + llvm::Optional result_id; +}; +// Converts a TokenKind to a BinaryOperator operator. static auto GetBinaryOp(TokenKind kind) -> Semantics::BinaryOperator::Op { switch (kind) { case TokenKind::Plus(): @@ -165,91 +59,177 @@ static auto GetBinaryOp(TokenKind kind) -> Semantics::BinaryOperator::Op { } } -void SemanticsIRFactory::TransformInfixOperator( - llvm::SmallVector& nodes, ParseTree::Node node, - Semantics::NodeId target_id) { - CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::InfixOperator()); +void SemanticsIRFactory::Build() { + llvm::SmallVector node_stack; + auto range = parse_tree().postorder(); + for (auto it = range.begin();; ++it) { + auto parse_node = *it; + switch (auto parse_kind = parse_tree().node_kind(parse_node)) { + case ParseNodeKind::DeclaredName(): { + // DeclaredNames will be acted upon as part of the declaring construct. + node_stack.push_back(TraversalStackEntry(parse_node)); + break; + } + case ParseNodeKind::FunctionDefinition(): { + // Merges code block children up under the FunctionDefinitionStart. + llvm::SmallVector body; + while (parse_tree().node_kind(node_stack.back().parse_node) != + ParseNodeKind::FunctionDefinitionStart()) { + body.insert(body.begin(), node_stack.back().sem_ir.begin(), + node_stack.back().sem_ir.end()); + node_stack.pop_back(); + } - auto token = parse_tree().node_token(node); - auto token_kind = tokens_->GetKind(token); - auto op = GetBinaryOp(token_kind); + // Next is the FunctionDefinitionStart. + llvm::SmallVector sig = + std::move(node_stack.back().sem_ir); + node_stack.pop_back(); - auto rhs_id = next_id(); - auto lhs_id = next_id(); - nodes.push_back(semantics_.nodes_.Store( - Semantics::BinaryOperator(node, target_id, op, lhs_id, rhs_id))); - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - TransformExpression(nodes, subtree.RequireConsume(), rhs_id); - TransformExpression(nodes, subtree.RequireConsume(), lhs_id); -} + // TODO: This replacement is in particular why I want to change + // the IR setup now, but for now I want to just produce output that + // satisfies tests without changes. + auto orig_function = semantics_.nodes_.Get(sig[0]); + auto orig_set_name = semantics_.nodes_.Get(sig[1]); + llvm::SmallVector function_sem_ir; + auto function_id = next_id(); + function_sem_ir.push_back(semantics_.nodes_.Store( + Semantics::Function(orig_function.node(), function_id, body))); + function_sem_ir.push_back(semantics_.nodes_.Store(Semantics::SetName( + orig_set_name.node(), orig_set_name.name(), function_id))); -/* -auto SemanticsIRFactory::TransformParameterList(ParseTree::Node node) - -> llvm::SmallVector { - CARBON_CHECK(parse_tree().node_kind(node) == -ParseNodeKind::ParameterList()); + node_stack.push_back( + TraversalStackEntry(parse_node, std::move(function_sem_ir))); + break; + } + case ParseNodeKind::FunctionDefinitionStart(): { + // TODO: Skip over the parameter list for now. + node_stack.pop_back(); - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::ParameterListEnd())); + // TODO: At this point, it should be possible to forward-declare the + // function so that it can be called from its code block. For now, we + // just assemble the semantic function to associate the body. + llvm::SmallVector sem_ir; - llvm::SmallVector params; - if (auto first_param_node = - subtree.TryConsume(ParseNodeKind::PatternBinding())) { - params.push_back(TransformPatternBinding(*first_param_node)); + auto function_id = next_id(); + sem_ir.push_back(semantics_.nodes_.Store( + Semantics::Function(parse_node, function_id, {}))); - while (auto comma_node = - subtree.TryConsume(ParseNodeKind::ParameterListComma())) { - RequireNodeEmpty(*comma_node); - params.push_back(TransformPatternBinding( - subtree.RequireConsume(ParseNodeKind::PatternBinding()))); + auto name_node = node_stack.back().parse_node; + sem_ir.push_back(semantics_.nodes_.Store(Semantics::SetName( + name_node, parse_tree().GetNodeText(name_node), function_id))); + node_stack.pop_back(); + + // Do nothing with the `fn`. + node_stack.pop_back(); + + node_stack.push_back( + TraversalStackEntry(parse_node, std::move(sem_ir))); + break; + } + case ParseNodeKind::FileEnd(): { + ++it; + CARBON_CHECK(it == range.end()) + << "FileEnd should always be last, found " + << parse_tree().node_kind(*it); + + for (const auto& entry : node_stack) { + semantics_.root_block_.append(entry.sem_ir.begin(), + entry.sem_ir.end()); + } + return; + } + case ParseNodeKind::InfixOperator(): { + llvm::SmallVector sem_ir; + + sem_ir.insert(sem_ir.begin(), node_stack.back().sem_ir.begin(), + node_stack.back().sem_ir.end()); + auto rhs_id = *node_stack.back().result_id; + node_stack.pop_back(); + + sem_ir.insert(sem_ir.begin(), node_stack.back().sem_ir.begin(), + node_stack.back().sem_ir.end()); + auto lhs_id = *node_stack.back().result_id; + node_stack.pop_back(); + + // Figure out the operator for the token. + auto token = parse_tree().node_token(parse_node); + auto token_kind = tokens_->GetKind(token); + auto op = GetBinaryOp(token_kind); + + auto literal_id = next_id(); + sem_ir.push_back(semantics_.nodes_.Store(Semantics::BinaryOperator( + parse_node, literal_id, op, lhs_id, rhs_id))); + node_stack.push_back( + TraversalStackEntry(parse_node, std::move(sem_ir), literal_id)); + break; + } + case ParseNodeKind::Literal(): { + auto literal_id = next_id(); + + llvm::SmallVector sem_ir; + auto token = parse_tree().node_token(parse_node); + switch (auto token_kind = tokens_->GetKind(token)) { + case TokenKind::IntegerLiteral(): { + sem_ir.push_back(semantics_.nodes_.Store(Semantics::IntegerLiteral( + parse_node, literal_id, tokens_->GetIntegerLiteral(token)))); + break; + } + default: + CARBON_FATAL() << "Unhandled kind: " << token_kind.Name(); + } + node_stack.push_back( + TraversalStackEntry(parse_node, std::move(sem_ir), literal_id)); + break; + } + case ParseNodeKind::ReturnStatement(): { + CARBON_CHECK(parse_tree().node_kind(node_stack.back().parse_node) == + ParseNodeKind::StatementEnd()); + node_stack.pop_back(); + + // TODO: Restructure ReturnStatement so that we can do this without + // looking at the subtree size. + if (parse_tree().node_subtree_size(parse_node) == 2) { + node_stack.push_back(TraversalStackEntry( + parse_node, {semantics_.nodes_.Store( + Semantics::Return(parse_node, llvm::None))})); + } else { + // Return should only ever have one expression child. + llvm::SmallVector sem_ir = + std::move(node_stack.back().sem_ir); + Semantics::NodeId result_id = *node_stack.back().result_id; + node_stack.pop_back(); + sem_ir.push_back(semantics_.nodes_.Store( + Semantics::Return(parse_node, result_id))); + node_stack.push_back( + TraversalStackEntry(parse_node, std::move(sem_ir))); + } + break; + } + case ParseNodeKind::ParameterList(): { + // TODO: This should transform into a usable parameter list. For now + // it's unused and only stored so that node counts match. + // TODO: Reorder with ParameterListStart so that we can traverse without + // subtree_size. + CARBON_CHECK(parse_tree().node_kind(node_stack.back().parse_node) == + ParseNodeKind::ParameterListEnd()); + node_stack.pop_back(); + node_stack.push_back(TraversalStackEntry(parse_node)); + break; + } + case ParseNodeKind::FunctionIntroducer(): + case ParseNodeKind::ParameterListEnd(): + case ParseNodeKind::StatementEnd(): { + // The token has no action, but we still track it for the stack. + node_stack.push_back(TraversalStackEntry(parse_node)); + break; + } + default: { + CARBON_FATAL() << "In ParseTree at index " << parse_node.index() + << ", unhandled NodeKind " << parse_kind; + } } } - FixReverseOrdering(params); - return params; + llvm_unreachable("Should always end at FileEnd"); } -auto SemanticsIRFactory::TransformPatternBinding(ParseTree::Node node) - -> Semantics::PatternBinding { - CARBON_CHECK(parse_tree().node_kind(node) == -ParseNodeKind::PatternBinding()); - - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - auto type = TransformExpression(subtree.RequireConsume()); - auto name = TransformDeclaredName( - subtree.RequireConsume(ParseNodeKind::DeclaredName())); - return Semantics::PatternBinding(node, name, type); -} -*/ - -void SemanticsIRFactory::TransformReturnStatement( - llvm::SmallVector& nodes, ParseTree::Node node) { - CARBON_CHECK(parse_tree().node_kind(node) == - ParseNodeKind::ReturnStatement()); - - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - RequireNodeEmpty(subtree.RequireConsume(ParseNodeKind::StatementEnd())); - - auto expr = subtree.TryConsume(); - if (expr) { - // return expr; - auto id = next_id(); - nodes.push_back(semantics_.nodes_.Store(Semantics::Return(node, id))); - TransformExpression(nodes, *expr, id); - } else { - // return; - nodes.push_back( - semantics_.nodes_.Store(Semantics::Return(node, llvm::None))); - } -} - -/* -auto SemanticsIRFactory::TransformReturnType(ParseTree::Node node) - -> Semantics::Statement { - CARBON_CHECK(parse_tree().node_kind(node) == ParseNodeKind::ReturnType()); - - auto subtree = ParseSubtreeConsumer::ForParent(parse_tree(), node); - return TransformExpression(subtree.RequireConsume()); -} -*/ - } // namespace Carbon diff --git a/toolchain/semantics/semantics_ir_factory.h b/toolchain/semantics/semantics_ir_factory.h index a582c9c6f43a..290648781625 100644 --- a/toolchain/semantics/semantics_ir_factory.h +++ b/toolchain/semantics/semantics_ir_factory.h @@ -6,7 +6,6 @@ #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_IR_FACTORY_H_ #include "toolchain/parser/parse_tree.h" -#include "toolchain/semantics/parse_subtree_consumer.h" #include "toolchain/semantics/semantics_ir.h" namespace Carbon { @@ -25,39 +24,6 @@ class SemanticsIRFactory { void Build(); - // Requires that a node have no children, to emphasize why the subtree isn't - // otherwise checked. - void RequireNodeEmpty(ParseTree::Node node); - - // Transforms a block subtree, such as a file or CodeBlock, into its semantic - // nodes. - auto TransformBlockSubtree(ParseSubtreeConsumer& subtree, - ParseNodeKind end_kind) - -> llvm::SmallVector; - - // Each of these takes a parse tree node and does a transformation based on - // its type. These functions are per ParseNodeKind. - auto TransformCodeBlock(ParseTree::Node node) - -> llvm::SmallVector; - void TransformDeclaredName(llvm::SmallVector& nodes, - ParseTree::Node node, Semantics::NodeId target_id); - void TransformExpression(llvm::SmallVector& nodes, - ParseTree::Node node, Semantics::NodeId target_id); - // auto TransformExpressionStatement(ParseTree::Node node) - // -> Semantics::Statement; - void TransformFunctionDeclaration( - llvm::SmallVector& nodes, ParseTree::Node node); - void TransformInfixOperator(llvm::SmallVector& nodes, - ParseTree::Node node, - Semantics::NodeId target_id); - // auto TransformParameterList(ParseTree::Node node) - // -> llvm::SmallVector - // auto TransformPatternBinding(ParseTree::Node node) - // -> Semantics::PatternBinding; - // auto TransformReturnType(ParseTree::Node node) -> Semantics::Statement; - void TransformReturnStatement(llvm::SmallVector& nodes, - ParseTree::Node node); - // Returns a unique ID for the SemanticsIR. auto next_id() -> Semantics::NodeId { return Semantics::NodeId(id_counter_++); diff --git a/toolchain/semantics/testdata/function/basic.carbon b/toolchain/semantics/testdata/function/basic.carbon index 2ece5b6cdbae..1686c09da171 100644 --- a/toolchain/semantics/testdata/function/basic.carbon +++ b/toolchain/semantics/testdata/function/basic.carbon @@ -6,10 +6,10 @@ // RUN: %{carbon-run-semantics} // CHECK:STDOUT: { // CHECK:STDOUT: Function( -// CHECK:STDOUT: %0, +// CHECK:STDOUT: %1, // CHECK:STDOUT: { // CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Foo`, %0), +// CHECK:STDOUT: SetName(`Foo`, %1), // CHECK:STDOUT: } fn Foo() {} diff --git a/toolchain/semantics/testdata/function/order.carbon b/toolchain/semantics/testdata/function/order.carbon index feb4ec1b910e..4f7b10b07297 100644 --- a/toolchain/semantics/testdata/function/order.carbon +++ b/toolchain/semantics/testdata/function/order.carbon @@ -6,20 +6,20 @@ // RUN: %{carbon-run-semantics} // CHECK:STDOUT: { // CHECK:STDOUT: Function( -// CHECK:STDOUT: %2, -// CHECK:STDOUT: { -// CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Foo`, %2), -// CHECK:STDOUT: Function( // CHECK:STDOUT: %1, // CHECK:STDOUT: { // CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Bar`, %1), +// CHECK:STDOUT: SetName(`Foo`, %1), // CHECK:STDOUT: Function( -// CHECK:STDOUT: %0, +// CHECK:STDOUT: %3, // CHECK:STDOUT: { // CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Baz`, %0), +// CHECK:STDOUT: SetName(`Bar`, %3), +// CHECK:STDOUT: Function( +// CHECK:STDOUT: %5, +// CHECK:STDOUT: { +// CHECK:STDOUT: }), +// CHECK:STDOUT: SetName(`Baz`, %5), // CHECK:STDOUT: } fn Foo() {} diff --git a/toolchain/semantics/testdata/return/binary_op.carbon b/toolchain/semantics/testdata/return/binary_op.carbon index 9f89e675cfc5..683224c984b7 100644 --- a/toolchain/semantics/testdata/return/binary_op.carbon +++ b/toolchain/semantics/testdata/return/binary_op.carbon @@ -6,14 +6,14 @@ // RUN: %{carbon-run-semantics} // CHECK:STDOUT: { // CHECK:STDOUT: Function( -// CHECK:STDOUT: %0, +// CHECK:STDOUT: %4, // CHECK:STDOUT: { -// CHECK:STDOUT: IntegerLiteral(%3, 12), +// CHECK:STDOUT: IntegerLiteral(%1, 12), // CHECK:STDOUT: IntegerLiteral(%2, 34), -// CHECK:STDOUT: BinaryOperator(%1, +, %3, %2), -// CHECK:STDOUT: Return(%1), +// CHECK:STDOUT: BinaryOperator(%3, +, %1, %2), +// CHECK:STDOUT: Return(%3), // CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Main`, %0), +// CHECK:STDOUT: SetName(`Main`, %4), // CHECK:STDOUT: } fn Main() { diff --git a/toolchain/semantics/testdata/return/literal.carbon b/toolchain/semantics/testdata/return/literal.carbon index 8a09ed299c31..01c97db47dc1 100644 --- a/toolchain/semantics/testdata/return/literal.carbon +++ b/toolchain/semantics/testdata/return/literal.carbon @@ -6,12 +6,12 @@ // RUN: %{carbon-run-semantics} // CHECK:STDOUT: { // CHECK:STDOUT: Function( -// CHECK:STDOUT: %0, +// CHECK:STDOUT: %2, // CHECK:STDOUT: { // CHECK:STDOUT: IntegerLiteral(%1, 0), // CHECK:STDOUT: Return(%1), // CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Main`, %0), +// CHECK:STDOUT: SetName(`Main`, %2), // CHECK:STDOUT: } fn Main() { diff --git a/toolchain/semantics/testdata/return/trivial.carbon b/toolchain/semantics/testdata/return/trivial.carbon index 08ac417593c5..b8dd71d3cc72 100644 --- a/toolchain/semantics/testdata/return/trivial.carbon +++ b/toolchain/semantics/testdata/return/trivial.carbon @@ -6,11 +6,11 @@ // RUN: %{carbon-run-semantics} // CHECK:STDOUT: { // CHECK:STDOUT: Function( -// CHECK:STDOUT: %0, +// CHECK:STDOUT: %1, // CHECK:STDOUT: { // CHECK:STDOUT: Return(None), // CHECK:STDOUT: }), -// CHECK:STDOUT: SetName(`Main`, %0), +// CHECK:STDOUT: SetName(`Main`, %1), // CHECK:STDOUT: } fn Main() {