%{
  # -*- mode: C++ -*-
  from gyb_syntax_support import *
  NODE_MAP = create_node_map()
  # Ignore the following admonition; it applies to the resulting .cpp file only
}%
//// Automatically Generated From ParsedSyntaxBuilders.cpp.gyb.
//// Do Not Edit Directly!
//===------------- ParsedSyntaxBuilders.cpp - Parsed Syntax Building ------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Parse/ParsedSyntaxBuilders.h"
#include "swift/Parse/ParsedRawSyntaxRecorder.h"
#include "swift/Parse/SyntaxParsingContext.h"
#include "swift/Syntax/SyntaxNodes.h"

using namespace swift;
using namespace swift::syntax;

% for node in SYNTAX_NODES:
%   if node.is_buildable():
%     for child in node.children:
%       child_elt = None
%       child_elt_type = None
%       child_node = NODE_MAP.get(child.syntax_kind)
%       if child_node and child_node.is_syntax_collection():
%         child_elt = child_node.collection_element_name
%         child_elt_type = child_node.collection_element_type
%       end
Parsed${node.name}Builder &
Parsed${node.name}Builder::use${child.name}(Parsed${child.type_name} ${child.name}) {
%       if child_elt:
  assert(${child_elt}Nodes.empty() && "use either 'use' function or 'add', not both");
%       end
  Layout[cursorIndex(${node.name}::Cursor::${child.name})] =
    ${child.name}.getRaw();
  return *this;
}
%       if child_elt:
Parsed${node.name}Builder &
Parsed${node.name}Builder::add${child_elt}(Parsed${child_elt_type} ${child_elt}) {
  assert(Layout[cursorIndex(${node.name}::Cursor::${child.name})].isNull() && "use either 'use' function or 'add', not both");
  ${child_elt}Nodes.push_back(std::move(${child_elt}.getRaw()));
  return *this;
}
%       end
%     end

Parsed${node.name}
Parsed${node.name}Builder::record() {
  finishLayout(/*deferred=*/false);
  auto &Rec = SPCtx.getRecorder();
  auto raw = Rec.recordRawSyntax(SyntaxKind::${node.syntax_kind}, Layout);
  return Parsed${node.name}(std::move(raw));
}

Parsed${node.name}
Parsed${node.name}Builder::makeDeferred() {
  finishLayout(/*deferred=*/true);
  auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind},
    Layout, SPCtx);
  return Parsed${node.name}(std::move(raw));
}

Parsed${node.name}
Parsed${node.name}Builder::build() {
  if (SPCtx.isBacktracking())
    return makeDeferred();
  return record();
}

void Parsed${node.name}Builder::finishLayout(bool deferred) {
  auto &Rec = SPCtx.getRecorder();
  (void)Rec;
% if node.children:
%   for (idx, child) in enumerate(node.children):
%     child_elt = None
%     child_node = NODE_MAP.get(child.syntax_kind)
%     if child_node and child_node.is_syntax_collection():
%       child_elt = child_node.collection_element_name
%     if child_elt:
  if (!${child_elt}Nodes.empty()) {
    if (deferred) {
      Layout[${idx}] = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${child_node.syntax_kind},
                          ${child_elt}Nodes, SPCtx);
    } else {
      Layout[${idx}] = Rec.recordRawSyntax(SyntaxKind::${child_node.syntax_kind}, ${child_elt}Nodes);
    }
  }
%     end
%     if not child.is_optional:
  if (Layout[${idx}].isNull()) {
%       if child.is_token():
%         token = child.main_token()
%         tok_kind = token.kind if token else "unknown"
    if (deferred) {
      Layout[${idx}] = ParsedRawSyntaxNode::makeDeferredMissing(tok::${tok_kind}, SourceLoc());
    } else {
      Layout[${idx}] = Rec.recordMissingToken(tok::${tok_kind}, SourceLoc());
    }
%       elif child_elt:
    if (deferred) {
      Layout[${idx}] = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${child_node.syntax_kind}, {}, SPCtx);
    } else {
      Layout[${idx}] = Rec.recordRawSyntax(SyntaxKind::${child_node.syntax_kind}, {});
    }
%       else:
    llvm_unreachable("need missing non-token nodes ?");
%       end
  }
%     end
%   end
% end
}

%   end
% end
