%{ from gyb_syntax_support import * # -*- mode: C++ -*- # Ignore the following admonition; it applies to the resulting .cpp file only }% //// Automatically Generated From SyntaxFactory.cpp.gyb. //// Do Not Edit Directly! //===--------- SyntaxFactory.cpp - Syntax Factory implementations ---------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// // // This file defines the SyntaxFactory, one of the most important client-facing // types in lib/Syntax and likely to be very commonly used. // // Effectively a namespace, SyntaxFactory is never instantiated, but is *the* // one-stop shop for making new Syntax nodes. Putting all of these into a // collection of static methods provides a single point of API lookup for // clients' convenience and also allows the library to hide all of the // constructors for all Syntax nodes, as the SyntaxFactory is friend to all. // //===----------------------------------------------------------------------===// #include "swift/Syntax/SyntaxFactory.h" #include "swift/Syntax/SyntaxNodes.h" #include "swift/Syntax/Trivia.h" #include "llvm/ADT/ArrayRef.h" #include using namespace swift; using namespace swift::syntax; TokenSyntax SyntaxFactory::makeToken(tok Kind, OwnedString Text, SourcePresence Presence, const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return make(RawTokenSyntax::make(Kind, Text, Presence, LeadingTrivia, TrailingTrivia)); } UnknownSyntax SyntaxFactory::makeUnknownSyntax(llvm::ArrayRef Tokens) { RawSyntax::LayoutList Layout; for (auto &Token : Tokens) { Layout.push_back(Token.getRaw()); } auto Raw = RawSyntax::make(SyntaxKind::Unknown, Layout, SourcePresence::Present); return make(Raw); } Syntax SyntaxFactory::makeBlankCollectionSyntax(SyntaxKind Kind) { switch(Kind) { % for node in SYNTAX_NODES: % if node.is_syntax_collection(): case SyntaxKind::${node.syntax_kind}: return makeBlank${node.syntax_kind}(); % end % end default: break; } llvm_unreachable("not collection kind."); } std::pair SyntaxFactory::countChildren(SyntaxKind Kind){ switch(Kind) { % for node in SYNTAX_NODES: % if not node.is_syntax_collection(): case SyntaxKind::${node.syntax_kind}: % child_count = len(node.children) % non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.children) return {${non_optional_child_count}, ${child_count}}; % end % end default: llvm_unreachable("bad syntax kind."); } } bool SyntaxFactory:: canServeAsCollectionMember(SyntaxKind CollectionKind, Syntax Member) { switch (CollectionKind) { % for node in SYNTAX_NODES: % if node.is_syntax_collection(): case SyntaxKind::${node.syntax_kind}: { return Member.is<${node.collection_element_type}>(); } % end % end default: llvm_unreachable("Not collection kind."); } } Optional SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef Elements) { switch(Kind) { % for node in SYNTAX_NODES: case SyntaxKind::${node.syntax_kind}: { % if node.children: % child_count = len(node.children) static std::pair> ChildrenConditions[${child_count}] = { % for child in node.children: % if child.is_optional: % option = "true" % else: % option = "false" % if child.token_choices: { ${option}, [](const Syntax &S) { // check ${child.name}. if (auto Tok = S.getAs()) { auto Kind = Tok->getTokenKind(); % tok_checks = [] % for choice in child.token_choices: % tok_checks.append("Kind == tok::%s" % choice.kind) % end % all_checks = ' || '.join(tok_checks) return ${all_checks}; } return false; } }, % elif child.text_choices: { ${option}, [](const Syntax &S) { // check ${child.name}. if (auto Tok = S.getAs()) { auto Text = Tok->getText(); % tok_checks = [] % for choice in child.text_choices: % tok_checks.append("Text == \"%s\"" % choice) % end % all_checks = ' || '.join(tok_checks) return ${all_checks}; } return false; } }, % else: { ${option}, [](const Syntax &S) { // check ${child.name}. return S.getAs<${child.type_name}>().hasValue(); } }, % end % end }; Optional Parameters[${child_count}]; unsigned CurCond = 0; for (unsigned I = 0, N = Elements.size(); I < N; ) { // We should use all elements. if (CurCond == ${child_count}) { return None; } if (ChildrenConditions[CurCond].second(Elements[I])) { // we find a node that satisfies the condition. Parameters[CurCond].emplace(Elements[I]); CurCond ++; I ++; } else if (ChildrenConditions[CurCond].first) { // If the unsatisfied condition is optional, move on to the next condition. CurCond ++; } else { // Mandatory condition is not satisfied. return None; } } for (; CurCond < ${child_count}; CurCond ++) { if (!ChildrenConditions[CurCond].first) { // if the remaining condition is mandatory, we cannot create. return None; } } assert(CurCond == ${child_count}); return make${node.syntax_kind}( % params = [] % for i, child in enumerate(node.children): % child = node.children[i] % if child.is_optional: % params.append("/*Optional %s*/ Parameters[%s].hasValue() ?" \ % "(*Parameters[%s]).getAs<%s>().getValue() : (Optional<%s>) None" % % (child.name, i, i, child.type_name, child.type_name)) % else: % params.append("/*%s*/ (*Parameters[%s]).getAs<%s>().getValue()" % % (child.name, i, child.type_name)) % end % end % child_parms = '\n, '.join(params) ${child_parms} ); % elif node.is_syntax_collection(): std::vector<${node.collection_element_type}> Parts; for (auto &E: Elements) { if (auto P = E.getAs<${node.collection_element_type}>()) { Parts.emplace_back(make<${node.collection_element_type}>(P->getRaw())); } else { return None; } } return make${node.syntax_kind}(Parts); % else: return None; % end } % end default: return None; } } % for node in SYNTAX_NODES: % if node.children: % child_params = [] % for child in node.children: % param_type = child.type_name % if child.is_optional: % param_type = "llvm::Optional<%s>" % param_type % child_params.append("%s %s" % (param_type, child.name)) % child_params = ', '.join(child_params) ${node.name} SyntaxFactory::make${node.syntax_kind}(${child_params}) { auto Raw = RawSyntax::make(SyntaxKind::${node.syntax_kind}, { % for child in node.children: % if child.is_optional: ${child.name}.hasValue() ? ${child.name}->getRaw() : cast(${make_missing_child(child)}), % else: ${child.name}.getRaw(), % end % end }, SourcePresence::Present); return make<${node.name}>(Raw); } % elif node.is_syntax_collection(): ${node.name} SyntaxFactory::make${node.syntax_kind}( const std::vector<${node.collection_element_type}> &elements) { RawSyntax::LayoutList layout; for (auto &element : elements) { layout.push_back(element.getRaw()); } auto raw = RawSyntax::make(SyntaxKind::${node.syntax_kind}, layout, SourcePresence::Present); return make<${node.name}>(raw); } % end ${node.name} SyntaxFactory::makeBlank${node.syntax_kind}() { auto raw = RawSyntax::make(SyntaxKind::${node.syntax_kind}, { % for child in node.children: ${make_missing_child(child)}, % end }, SourcePresence::Present); return make<${node.name}>(raw); } % end % for token in SYNTAX_TOKENS: % if token.is_keyword: TokenSyntax SyntaxFactory::make${token.name}Keyword(const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeToken(tok::${token.kind}, "${token.text}", SourcePresence::Present, LeadingTrivia, TrailingTrivia); } % elif token.text: TokenSyntax SyntaxFactory::make${token.name}Token(const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeToken(tok::${token.kind}, "${token.text}", SourcePresence::Present, LeadingTrivia, TrailingTrivia); } % else: TokenSyntax SyntaxFactory::make${token.name}(OwnedString Text, const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeToken(tok::${token.kind}, Text, SourcePresence::Present, LeadingTrivia, TrailingTrivia); } % end % end TupleTypeSyntax SyntaxFactory::makeVoidTupleType() { return makeTupleType(makeLeftParenToken({}, {}), makeBlankTupleTypeElementList(), makeRightParenToken({}, {})); } TupleTypeElementSyntax SyntaxFactory::makeTupleTypeElement(llvm::Optional Label, llvm::Optional Colon, TypeSyntax Type, llvm::Optional TrailingComma) { return makeTupleTypeElement(None, Label, None, Colon, Type, None, None, TrailingComma); } TupleTypeElementSyntax SyntaxFactory::makeTupleTypeElement(TypeSyntax Type, llvm::Optional TrailingComma) { return makeTupleTypeElement(None, None, None, None, Type, None, None, TrailingComma); } GenericParameterSyntax SyntaxFactory::makeGenericParameter(TokenSyntax Name, llvm::Optional TrailingComma) { return makeGenericParameter(None, Name, None, None, TrailingComma); } TypeSyntax SyntaxFactory::makeTypeIdentifier(OwnedString TypeName, const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { auto identifier = makeIdentifier(TypeName, LeadingTrivia, TrailingTrivia); return makeSimpleTypeIdentifier(identifier, None); } TypeSyntax SyntaxFactory::makeAnyTypeIdentifier( const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeTypeIdentifier("Any", LeadingTrivia, TrailingTrivia); } TypeSyntax SyntaxFactory::makeSelfTypeIdentifier( const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeTypeIdentifier("Self", LeadingTrivia, TrailingTrivia); } TokenSyntax SyntaxFactory::makeTypeToken( const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeIdentifier("Type", LeadingTrivia, TrailingTrivia); } TokenSyntax SyntaxFactory::makeProtocolToken( const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeIdentifier("Protocol", LeadingTrivia, TrailingTrivia); } TokenSyntax SyntaxFactory::makeEqualityOperator( const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) { return makeToken(tok::oper_binary_spaced, "==", SourcePresence::Present, LeadingTrivia, TrailingTrivia); }