Răsfoiți Sursa

Switch the driver to print ParseTree postorder by default (#2371)

The ParseTree comments say that preorder is "easier to visualize and read". The problem is, both the ParseTree and Semantics need to operate on the postorder traversal: the ParseTree during construction, and the Semantics during processing. As a consequence, understanding the postorder traversal is important, but it's also very hard to decipher when presented preorder. This PR provides a way to see the postorder, with helpful indents to show subtrees.

This retains the preorder printing as an option for people who prefer that. I'm pretty sure it'll be easier to debug tests if we can see the postorder, so I'm making that the default.

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Jon Ross-Perkins 3 ani în urmă
părinte
comite
e21449edff
56 a modificat fișierele cu 1026 adăugiri și 976 ștergeri
  1. 8 1
      toolchain/driver/driver.cpp
  2. 4 41
      toolchain/driver/driver_test.cpp
  3. 70 31
      toolchain/parser/parse_tree.cpp
  4. 39 22
      toolchain/parser/parse_tree.h
  5. 25 1
      toolchain/parser/parse_tree_test.cpp
  6. 1 1
      toolchain/parser/testdata/basics/empty.carbon
  7. 2 2
      toolchain/parser/testdata/basics/empty_declaration.carbon
  8. 17 17
      toolchain/parser/testdata/basics/fail_invalid_designators.carbon
  9. 2 2
      toolchain/parser/testdata/basics/fail_no_intro_with_semi.carbon
  10. 1 1
      toolchain/parser/testdata/basics/fail_no_intro_without_semi.carbon
  11. 6 6
      toolchain/parser/testdata/basics/fail_paren_match_regression.carbon
  12. 26 26
      toolchain/parser/testdata/basics/function_call.carbon
  13. 21 21
      toolchain/parser/testdata/basics/package.carbon
  14. 29 29
      toolchain/parser/testdata/basics/return.carbon
  15. 56 56
      toolchain/parser/testdata/basics/structs.carbon
  16. 30 30
      toolchain/parser/testdata/basics/tuples.carbon
  17. 26 26
      toolchain/parser/testdata/basics/var.carbon
  18. 22 22
      toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon
  19. 21 21
      toolchain/parser/testdata/for/fail_missing_in.carbon
  20. 19 19
      toolchain/parser/testdata/for/fail_missing_var.carbon
  21. 34 34
      toolchain/parser/testdata/for/nested.carbon
  22. 23 23
      toolchain/parser/testdata/for/simple.carbon
  23. 6 6
      toolchain/parser/testdata/function/declaration/basic.carbon
  24. 4 4
      toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon
  25. 3 3
      toolchain/parser/testdata/function/declaration/fail_missing_name.carbon
  26. 4 4
      toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon
  27. 3 3
      toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon
  28. 3 3
      toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon
  29. 8 8
      toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon
  30. 8 8
      toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon
  31. 8 8
      toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon
  32. 8 8
      toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon
  33. 6 6
      toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon
  34. 6 6
      toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon
  35. 3 3
      toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon
  36. 13 13
      toolchain/parser/testdata/function/declaration/with_params.carbon
  37. 8 8
      toolchain/parser/testdata/function/declaration/with_return_type.carbon
  38. 7 7
      toolchain/parser/testdata/function/definition/basic.carbon
  39. 8 8
      toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon
  40. 23 23
      toolchain/parser/testdata/function/definition/with_params.carbon
  41. 12 12
      toolchain/parser/testdata/function/definition/with_return_type.carbon
  42. 27 27
      toolchain/parser/testdata/if/basic.carbon
  43. 53 53
      toolchain/parser/testdata/if/else.carbon
  44. 53 53
      toolchain/parser/testdata/if/fail_else_unbraced.carbon
  45. 28 28
      toolchain/parser/testdata/if/fail_errors.carbon
  46. 27 27
      toolchain/parser/testdata/if/fail_unbraced.carbon
  47. 13 13
      toolchain/parser/testdata/operators/associative.carbon
  48. 13 13
      toolchain/parser/testdata/operators/fail_missing_precedence_and_or.carbon
  49. 13 13
      toolchain/parser/testdata/operators/fail_missing_precedence_or_and.carbon
  50. 28 28
      toolchain/parser/testdata/operators/fail_variety.carbon
  51. 66 66
      toolchain/parser/testdata/operators/fixity.carbon
  52. 16 16
      toolchain/parser/testdata/operators/missing_precedence_not.carbon
  53. 11 11
      toolchain/parser/testdata/operators/postfix_unary.carbon
  54. 11 11
      toolchain/parser/testdata/operators/prefix_unary.carbon
  55. 29 29
      toolchain/parser/testdata/while/basic.carbon
  56. 15 15
      toolchain/parser/testdata/while/fail_unbraced.carbon

+ 8 - 1
toolchain/driver/driver.cpp

@@ -125,6 +125,13 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   }
   args = args.drop_front();
 
+  auto parse_tree_preorder = false;
+  if (dump_mode == DumpMode::ParseTree && !args.empty() &&
+      args.front() == "--preorder") {
+    args = args.drop_front();
+    parse_tree_preorder = true;
+  }
+
   if (args.empty()) {
     error_stream_ << "ERROR: No input file specified.\n";
     return false;
@@ -158,7 +165,7 @@ auto Driver::RunDumpSubcommand(DiagnosticConsumer& consumer,
   auto parse_tree = ParseTree::Parse(tokenized_source, consumer);
   if (dump_mode == DumpMode::ParseTree) {
     consumer.Flush();
-    parse_tree.Print(output_stream_);
+    parse_tree.Print(output_stream_, parse_tree_preorder);
     return !tokenized_source.has_errors() && !parse_tree.has_errors();
   }
 

+ 4 - 41
toolchain/driver/driver_test.cpp

@@ -197,51 +197,14 @@ TEST(DriverTest, DumpParseTree) {
   EXPECT_TRUE(driver.RunDumpSubcommand(ConsoleDiagnosticConsumer(),
                                        {"parse-tree", test_file_path}));
   EXPECT_THAT(test_error_stream.TakeStr(), StrEq(""));
-  auto tokenized_text = test_output_stream.TakeStr();
-
-  EXPECT_THAT(
-      Yaml::Value::FromText(tokenized_text),
-      ElementsAre(Yaml::SequenceValue{
-          Yaml::MappingValue{
-              {"node_index", "6"},
-              {"kind", "VariableDeclaration"},
-              {"text", "var"},
-              {"subtree_size", "7"},
-              {"children",
-               Yaml::SequenceValue{
-                   Yaml::MappingValue{
-                       {"node_index", "2"},
-                       {"kind", "PatternBinding"},
-                       {"text", ":"},
-                       {"subtree_size", "3"},
-                       {"children",
-                        Yaml::SequenceValue{
-                            Yaml::MappingValue{{"node_index", "0"},
-                                               {"kind", "DeclaredName"},
-                                               {"text", "v"}},
-                            Yaml::MappingValue{{"node_index", "1"},
-                                               {"kind", "NameReference"},
-                                               {"text", "Int"}}}}},
-                   Yaml::MappingValue{{"node_index", "4"},
-                                      {"kind", "VariableInitializer"},
-                                      {"text", "="},
-                                      {"subtree_size", "2"},
-                                      {"children",  //
-                                       Yaml::SequenceValue{Yaml::MappingValue{
-                                           {"node_index", "3"},
-                                           {"kind", "Literal"},
-                                           {"text", "42"}}}}},
-                   Yaml::MappingValue{{"node_index", "5"},
-                                      {"kind", "DeclarationEnd"},
-                                      {"text", ";"}}}}},
-          Yaml::MappingValue{{"node_index", "7"},  //
-                             {"kind", "FileEnd"},
-                             {"text", ""}}}));
+  // Verify there is output without examining it.
+  EXPECT_FALSE(test_output_stream.TakeStr().empty());
 
   // Check that the subcommand dispatch works.
   EXPECT_TRUE(driver.RunFullCommand({"dump", "parse-tree", test_file_path}));
   EXPECT_THAT(test_error_stream.TakeStr(), StrEq(""));
-  EXPECT_THAT(test_output_stream.TakeStr(), StrEq(tokenized_text));
+  // Verify there is output without examining it.
+  EXPECT_FALSE(test_output_stream.TakeStr().empty());
 }
 
 }  // namespace

+ 70 - 31
toolchain/parser/parse_tree.cpp

@@ -88,16 +88,39 @@ auto ParseTree::GetNodeText(Node n) const -> llvm::StringRef {
   return tokens_->GetTokenText(node_impls_[n.index_].token);
 }
 
+auto ParseTree::PrintNode(llvm::raw_ostream& output, Node n, int depth,
+                          bool preorder) const -> bool {
+  const auto& n_impl = node_impls_[n.index()];
+  output.indent(2 * depth);
+  output << "{";
+  // If children are being added, include node_index in order to disambiguate
+  // nodes.
+  if (preorder) {
+    output << "node_index: " << n.index_ << ", ";
+  }
+  output << "kind: '" << n_impl.kind.name() << "', text: '"
+         << tokens_->GetTokenText(n_impl.token) << "'";
+
+  if (n_impl.has_error) {
+    output << ", has_error: yes";
+  }
+
+  if (n_impl.subtree_size > 1) {
+    output << ", subtree_size: " << n_impl.subtree_size;
+    if (preorder) {
+      output << ", children: [\n";
+      return true;
+    }
+  }
+  output << "}";
+  return false;
+}
+
 auto ParseTree::Print(llvm::raw_ostream& output) const -> void {
-  output << "[\n";
-  // The parse tree is stored in postorder, but the most natural order to
-  // visualize is preorder. This is a tree, so the preorder can be constructed
-  // by reversing the order of each level of siblings within an RPO. The sibling
-  // iterators are directly built around RPO and so can be used with a stack to
-  // produce preorder.
+  // Walk the tree just to calculate depths for each node.
+  llvm::SmallVector<int> indents;
+  indents.append(size(), 0);
 
-  // The roots, like siblings, are in RPO (so reversed), but we add them in
-  // order here because we'll pop off the stack effectively reversing then.
   llvm::SmallVector<std::pair<Node, int>, 16> node_stack;
   for (Node n : roots()) {
     node_stack.push_back({n, 0});
@@ -107,37 +130,53 @@ auto ParseTree::Print(llvm::raw_ostream& output) const -> void {
     Node n;
     int depth;
     std::tie(n, depth) = node_stack.pop_back_val();
-    const auto& n_impl = node_impls_[n.index()];
-
-    for (int unused_indent : llvm::seq(0, depth)) {
-      (void)unused_indent;
-      output << "  ";
+    for (Node sibling_n : children(n)) {
+      indents[sibling_n.index()] = depth + 1;
+      node_stack.push_back({sibling_n, depth + 1});
     }
+  }
+
+  output << "[\n";
+  for (Node n : postorder()) {
+    PrintNode(output, n, indents[n.index()], /*adding_children=*/false);
+    output << ",\n";
+  }
+  output << "]\n";
+}
 
-    output << "{node_index: " << n.index_ << ", kind: '" << n_impl.kind.name()
-           << "', text: '" << tokens_->GetTokenText(n_impl.token) << "'";
+auto ParseTree::Print(llvm::raw_ostream& output, bool preorder) const -> void {
+  if (!preorder) {
+    Print(output);
+    return;
+  }
 
-    if (n_impl.has_error) {
-      output << ", has_error: yes";
-    }
+  output << "[\n";
+  // The parse tree is stored in postorder. The preorder can be constructed
+  // by reversing the order of each level of siblings within an RPO. The
+  // sibling iterators are directly built around RPO and so can be used with a
+  // stack to produce preorder.
 
-    if (n_impl.subtree_size > 1) {
-      output << ", subtree_size: " << n_impl.subtree_size;
-      // Has children, so we descend.
-      output << ", children: [\n";
-      // We append the children in order here as well because they will get
-      // reversed when popped off the stack.
+  // The roots, like siblings, are in RPO (so reversed), but we add them in
+  // order here because we'll pop off the stack effectively reversing then.
+  llvm::SmallVector<std::pair<Node, int>, 16> node_stack;
+  for (Node n : roots()) {
+    node_stack.push_back({n, 0});
+  }
+
+  while (!node_stack.empty()) {
+    Node n;
+    int depth;
+    std::tie(n, depth) = node_stack.pop_back_val();
+
+    if (PrintNode(output, n, depth, /*adding_children=*/true)) {
+      // Has children, so we descend. We append the children in order here as
+      // well because they will get reversed when popped off the stack.
       for (Node sibling_n : children(n)) {
         node_stack.push_back({sibling_n, depth + 1});
       }
       continue;
     }
 
-    // This node is finished, so close it up.
-    CARBON_CHECK(n_impl.subtree_size == 1)
-        << "Subtree size must always be a positive integer!";
-    output << "}";
-
     int next_depth = node_stack.empty() ? 0 : node_stack.back().second;
     CARBON_CHECK(next_depth <= depth) << "Cannot have the next depth increase!";
     for (int close_children_count : llvm::seq(0, depth - next_depth)) {
@@ -145,8 +184,8 @@ auto ParseTree::Print(llvm::raw_ostream& output) const -> void {
       output << "]}";
     }
 
-    // We always end with a comma and a new line as we'll move to the next node
-    // at whatever the current level ends up being.
+    // We always end with a comma and a new line as we'll move to the next
+    // node at whatever the current level ends up being.
     output << ",\n";
   }
   output << "]\n";

+ 39 - 22
toolchain/parser/parse_tree.h

@@ -102,36 +102,48 @@ class ParseTree {
   // the underlying source text.
   [[nodiscard]] auto GetNodeText(Node n) const -> llvm::StringRef;
 
+  // See the other Print comments.
+  auto Print(llvm::raw_ostream& output) const -> void;
+
   // Prints a description of the parse tree to the provided `raw_ostream`.
   //
-  // While the parse tree is represented as a postorder sequence, we print it in
-  // preorder to make it easier to visualize and read. The node indices are the
-  // postorder indices. The print out represents each node as a YAML record,
-  // with children nested within it.
+  // The tree may be printed in either preorder or postorder. Output represents
+  // each node as a YAML record; in preorder, children are nested.
+  //
+  // In both, a node is formatted as:
+  //   ```
+  //   {kind: 'foo', text: '...'}
+  //   ```
   //
-  // A single node without children is formatted as:
-  // ```
-  // {node_index: 0, kind: 'foo', text: '...'}
-  // ```
-  // A node with two children, one of them with an error:
-  // ```
-  // {node_index: 2, kind: 'foo', text: '...', children: [
-  //   {node_index: 0, kind: 'bar', text: '...', has_error: yes},
-  //   {node_index: 1, kind: 'baz', text: '...'}]}
-  // ```
   // The top level is formatted as an array of these nodes.
-  // ```
-  // [
-  // {node_index: 1, kind: 'foo', text: '...'},
-  // {node_index: 0, kind: 'foo', text: '...'},
-  // ...
-  // ]
-  // ```
+  //   ```
+  //   [
+  //   {kind: 'foo', text: '...'},
+  //   {kind: 'foo', text: '...'},
+  //   ...
+  //   ]
+  //   ```
+  //
+  // In postorder, nodes are indented in order to indicate depth. For example, a
+  // node with two children, one of them with an error:
+  //   ```
+  //     {kind: 'bar', text: '...', has_error: yes},
+  //     {kind: 'baz', text: '...'}
+  //   {kind: 'foo', text: '...', subtree_size: 2}
+  //   ```
+  //
+  // In preorder, nodes are marked as children with postorder (storage) index.
+  // For example, a node with two children, one of them with an error:
+  //   ```
+  //   {node_index: 2, kind: 'foo', text: '...', subtree_size: 2, children: [
+  //     {node_index: 0, kind: 'bar', text: '...', has_error: yes},
+  //     {node_index: 1, kind: 'baz', text: '...'}]}
+  //   ```
   //
   // This can be parsed as YAML using tools like `python-yq` combined with `jq`
   // on the command line. The format is also reasonably amenable to other
   // line-oriented shell tools from `grep` to `awk`.
-  auto Print(llvm::raw_ostream& output) const -> void;
+  auto Print(llvm::raw_ostream& output, bool preorder) const -> void;
 
   // Verifies the parse tree structure.
   //
@@ -211,6 +223,11 @@ class ParseTree {
   // should be used to actually parse the tokens into a tree.
   explicit ParseTree(TokenizedBuffer& tokens_arg) : tokens_(&tokens_arg) {}
 
+  // Prints a single node for Print(). Returns true when preorder and there are
+  // children.
+  auto PrintNode(llvm::raw_ostream& output, Node n, int depth,
+                 bool preorder) const -> bool;
+
   // Depth-first postorder sequence of node implementation data.
   llvm::SmallVector<NodeImpl, 0> node_impls_;
 

+ 25 - 1
toolchain/parser/parse_tree_test.cpp

@@ -146,7 +146,7 @@ TEST_F(ParseTreeTest, StructErrors) {
   }
 }
 
-TEST_F(ParseTreeTest, PrintingAsYAML) {
+TEST_F(ParseTreeTest, PrintPostorderAsYAML) {
   TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
   ParseTree tree = ParseTree::Parse(tokens, consumer);
   EXPECT_FALSE(tree.has_errors());
@@ -155,6 +155,30 @@ TEST_F(ParseTreeTest, PrintingAsYAML) {
   tree.Print(print_stream);
   print_stream.flush();
 
+  auto file = Yaml::SequenceValue{
+      Yaml::MappingValue{{"kind", "FunctionIntroducer"}, {"text", "fn"}},
+      Yaml::MappingValue{{"kind", "DeclaredName"}, {"text", "F"}},
+      Yaml::MappingValue{{"kind", "ParameterListEnd"}, {"text", ")"}},
+      Yaml::MappingValue{
+          {"kind", "ParameterList"}, {"text", "("}, {"subtree_size", "2"}},
+      Yaml::MappingValue{{"kind", "FunctionDeclaration"},
+                         {"text", ";"},
+                         {"subtree_size", "5"}},
+      Yaml::MappingValue{{"kind", "FileEnd"}, {"text", ""}},
+  };
+
+  EXPECT_THAT(Yaml::Value::FromText(print_output), ElementsAre(file));
+}
+
+TEST_F(ParseTreeTest, PrintPreorderAsYAML) {
+  TokenizedBuffer tokens = GetTokenizedBuffer("fn F();");
+  ParseTree tree = ParseTree::Parse(tokens, consumer);
+  EXPECT_FALSE(tree.has_errors());
+  std::string print_output;
+  llvm::raw_string_ostream print_stream(print_output);
+  tree.Print(print_stream, /*preorder=*/true);
+  print_stream.flush();
+
   auto parameter_list = Yaml::SequenceValue{
       Yaml::MappingValue{
           {"node_index", "2"}, {"kind", "ParameterListEnd"}, {"text", ")"}},

+ 1 - 1
toolchain/parser/testdata/basics/empty.carbon

@@ -5,5 +5,5 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 0, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]

+ 2 - 2
toolchain/parser/testdata/basics/empty_declaration.carbon

@@ -5,8 +5,8 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 0, kind: 'EmptyDeclaration', text: ';'},
-// CHECK:STDOUT: {node_index: 1, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT: {kind: 'EmptyDeclaration', text: ';'},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 ;

+ 17 - 17
toolchain/parser/testdata/basics/fail_invalid_designators.carbon

@@ -5,23 +5,23 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:     {kind: 'DesignatorExpression', text: '.', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', has_error: yes, subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'DesignatedName', text: 'fn', has_error: yes},
+// CHECK:STDOUT:     {kind: 'DesignatorExpression', text: '.', subtree_size: 3},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:     {kind: 'DesignatorExpression', text: '.', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', has_error: yes, subtree_size: 3},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 2 - 2
toolchain/parser/testdata/basics/fail_no_intro_with_semi.carbon

@@ -5,8 +5,8 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 0, kind: 'EmptyDeclaration', text: ';', has_error: yes},
-// CHECK:STDOUT: {node_index: 1, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT: {kind: 'EmptyDeclaration', text: ';', has_error: yes},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/basics/fail_no_intro_with_semi.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.

+ 1 - 1
toolchain/parser/testdata/basics/fail_no_intro_without_semi.carbon

@@ -5,7 +5,7 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 0, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/basics/fail_no_intro_without_semi.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.

+ 6 - 6
toolchain/parser/testdata/basics/fail_paren_match_regression.carbon

@@ -5,12 +5,12 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 4, kind: 'VariableDeclaration', text: 'var', has_error: yes, subtree_size: 5, children: [
-// CHECK:STDOUT:   {node_index: 3, kind: 'VariableInitializer', text: '=', subtree_size: 4, children: [
-// CHECK:STDOUT:     {node_index: 2, kind: 'ParenExpression', text: '(', has_error: yes, subtree_size: 3, children: [
-// CHECK:STDOUT:       {node_index: 0, kind: 'NameReference', text: 'foo'},
-// CHECK:STDOUT:       {node_index: 1, kind: 'ParenExpressionEnd', text: ')'}]}]}]},
-// CHECK:STDOUT: {node_index: 5, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParenExpressionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParenExpression', text: '(', has_error: yes, subtree_size: 3},
+// CHECK:STDOUT:   {kind: 'VariableInitializer', text: '=', subtree_size: 4},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', has_error: yes, subtree_size: 5},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/basics/fail_paren_match_regression.carbon:[[@LINE+3]]:5: Expected pattern in `var` declaration.

+ 26 - 26
toolchain/parser/testdata/basics/function_call.carbon

@@ -5,32 +5,32 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:               {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:               {kind: 'DesignatedName', text: 'b'},
+// CHECK:STDOUT:             {kind: 'DesignatorExpression', text: '.', subtree_size: 3},
+// CHECK:STDOUT:             {kind: 'DesignatedName', text: 'f'},
+// CHECK:STDOUT:           {kind: 'DesignatorExpression', text: '.', subtree_size: 5},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:             {kind: 'DesignatedName', text: 'd'},
+// CHECK:STDOUT:           {kind: 'DesignatorExpression', text: '.', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CallExpressionComma', text: ','},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'e'},
+// CHECK:STDOUT:             {kind: 'ParenExpressionEnd', text: ')'},
+// CHECK:STDOUT:           {kind: 'ParenExpression', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'CallExpression', text: '(', subtree_size: 14},
+// CHECK:STDOUT:         {kind: 'DesignatedName', text: 'g'},
+// CHECK:STDOUT:       {kind: 'DesignatorExpression', text: '.', subtree_size: 16},
+// CHECK:STDOUT:       {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'CallExpression', text: '(', subtree_size: 18},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 19},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 25},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 21 - 21
toolchain/parser/testdata/basics/package.carbon

@@ -5,27 +5,27 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 3, kind: 'PackageDirective', text: 'package', subtree_size: 4, children: [
-// CHECK:STDOUT:   {node_index: 0, kind: 'DeclaredName', text: 'Geometry'},
-// CHECK:STDOUT:   {node_index: 1, kind: 'PackageApi', text: 'api'},
-// CHECK:STDOUT:   {node_index: 2, kind: 'PackageEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 7, kind: 'PackageDirective', text: 'package', subtree_size: 4, children: [
-// CHECK:STDOUT:   {node_index: 4, kind: 'DeclaredName', text: 'Geometry'},
-// CHECK:STDOUT:   {node_index: 5, kind: 'PackageImpl', text: 'impl'},
-// CHECK:STDOUT:   {node_index: 6, kind: 'PackageEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 13, kind: 'PackageDirective', text: 'package', subtree_size: 6, children: [
-// CHECK:STDOUT:   {node_index: 8, kind: 'DeclaredName', text: 'Geometry'},
-// CHECK:STDOUT:   {node_index: 10, kind: 'PackageLibrary', text: 'library', subtree_size: 2, children: [
-// CHECK:STDOUT:     {node_index: 9, kind: 'Literal', text: '"Shapes"'}]},
-// CHECK:STDOUT:   {node_index: 11, kind: 'PackageApi', text: 'api'},
-// CHECK:STDOUT:   {node_index: 12, kind: 'PackageEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 19, kind: 'PackageDirective', text: 'package', subtree_size: 6, children: [
-// CHECK:STDOUT:   {node_index: 14, kind: 'DeclaredName', text: 'Geometry'},
-// CHECK:STDOUT:   {node_index: 16, kind: 'PackageLibrary', text: 'library', subtree_size: 2, children: [
-// CHECK:STDOUT:     {node_index: 15, kind: 'Literal', text: '"Shapes"'}]},
-// CHECK:STDOUT:   {node_index: 17, kind: 'PackageImpl', text: 'impl'},
-// CHECK:STDOUT:   {node_index: 18, kind: 'PackageEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 20, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'Geometry'},
+// CHECK:STDOUT:   {kind: 'PackageApi', text: 'api'},
+// CHECK:STDOUT:   {kind: 'PackageEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'PackageDirective', text: 'package', subtree_size: 4},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'Geometry'},
+// CHECK:STDOUT:   {kind: 'PackageImpl', text: 'impl'},
+// CHECK:STDOUT:   {kind: 'PackageEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'PackageDirective', text: 'package', subtree_size: 4},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'Geometry'},
+// CHECK:STDOUT:     {kind: 'Literal', text: '"Shapes"'},
+// CHECK:STDOUT:   {kind: 'PackageLibrary', text: 'library', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'PackageApi', text: 'api'},
+// CHECK:STDOUT:   {kind: 'PackageEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'PackageDirective', text: 'package', subtree_size: 6},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'Geometry'},
+// CHECK:STDOUT:     {kind: 'Literal', text: '"Shapes"'},
+// CHECK:STDOUT:   {kind: 'PackageLibrary', text: 'library', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'PackageImpl', text: 'impl'},
+// CHECK:STDOUT:   {kind: 'PackageEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'PackageDirective', text: 'package', subtree_size: 6},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 29 - 29
toolchain/parser/testdata/basics/return.carbon

@@ -5,35 +5,35 @@
 // AUTOUPDATE
 // RUN: %{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: '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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:         {kind: 'StatementEnd', text: ';'},
+// CHECK:STDOUT:       {kind: 'ReturnStatement', text: 'return', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 8},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14},
+// CHECK:STDOUT:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'G'},
+// CHECK:STDOUT:         {kind: 'DeclaredName', text: 'x'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'Foo'},
+// CHECK:STDOUT:       {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'Foo'},
+// CHECK:STDOUT:     {kind: 'ReturnType', text: '->', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 10},
+// CHECK:STDOUT:     {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:     {kind: 'StatementEnd', text: ';'},
+// CHECK:STDOUT:   {kind: 'ReturnStatement', text: 'return', subtree_size: 3},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 56 - 56
toolchain/parser/testdata/basics/structs.carbon

@@ -5,62 +5,62 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 26, kind: 'VariableDeclaration', text: 'var', subtree_size: 27, children: [
-// CHECK:STDOUT:   {node_index: 12, kind: 'PatternBinding', text: ':', subtree_size: 13, children: [
-// CHECK:STDOUT:     {node_index: 0, kind: 'DeclaredName', text: 'x'},
-// CHECK:STDOUT:     {node_index: 11, kind: 'StructTypeLiteral', text: '{', subtree_size: 11, children: [
-// CHECK:STDOUT:       {node_index: 4, kind: 'StructFieldType', text: ':', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 2, kind: 'StructFieldDesignator', text: '.', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 1, kind: 'DesignatedName', text: 'a'}]},
-// CHECK:STDOUT:         {node_index: 3, kind: 'Literal', text: 'i32'}]},
-// CHECK:STDOUT:       {node_index: 5, kind: 'StructComma', text: ','},
-// CHECK:STDOUT:       {node_index: 9, kind: 'StructFieldType', text: ':', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 7, kind: 'StructFieldDesignator', text: '.', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 6, kind: 'DesignatedName', text: 'b'}]},
-// CHECK:STDOUT:         {node_index: 8, kind: 'Literal', text: 'i32'}]},
-// CHECK:STDOUT:       {node_index: 10, kind: 'StructEnd', text: '}'}]}]},
-// CHECK:STDOUT:   {node_index: 24, kind: 'VariableInitializer', text: '=', subtree_size: 12, children: [
-// CHECK:STDOUT:     {node_index: 23, kind: 'StructLiteral', text: '{', subtree_size: 11, children: [
-// CHECK:STDOUT:       {node_index: 16, kind: 'StructFieldValue', text: '=', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 14, kind: 'StructFieldDesignator', text: '.', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 13, kind: 'DesignatedName', text: 'a'}]},
-// CHECK:STDOUT:         {node_index: 15, kind: 'Literal', text: '1'}]},
-// CHECK:STDOUT:       {node_index: 17, kind: 'StructComma', text: ','},
-// CHECK:STDOUT:       {node_index: 21, kind: 'StructFieldValue', text: '=', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 19, kind: 'StructFieldDesignator', text: '.', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 18, kind: 'DesignatedName', text: 'b'}]},
-// CHECK:STDOUT:         {node_index: 20, kind: 'Literal', text: '2'}]},
-// CHECK:STDOUT:       {node_index: 22, kind: 'StructEnd', text: '}'}]}]},
-// CHECK:STDOUT:   {node_index: 25, kind: 'DeclarationEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 35, kind: 'VariableDeclaration', text: 'var', subtree_size: 9, children: [
-// CHECK:STDOUT:   {node_index: 30, kind: 'PatternBinding', text: ':', subtree_size: 4, children: [
-// CHECK:STDOUT:     {node_index: 27, kind: 'DeclaredName', text: 'y'},
-// CHECK:STDOUT:     {node_index: 29, kind: 'StructLiteral', text: '{', subtree_size: 2, children: [
-// CHECK:STDOUT:       {node_index: 28, kind: 'StructEnd', text: '}'}]}]},
-// CHECK:STDOUT:   {node_index: 33, kind: 'VariableInitializer', text: '=', subtree_size: 3, children: [
-// CHECK:STDOUT:     {node_index: 32, kind: 'StructLiteral', text: '{', subtree_size: 2, children: [
-// CHECK:STDOUT:       {node_index: 31, kind: 'StructEnd', text: '}'}]}]},
-// CHECK:STDOUT:   {node_index: 34, kind: 'DeclarationEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 54, kind: 'VariableDeclaration', text: 'var', subtree_size: 19, children: [
-// CHECK:STDOUT:   {node_index: 44, kind: 'PatternBinding', text: ':', subtree_size: 9, children: [
-// CHECK:STDOUT:     {node_index: 36, kind: 'DeclaredName', text: 'z'},
-// CHECK:STDOUT:     {node_index: 43, kind: 'StructTypeLiteral', text: '{', subtree_size: 7, children: [
-// CHECK:STDOUT:       {node_index: 40, kind: 'StructFieldType', text: ':', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 38, kind: 'StructFieldDesignator', text: '.', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 37, kind: 'DesignatedName', text: 'n'}]},
-// CHECK:STDOUT:         {node_index: 39, kind: 'Literal', text: 'i32'}]},
-// CHECK:STDOUT:       {node_index: 41, kind: 'StructComma', text: ','},
-// CHECK:STDOUT:       {node_index: 42, kind: 'StructEnd', text: '}'}]}]},
-// CHECK:STDOUT:   {node_index: 52, kind: 'VariableInitializer', text: '=', subtree_size: 8, children: [
-// CHECK:STDOUT:     {node_index: 51, kind: 'StructLiteral', text: '{', subtree_size: 7, children: [
-// CHECK:STDOUT:       {node_index: 48, kind: 'StructFieldValue', text: '=', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 46, kind: 'StructFieldDesignator', text: '.', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 45, kind: 'DesignatedName', text: 'n'}]},
-// CHECK:STDOUT:         {node_index: 47, kind: 'Literal', text: '4'}]},
-// CHECK:STDOUT:       {node_index: 49, kind: 'StructComma', text: ','},
-// CHECK:STDOUT:       {node_index: 50, kind: 'StructEnd', text: '}'}]}]},
-// CHECK:STDOUT:   {node_index: 53, kind: 'DeclarationEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 55, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'x'},
+// CHECK:STDOUT:           {kind: 'DesignatedName', text: 'a'},
+// CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'StructFieldType', text: ':', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'DesignatedName', text: 'b'},
+// CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'StructFieldType', text: ':', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructEnd', text: '}'},
+// CHECK:STDOUT:     {kind: 'StructTypeLiteral', text: '{', subtree_size: 11},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 13},
+// CHECK:STDOUT:           {kind: 'DesignatedName', text: 'a'},
+// CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'Literal', text: '1'},
+// CHECK:STDOUT:       {kind: 'StructFieldValue', text: '=', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:           {kind: 'DesignatedName', text: 'b'},
+// CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'Literal', text: '2'},
+// CHECK:STDOUT:       {kind: 'StructFieldValue', text: '=', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructEnd', text: '}'},
+// CHECK:STDOUT:     {kind: 'StructLiteral', text: '{', subtree_size: 11},
+// CHECK:STDOUT:   {kind: 'VariableInitializer', text: '=', subtree_size: 12},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 27},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'y'},
+// CHECK:STDOUT:       {kind: 'StructEnd', text: '}'},
+// CHECK:STDOUT:     {kind: 'StructLiteral', text: '{', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructEnd', text: '}'},
+// CHECK:STDOUT:     {kind: 'StructLiteral', text: '{', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'VariableInitializer', text: '=', subtree_size: 3},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 9},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'z'},
+// CHECK:STDOUT:           {kind: 'DesignatedName', text: 'n'},
+// CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'StructFieldType', text: ':', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:       {kind: 'StructEnd', text: '}'},
+// CHECK:STDOUT:     {kind: 'StructTypeLiteral', text: '{', subtree_size: 7},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 9},
+// CHECK:STDOUT:           {kind: 'DesignatedName', text: 'n'},
+// CHECK:STDOUT:         {kind: 'StructFieldDesignator', text: '.', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'Literal', text: '4'},
+// CHECK:STDOUT:       {kind: 'StructFieldValue', text: '=', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'StructComma', text: ','},
+// CHECK:STDOUT:       {kind: 'StructEnd', text: '}'},
+// CHECK:STDOUT:     {kind: 'StructLiteral', text: '{', subtree_size: 7},
+// CHECK:STDOUT:   {kind: 'VariableInitializer', text: '=', subtree_size: 8},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 19},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 30 - 30
toolchain/parser/testdata/basics/tuples.carbon

@@ -5,36 +5,36 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 14, kind: 'VariableDeclaration', text: 'var', subtree_size: 15, children: [
-// CHECK:STDOUT:   {node_index: 6, kind: 'PatternBinding', text: ':', subtree_size: 7, children: [
-// CHECK:STDOUT:     {node_index: 0, kind: 'DeclaredName', text: 'x'},
-// CHECK:STDOUT:     {node_index: 5, kind: 'TupleLiteral', text: '(', subtree_size: 5, children: [
-// CHECK:STDOUT:       {node_index: 1, kind: 'Literal', text: 'i32'},
-// CHECK:STDOUT:       {node_index: 2, kind: 'TupleLiteralComma', text: ','},
-// CHECK:STDOUT:       {node_index: 3, kind: 'Literal', text: 'i32'},
-// CHECK:STDOUT:       {node_index: 4, kind: 'TupleLiteralEnd', text: ')'}]}]},
-// CHECK:STDOUT:   {node_index: 12, kind: 'VariableInitializer', text: '=', subtree_size: 6, children: [
-// CHECK:STDOUT:     {node_index: 11, kind: 'TupleLiteral', text: '(', subtree_size: 5, children: [
-// CHECK:STDOUT:       {node_index: 7, kind: 'Literal', text: '1'},
-// CHECK:STDOUT:       {node_index: 8, kind: 'TupleLiteralComma', text: ','},
-// CHECK:STDOUT:       {node_index: 9, kind: 'Literal', text: '2'},
-// CHECK:STDOUT:       {node_index: 10, kind: 'TupleLiteralEnd', text: ')'}]}]},
-// CHECK:STDOUT:   {node_index: 13, kind: 'DeclarationEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 28, kind: 'VariableDeclaration', text: 'var', subtree_size: 14, children: [
-// CHECK:STDOUT:   {node_index: 26, kind: 'PatternBinding', text: ':', subtree_size: 12, children: [
-// CHECK:STDOUT:     {node_index: 15, kind: 'DeclaredName', text: 'y'},
-// CHECK:STDOUT:     {node_index: 25, kind: 'TupleLiteral', text: '(', subtree_size: 10, children: [
-// CHECK:STDOUT:       {node_index: 17, kind: 'TupleLiteral', text: '(', subtree_size: 2, children: [
-// CHECK:STDOUT:         {node_index: 16, kind: 'TupleLiteralEnd', text: ')'}]},
-// CHECK:STDOUT:       {node_index: 18, kind: 'TupleLiteralComma', text: ','},
-// CHECK:STDOUT:       {node_index: 20, kind: 'TupleLiteral', text: '(', subtree_size: 2, children: [
-// CHECK:STDOUT:         {node_index: 19, kind: 'TupleLiteralEnd', text: ')'}]},
-// CHECK:STDOUT:       {node_index: 21, kind: 'TupleLiteralComma', text: ','},
-// CHECK:STDOUT:       {node_index: 23, kind: 'TupleLiteral', text: '(', subtree_size: 2, children: [
-// CHECK:STDOUT:         {node_index: 22, kind: 'TupleLiteralEnd', text: ')'}]},
-// CHECK:STDOUT:       {node_index: 24, kind: 'TupleLiteralEnd', text: ')'}]}]},
-// CHECK:STDOUT:   {node_index: 27, kind: 'DeclarationEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 29, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'x'},
+// CHECK:STDOUT:       {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'TupleLiteralComma', text: ','},
+// CHECK:STDOUT:       {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'TupleLiteralEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'TupleLiteral', text: '(', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 7},
+// CHECK:STDOUT:       {kind: 'Literal', text: '1'},
+// CHECK:STDOUT:       {kind: 'TupleLiteralComma', text: ','},
+// CHECK:STDOUT:       {kind: 'Literal', text: '2'},
+// CHECK:STDOUT:       {kind: 'TupleLiteralEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'TupleLiteral', text: '(', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'VariableInitializer', text: '=', subtree_size: 6},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 15},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'y'},
+// CHECK:STDOUT:         {kind: 'TupleLiteralEnd', text: ')'},
+// CHECK:STDOUT:       {kind: 'TupleLiteral', text: '(', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'TupleLiteralComma', text: ','},
+// CHECK:STDOUT:         {kind: 'TupleLiteralEnd', text: ')'},
+// CHECK:STDOUT:       {kind: 'TupleLiteral', text: '(', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'TupleLiteralComma', text: ','},
+// CHECK:STDOUT:         {kind: 'TupleLiteralEnd', text: ')'},
+// CHECK:STDOUT:       {kind: 'TupleLiteral', text: '(', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'TupleLiteralEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'TupleLiteral', text: '(', subtree_size: 10},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 12},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 14},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 26 - 26
toolchain/parser/testdata/basics/var.carbon

@@ -5,32 +5,32 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 6, kind: 'VariableDeclaration', text: 'var', subtree_size: 7, children: [
-// CHECK:STDOUT:   {node_index: 2, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [
-// CHECK:STDOUT:     {node_index: 0, kind: 'DeclaredName', text: 'v'},
-// CHECK:STDOUT:     {node_index: 1, kind: 'Literal', text: 'i32'}]},
-// CHECK:STDOUT:   {node_index: 4, kind: 'VariableInitializer', text: '=', subtree_size: 2, children: [
-// CHECK:STDOUT:     {node_index: 3, kind: 'Literal', text: '0'}]},
-// CHECK:STDOUT:   {node_index: 5, kind: 'DeclarationEnd', text: ';'}]},
-// CHECK:STDOUT: {node_index: 11, kind: 'VariableDeclaration', text: 'var', subtree_size: 5, children: [
-// CHECK:STDOUT:   {node_index: 9, kind: 'PatternBinding', text: ':', subtree_size: 3, children: [
-// 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: '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:     {kind: 'DeclaredName', text: 'v'},
+// CHECK:STDOUT:     {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'Literal', text: '0'},
+// CHECK:STDOUT:   {kind: 'VariableInitializer', text: '=', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 7},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'w'},
+// CHECK:STDOUT:     {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:   {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:   {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT: {kind: 'VariableDeclaration', text: 'var', subtree_size: 5},
+// CHECK:STDOUT:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'DeclaredName', text: 's'},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'String'},
+// CHECK:STDOUT:     {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'Literal', text: '"hello"'},
+// CHECK:STDOUT:     {kind: 'VariableInitializer', text: '=', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT:   {kind: 'VariableDeclaration', text: 'var', subtree_size: 7},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 13},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // NOTE: Move to its own directory when more tests are added.

+ 22 - 22
toolchain/parser/testdata/for/fail_colon_instead_of_in.carbon

@@ -5,28 +5,28 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:           {kind: 'DeclaredName', text: 'x'},
+// CHECK:STDOUT:           {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:         {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'VariableDeclaration', text: 'var', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'y'},
+// CHECK:STDOUT:       {kind: 'ForHeaderEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 7},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'Print'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:           {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'CallExpression', text: '(', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 5},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 7},
+// CHECK:STDOUT:   {kind: 'ForStatement', text: 'for', subtree_size: 15},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 21},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() {

+ 21 - 21
toolchain/parser/testdata/for/fail_missing_in.carbon

@@ -5,27 +5,27 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:           {kind: 'DeclaredName', text: 'x'},
+// CHECK:STDOUT:           {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:         {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'VariableDeclaration', text: 'var', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ForHeaderEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 6},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'Print'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:           {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'CallExpression', text: '(', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 5},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 7},
+// CHECK:STDOUT:   {kind: 'ForStatement', text: 'for', subtree_size: 14},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 20},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() {

+ 19 - 19
toolchain/parser/testdata/for/fail_missing_var.carbon

@@ -5,25 +5,25 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'ForIn', text: 'in'},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'y'},
+// CHECK:STDOUT:       {kind: 'ForHeaderEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ForHeader', text: '(', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'Print'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:           {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'CallExpression', text: '(', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 5},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 7},
+// CHECK:STDOUT:   {kind: 'ForStatement', text: 'for', subtree_size: 12},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() {

+ 34 - 34
toolchain/parser/testdata/for/nested.carbon

@@ -5,40 +5,40 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:           {kind: 'DeclaredName', text: 'y'},
+// CHECK:STDOUT:           {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:         {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'VariableDeclaration', text: 'var', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ForIn', text: 'in'},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:       {kind: 'ForHeaderEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ForHeader', text: '(', subtree_size: 8},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:               {kind: 'DeclaredName', text: 'z'},
+// CHECK:STDOUT:               {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:             {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'VariableDeclaration', text: 'var', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'ForIn', text: 'in'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'y'},
+// CHECK:STDOUT:           {kind: 'ForHeaderEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'ForHeader', text: '(', subtree_size: 8},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:               {kind: 'NameReference', text: 'Print'},
+// CHECK:STDOUT:               {kind: 'NameReference', text: 'z'},
+// CHECK:STDOUT:               {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:             {kind: 'CallExpression', text: '(', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'ExpressionStatement', text: ';', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: '}', subtree_size: 7},
+// CHECK:STDOUT:       {kind: 'ForStatement', text: 'for', subtree_size: 16},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 18},
+// CHECK:STDOUT:   {kind: 'ForStatement', text: 'for', subtree_size: 27},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 33},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() {

+ 23 - 23
toolchain/parser/testdata/for/simple.carbon

@@ -5,29 +5,29 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:           {kind: 'DeclaredName', text: 'x'},
+// CHECK:STDOUT:           {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:         {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'VariableDeclaration', text: 'var', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ForIn', text: 'in'},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'y'},
+// CHECK:STDOUT:       {kind: 'ForHeaderEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ForHeader', text: '(', subtree_size: 8},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'Print'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:           {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'CallExpression', text: '(', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 5},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 7},
+// CHECK:STDOUT:   {kind: 'ForStatement', text: 'for', subtree_size: 16},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 22},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() {

+ 6 - 6
toolchain/parser/testdata/function/declaration/basic.carbon

@@ -5,12 +5,12 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F();

+ 4 - 4
toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon

@@ -5,10 +5,10 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 3},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_identifier_instead_of_sig.carbon:[[@LINE+1]]:8: Expected `(` after function name.

+ 3 - 3
toolchain/parser/testdata/function/declaration/fail_missing_name.carbon

@@ -5,9 +5,9 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_missing_name.carbon:[[@LINE+1]]:4: Expected function name after `fn` keyword.

+ 4 - 4
toolchain/parser/testdata/function/declaration/fail_no_sig_or_semi.carbon

@@ -5,10 +5,10 @@
 // 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: 'FunctionIntroducer', text: 'fn'},
-// CHECK:STDOUT:   {node_index: 1, kind: 'DeclaredName', text: 'foo'}]},
-// CHECK:STDOUT: {node_index: 3, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 3},
+// CHECK:STDOUT: {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.

+ 3 - 3
toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon

@@ -5,9 +5,9 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_only_fn_and_semi.carbon:[[@LINE+1]]:3: Expected function name after `fn` keyword.

+ 3 - 3
toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon

@@ -5,9 +5,9 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_repeated_fn_and_semi.carbon:[[@LINE+1]]:4: Expected function name after `fn` keyword.

+ 8 - 8
toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_until_outdent.carbon

@@ -5,14 +5,14 @@
 // 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: '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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {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.

+ 8 - 8
toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon

@@ -5,14 +5,14 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_with_semi.carbon:[[@LINE+1]]:4: Expected function name after `fn` keyword.

+ 8 - 8
toolchain/parser/testdata/function/declaration/fail_skip_indented_newline_without_semi.carbon

@@ -5,14 +5,14 @@
 // 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: '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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {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.

+ 8 - 8
toolchain/parser/testdata/function/declaration/fail_skip_to_newline_without_semi.carbon

@@ -5,14 +5,14 @@
 // 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: '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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: 'fn', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {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.

+ 6 - 6
toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon

@@ -5,12 +5,12 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_skip_without_semi_to_curly.carbon:[[@LINE+1]]:1: Unrecognized declaration introducer.

+ 6 - 6
toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon

@@ -5,12 +5,12 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 5},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_with_identifier_as_param.carbon:[[@LINE+1]]:8: Expected parameter declaration.

+ 3 - 3
toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon

@@ -5,9 +5,9 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 // CHECK:STDERR: {{.*}}/toolchain/parser/testdata/function/declaration/fail_without_name_and_many_tokens_in_params.carbon:[[@LINE+1]]:4: Expected function name after `fn` keyword.

+ 13 - 13
toolchain/parser/testdata/function/declaration/with_params.carbon

@@ -5,19 +5,19 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'DeclaredName', text: 'bar'},
+// CHECK:STDOUT:       {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:     {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'ParameterListComma', text: ','},
+// CHECK:STDOUT:       {kind: 'DeclaredName', text: 'baz'},
+// CHECK:STDOUT:       {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:     {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 9},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 12},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo(bar: i32, baz: i32);

+ 8 - 8
toolchain/parser/testdata/function/declaration/with_return_type.carbon

@@ -5,14 +5,14 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:   {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:   {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:     {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:   {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'Literal', text: 'u32'},
+// CHECK:STDOUT:   {kind: 'ReturnType', text: '->', subtree_size: 2},
+// CHECK:STDOUT: {kind: 'FunctionDeclaration', text: ';', subtree_size: 7},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() -> u32;

+ 7 - 7
toolchain/parser/testdata/function/definition/basic.carbon

@@ -5,13 +5,13 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 6},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 8 - 8
toolchain/parser/testdata/function/definition/fail_identifier_in_statements.carbon

@@ -5,14 +5,14 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'NameReference', text: 'bar'},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', has_error: yes, subtree_size: 7},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 23 - 23
toolchain/parser/testdata/function/definition/with_params.carbon

@@ -5,29 +5,29 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:         {kind: 'DeclaredName', text: 'bar'},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i64'},
+// CHECK:STDOUT:       {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'ParameterListComma', text: ','},
+// CHECK:STDOUT:         {kind: 'DeclaredName', text: 'baz'},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i64'},
+// CHECK:STDOUT:       {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 9},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 12},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'baz'},
+// CHECK:STDOUT:       {kind: 'CallExpressionComma', text: ','},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'bar'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'baz'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: '+', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'CallExpression', text: '(', subtree_size: 8},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 9},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 22},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo(bar: i64, baz: i64) {

+ 12 - 12
toolchain/parser/testdata/function/definition/with_return_type.carbon

@@ -5,18 +5,18 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'foo'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'Literal', text: 'f64'},
+// CHECK:STDOUT:     {kind: 'ReturnType', text: '->', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
+// CHECK:STDOUT:     {kind: 'Literal', text: '42'},
+// CHECK:STDOUT:     {kind: 'StatementEnd', text: ';'},
+// CHECK:STDOUT:   {kind: 'ReturnStatement', text: 'return', subtree_size: 3},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 11},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn foo() -> f64 {

+ 27 - 27
toolchain/parser/testdata/if/basic.carbon

@@ -5,33 +5,33 @@
 // AUTOUPDATE
 // RUN: %{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: '}', 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:           {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:               {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:               {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:             {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:               {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:                 {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:               {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:             {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'IfStatement', text: 'if', subtree_size: 8},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: '}', subtree_size: 10},
+// CHECK:STDOUT:       {kind: 'IfStatement', text: 'if', subtree_size: 14},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 16},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 20},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 26},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 53 - 53
toolchain/parser/testdata/if/else.carbon

@@ -5,59 +5,59 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 51, kind: 'FunctionDefinition', text: '}', subtree_size: 52, 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: 50, kind: 'IfStatement', text: 'if', subtree_size: 22, 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: 35, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [
-// CHECK:STDOUT:       {node_index: 32, kind: 'CodeBlockStart', text: '{'},
-// CHECK:STDOUT:       {node_index: 34, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [
-// CHECK:STDOUT:         {node_index: 33, kind: 'NameReference', text: 'f'}]}]},
-// CHECK:STDOUT:     {node_index: 36, kind: 'IfStatementElse', text: 'else'},
-// CHECK:STDOUT:     {node_index: 49, kind: 'IfStatement', text: 'if', subtree_size: 13, children: [
-// CHECK:STDOUT:       {node_index: 39, kind: 'Condition', text: '(', subtree_size: 3, children: [
-// CHECK:STDOUT:         {node_index: 37, kind: 'NameReference', text: 'x'},
-// CHECK:STDOUT:         {node_index: 38, kind: 'ConditionEnd', text: ')'}]},
-// CHECK:STDOUT:       {node_index: 43, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 40, kind: 'CodeBlockStart', text: '{'},
-// CHECK:STDOUT:         {node_index: 42, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 41, kind: 'NameReference', text: 'g'}]}]},
-// CHECK:STDOUT:       {node_index: 44, kind: 'IfStatementElse', text: 'else'},
-// CHECK:STDOUT:       {node_index: 48, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 45, kind: 'CodeBlockStart', text: '{'},
-// CHECK:STDOUT:         {node_index: 47, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 46, kind: 'NameReference', text: 'h'}]}]}]}]}]},
-// CHECK:STDOUT: {node_index: 52, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:           {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:           {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:           {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'IfStatement', text: 'if', subtree_size: 13},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 15},
+// CHECK:STDOUT:     {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'e'},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 24},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'f'},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:     {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:         {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:       {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:         {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'g'},
+// CHECK:STDOUT:         {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:         {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'h'},
+// CHECK:STDOUT:         {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:     {kind: 'IfStatement', text: 'if', subtree_size: 13},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 22},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 52},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 53 - 53
toolchain/parser/testdata/if/fail_else_unbraced.carbon

@@ -5,59 +5,59 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// CHECK:STDOUT: {node_index: 51, kind: 'FunctionDefinition', text: '}', subtree_size: 52, 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: 50, kind: 'IfStatement', text: 'if', subtree_size: 22, 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: 35, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [
-// CHECK:STDOUT:       {node_index: 32, kind: 'CodeBlockStart', text: '{'},
-// CHECK:STDOUT:       {node_index: 34, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [
-// CHECK:STDOUT:         {node_index: 33, kind: 'NameReference', text: 'f'}]}]},
-// CHECK:STDOUT:     {node_index: 36, kind: 'IfStatementElse', text: 'else'},
-// CHECK:STDOUT:     {node_index: 49, kind: 'IfStatement', text: 'if', subtree_size: 13, children: [
-// CHECK:STDOUT:       {node_index: 39, kind: 'Condition', text: '(', subtree_size: 3, children: [
-// CHECK:STDOUT:         {node_index: 37, kind: 'NameReference', text: 'x'},
-// CHECK:STDOUT:         {node_index: 38, kind: 'ConditionEnd', text: ')'}]},
-// CHECK:STDOUT:       {node_index: 43, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 40, kind: 'CodeBlockStart', text: '{'},
-// CHECK:STDOUT:         {node_index: 42, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 41, kind: 'NameReference', text: 'g'}]}]},
-// CHECK:STDOUT:       {node_index: 44, kind: 'IfStatementElse', text: 'else'},
-// CHECK:STDOUT:       {node_index: 48, kind: 'CodeBlock', text: '}', subtree_size: 4, children: [
-// CHECK:STDOUT:         {node_index: 45, kind: 'CodeBlockStart', text: '{'},
-// CHECK:STDOUT:         {node_index: 47, kind: 'ExpressionStatement', text: ';', subtree_size: 2, children: [
-// CHECK:STDOUT:           {node_index: 46, kind: 'NameReference', text: 'h'}]}]}]}]}]},
-// CHECK:STDOUT: {node_index: 52, kind: 'FileEnd', text: ''},
+// CHECK:STDOUT:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: 'if', has_error: yes},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:           {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: 'c', has_error: yes},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:           {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: 'c', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:         {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: 'd', has_error: yes},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:           {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: 'd', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'IfStatement', text: 'if', subtree_size: 13},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: 'if', has_error: yes, subtree_size: 15},
+// CHECK:STDOUT:     {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: 'e', has_error: yes},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'e'},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: 'e', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 24},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'f'},
+// CHECK:STDOUT:       {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:     {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'x'},
+// CHECK:STDOUT:         {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:       {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:         {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'g'},
+// CHECK:STDOUT:         {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'IfStatementElse', text: 'else'},
+// CHECK:STDOUT:         {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'h'},
+// CHECK:STDOUT:         {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:     {kind: 'IfStatement', text: 'if', subtree_size: 13},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 22},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 52},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 28 - 28
toolchain/parser/testdata/if/fail_errors.carbon

@@ -5,34 +5,34 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:     {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', has_error: yes, subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 6},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '}', has_error: yes},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', has_error: yes, subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 6},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 27},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 27 - 27
toolchain/parser/testdata/if/fail_unbraced.carbon

@@ -6,33 +6,33 @@
 // 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: 'if', has_error: yes},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:           {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: 'if', has_error: yes},
+// CHECK:STDOUT:               {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:               {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:             {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:               {kind: 'CodeBlockStart', text: 'd', has_error: yes},
+// CHECK:STDOUT:                 {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:               {kind: 'ExpressionStatement', text: ';', subtree_size: 2},
+// CHECK:STDOUT:             {kind: 'CodeBlock', text: 'd', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:           {kind: 'IfStatement', text: 'if', subtree_size: 8},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: 'if', has_error: yes, subtree_size: 10},
+// CHECK:STDOUT:       {kind: 'IfStatement', text: 'if', subtree_size: 14},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: 'if', has_error: yes, subtree_size: 16},
+// CHECK:STDOUT:   {kind: 'IfStatement', text: 'if', subtree_size: 20},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 26},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 13 - 13
toolchain/parser/testdata/operators/associative.carbon

@@ -5,19 +5,19 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: 'and', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: 'and', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 12},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 13 - 13
toolchain/parser/testdata/operators/fail_missing_precedence_and_or.carbon

@@ -5,19 +5,19 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: 'and', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: 'or', has_error: yes, subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 12},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 13 - 13
toolchain/parser/testdata/operators/fail_missing_precedence_or_and.carbon

@@ -5,19 +5,19 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: 'or', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: 'and', has_error: yes, subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 12},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 28 - 28
toolchain/parser/testdata/operators/fail_variety.carbon

@@ -5,34 +5,34 @@
 // AUTOUPDATE
 // RUN: %{not} %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:           {kind: 'InfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:           {kind: 'InfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:         {kind: 'InfixOperator', text: '+', subtree_size: 7},
+// CHECK:STDOUT:                 {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:                 {kind: 'NameReference', text: 'd'},
+// CHECK:STDOUT:               {kind: 'InfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:               {kind: 'NameReference', text: 'e'},
+// CHECK:STDOUT:             {kind: 'InfixOperator', text: '<<', has_error: yes, subtree_size: 5},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'f'},
+// CHECK:STDOUT:           {kind: 'InfixOperator', text: '&', has_error: yes, subtree_size: 7},
+// CHECK:STDOUT:             {kind: 'NameReference', text: 'g'},
+// CHECK:STDOUT:           {kind: 'PrefixOperator', text: 'not', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'InfixOperator', text: '-', has_error: yes, subtree_size: 10},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: '=', subtree_size: 18},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: '=', subtree_size: 20},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 21},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 27},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 66 - 66
toolchain/parser/testdata/operators/fixity.carbon

@@ -5,72 +5,72 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:         {kind: 'DeclaredName', text: 'p'},
+// CHECK:STDOUT:           {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:         {kind: 'PostfixOperator', text: '*', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'PatternBinding', text: ':', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'ParameterListComma', text: ','},
+// CHECK:STDOUT:         {kind: 'DeclaredName', text: 'n'},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 10},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 13},
+// CHECK:STDOUT:       {kind: 'DeclaredName', text: 'q'},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'PostfixOperator', text: '*', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'PatternBinding', text: ':', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'p'},
+// CHECK:STDOUT:     {kind: 'VariableInitializer', text: '=', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT:   {kind: 'VariableDeclaration', text: 'var', subtree_size: 8},
+// CHECK:STDOUT:       {kind: 'DeclaredName', text: 't'},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'Type'},
+// CHECK:STDOUT:     {kind: 'PatternBinding', text: ':', subtree_size: 3},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'PostfixOperator', text: '*', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'VariableInitializer', text: '=', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'DeclarationEnd', text: ';'},
+// CHECK:STDOUT:   {kind: 'VariableDeclaration', text: 'var', subtree_size: 8},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 't'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 't'},
+// CHECK:STDOUT:         {kind: 'PostfixOperator', text: '*', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'PostfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: '=', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: '=', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'p'},
+// CHECK:STDOUT:         {kind: 'PrefixOperator', text: '*', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: '*', subtree_size: 4},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: '=', subtree_size: 6},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 7},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: '=', subtree_size: 5},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'G'},
+// CHECK:STDOUT:         {kind: 'Literal', text: 'i32'},
+// CHECK:STDOUT:       {kind: 'PostfixOperator', text: '*', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'CallExpressionComma', text: ','},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: '*', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CallExpressionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'CallExpression', text: '(', subtree_size: 9},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 10},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 65},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F(p: i32*, n: i32) {

+ 16 - 16
toolchain/parser/testdata/operators/missing_precedence_not.carbon

@@ -5,22 +5,22 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:         {kind: 'PrefixOperator', text: 'not', subtree_size: 2},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:         {kind: 'PrefixOperator', text: 'not', subtree_size: 2},
+// CHECK:STDOUT:       {kind: 'InfixOperator', text: 'and', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:       {kind: 'PrefixOperator', text: 'not', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'InfixOperator', text: 'and', subtree_size: 8},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 9},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 15},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 11 - 11
toolchain/parser/testdata/operators/postfix_unary.carbon

@@ -5,17 +5,17 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:       {kind: 'PostfixOperator', text: '++', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'PostfixOperator', text: '++', subtree_size: 3},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 4},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 10},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 11 - 11
toolchain/parser/testdata/operators/prefix_unary.carbon

@@ -5,17 +5,17 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:         {kind: 'NameReference', text: 'n'},
+// CHECK:STDOUT:       {kind: 'PrefixOperator', text: '++', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'PrefixOperator', text: '++', subtree_size: 3},
+// CHECK:STDOUT:   {kind: 'ExpressionStatement', text: ';', subtree_size: 4},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 10},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 29 - 29
toolchain/parser/testdata/while/basic.carbon

@@ -5,35 +5,35 @@
 // AUTOUPDATE
 // RUN: %{carbon-run-parser}
 // CHECK:STDOUT: [
-// 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'b'},
+// CHECK:STDOUT:           {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:             {kind: 'StatementEnd', text: ';'},
+// CHECK:STDOUT:           {kind: 'BreakStatement', text: 'break', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'IfStatement', text: 'if', subtree_size: 8},
+// CHECK:STDOUT:           {kind: 'NameReference', text: 'c'},
+// CHECK:STDOUT:           {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:         {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:           {kind: 'CodeBlockStart', text: '{'},
+// CHECK:STDOUT:             {kind: 'StatementEnd', text: ';'},
+// CHECK:STDOUT:           {kind: 'ContinueStatement', text: 'continue', subtree_size: 2},
+// CHECK:STDOUT:         {kind: 'CodeBlock', text: '}', subtree_size: 4},
+// CHECK:STDOUT:       {kind: 'IfStatement', text: 'if', subtree_size: 8},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: '}', subtree_size: 18},
+// CHECK:STDOUT:   {kind: 'WhileStatement', text: 'while', subtree_size: 22},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 28},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {

+ 15 - 15
toolchain/parser/testdata/while/fail_unbraced.carbon

@@ -6,21 +6,21 @@
 // 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:     {kind: 'FunctionIntroducer', text: 'fn'},
+// CHECK:STDOUT:     {kind: 'DeclaredName', text: 'F'},
+// CHECK:STDOUT:       {kind: 'ParameterListEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'ParameterList', text: '(', subtree_size: 2},
+// CHECK:STDOUT:   {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
+// CHECK:STDOUT:       {kind: 'NameReference', text: 'a'},
+// CHECK:STDOUT:       {kind: 'ConditionEnd', text: ')'},
+// CHECK:STDOUT:     {kind: 'Condition', text: '(', subtree_size: 3},
+// CHECK:STDOUT:       {kind: 'CodeBlockStart', text: 'break', has_error: yes},
+// CHECK:STDOUT:         {kind: 'StatementEnd', text: ';'},
+// CHECK:STDOUT:       {kind: 'BreakStatement', text: 'break', subtree_size: 2},
+// CHECK:STDOUT:     {kind: 'CodeBlock', text: 'break', has_error: yes, subtree_size: 4},
+// CHECK:STDOUT:   {kind: 'WhileStatement', text: 'while', subtree_size: 8},
+// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14},
+// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
 // CHECK:STDOUT: ]
 
 fn F() {