From 7b48ac7258af0989b9354e03d3df8883f640f5b5 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Tue, 18 Oct 2022 16:15:57 -0700 Subject: [PATCH] Start reorienting the ParseTree towards a more efficient SemanticsIR production. (#2275) In summary - some of the changes here are focused on producing the same test results for SemanticsIR, but I think the next step will be to change the SemanticsIR structure to reduce how much is added to the traversal stack. Switching semantics to a postorder traversal is intended to be more efficient. The traversal stack is to eliminate risk of recursion limits within the semantic analysis that could come from layered code structures. However, we need to start considering the implications for type-checking and what the ParseTree looks like, as well as copying of data here. As we start thinking about type-checking in SemanticsIR, it's helpful for a function to know its own signature in order to perform lookup recursive calls. The challenge in the post-order walk without this change is it doesn't know it's in a function definition (or similar) until it reaches the FunctionDeclaration; this restructures so that either: 1. For a declaration, the signature is a child of FunctionDeclaration(";") 2. For a definition, the signature is a child of FunctionDefinitionStart("{") which pairs with FunctionDefinition("}"), replacing CodeBlock. This similarly reorients CodeBlock to be CodeBlockStart("{") as the first child of CodeBlock("}"). I'm not doing that with ParameterList here just because it affects a bit more, and felt like it could be delayed. Overall, my goal is making the postorder traversal more intuitive along scope boundaries. I think we may also not need subtree_size, so I'm avoiding use of that now. Currently the SemanticsIRFactory implementation is less clean than I might like (there are a couple comments to this point), but I was starting to feel like a more complete rewrite would be appropriate rather than trying to clean it up further: in particular, I think the node structures are off, but changing them is significant and also changes test output; in turn it may also warrant more substantial ParseTree changes. If you prefer from a reviewer POV, I can do a more complete rewrite. --- toolchain/README.md | 38 +- toolchain/lexer/tokenized_buffer.h | 2 +- toolchain/parser/parse_node_kind.def | 7 +- toolchain/parser/parse_tree_fuzzer.cpp | 11 +- toolchain/parser/parse_tree_test.cpp | 56 +-- toolchain/parser/parser_impl.cpp | 197 +++++---- toolchain/parser/parser_impl.h | 20 +- .../basics/fail_invalid_designators.carbon | 32 +- .../testdata/basics/function_call.carbon | 50 +-- .../parser/testdata/basics/return.carbon | 56 +-- toolchain/parser/testdata/basics/var.carbon | 26 +- .../for/fail_colon_instead_of_in.carbon | 42 +- .../testdata/for/fail_missing_in.carbon | 40 +- .../testdata/for/fail_missing_var.carbon | 36 +- toolchain/parser/testdata/for/nested.carbon | 66 +-- toolchain/parser/testdata/for/simple.carbon | 44 +- .../function/declaration/basic.carbon | 10 +- .../fail_identifier_instead_of_sig.carbon | 6 +- .../declaration/fail_missing_name.carbon | 4 +- .../declaration/fail_no_sig_or_semi.carbon | 7 +- .../declaration/fail_only_fn_and_semi.carbon | 4 +- .../fail_repeated_fn_and_semi.carbon | 4 +- ...skip_indented_newline_until_outdent.carbon | 15 +- ...ail_skip_indented_newline_with_semi.carbon | 14 +- ..._skip_indented_newline_without_semi.carbon | 15 +- .../fail_skip_to_newline_without_semi.carbon | 15 +- .../fail_skip_without_semi_to_curly.carbon | 10 +- .../fail_with_identifier_as_param.carbon | 10 +- ...hout_name_and_many_tokens_in_params.carbon | 4 +- .../function/declaration/with_params.carbon | 24 +- .../declaration/with_return_type.carbon | 14 +- .../testdata/function/definition/basic.carbon | 12 +- .../fail_identifier_in_statements.carbon | 14 +- .../function/definition/with_params.carbon | 44 +- .../definition/with_return_type.carbon | 22 +- toolchain/parser/testdata/if/basic.carbon | 52 +-- toolchain/parser/testdata/if/else.carbon | 122 +++--- .../parser/testdata/if/else_unbraced.carbon | 79 ---- .../testdata/if/fail_else_unbraced.carbon | 87 ++++ .../parser/testdata/if/fail_errors.carbon | 54 +-- .../parser/testdata/if/fail_unbraced.carbon | 46 ++ toolchain/parser/testdata/if/unbraced.carbon | 40 -- .../testdata/operators/associative.carbon | 24 +- .../fail_missing_precedence_and_or.carbon | 24 +- .../fail_missing_precedence_or_and.carbon | 24 +- .../testdata/operators/fail_variety.carbon | 54 +-- .../parser/testdata/operators/fixity.carbon | 130 +++--- .../operators/missing_precedence_not.carbon | 30 +- .../testdata/operators/postfix_unary.carbon | 20 +- .../testdata/operators/prefix_unary.carbon | 20 +- toolchain/parser/testdata/while/basic.carbon | 56 +-- .../testdata/while/fail_unbraced.carbon | 30 ++ .../parser/testdata/while/unbraced.carbon | 28 -- toolchain/semantics/BUILD | 13 - toolchain/semantics/node_kind.h | 3 - toolchain/semantics/node_ref.h | 2 - toolchain/semantics/nodes/function.h | 23 +- .../semantics/parse_subtree_consumer.cpp | 70 ---- toolchain/semantics/parse_subtree_consumer.h | 71 ---- toolchain/semantics/semantics_ir_factory.cpp | 396 +++++++++--------- toolchain/semantics/semantics_ir_factory.h | 34 -- .../semantics/testdata/function/basic.carbon | 4 +- .../semantics/testdata/function/order.carbon | 16 +- .../testdata/return/binary_op.carbon | 10 +- .../semantics/testdata/return/literal.carbon | 4 +- .../semantics/testdata/return/trivial.carbon | 4 +- 66 files changed, 1177 insertions(+), 1364 deletions(-) delete mode 100644 toolchain/parser/testdata/if/else_unbraced.carbon create mode 100644 toolchain/parser/testdata/if/fail_else_unbraced.carbon create mode 100644 toolchain/parser/testdata/if/fail_unbraced.carbon delete mode 100644 toolchain/parser/testdata/if/unbraced.carbon create mode 100644 toolchain/parser/testdata/while/fail_unbraced.carbon delete mode 100644 toolchain/parser/testdata/while/unbraced.carbon delete mode 100644 toolchain/semantics/parse_subtree_consumer.cpp delete mode 100644 toolchain/semantics/parse_subtree_consumer.h 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() {