| %{ |
| 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 <vector> |
| |
| using namespace swift; |
| using namespace swift::syntax; |
| |
| TokenSyntax SyntaxFactory::makeToken(tok Kind, OwnedString Text, |
| const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| SourcePresence Presence, |
| RC<SyntaxArena> Arena) { |
| return make<TokenSyntax>(RawSyntax::make(Kind, Text, LeadingTrivia.Pieces, |
| TrailingTrivia.Pieces, Presence, |
| Arena)); |
| } |
| |
| UnknownSyntax |
| SyntaxFactory::makeUnknownSyntax(llvm::ArrayRef<TokenSyntax> Tokens, |
| RC<SyntaxArena> Arena) { |
| std::vector<RC<RawSyntax>> Layout; |
| Layout.reserve(Tokens.size()); |
| for (auto &Token : Tokens) { |
| Layout.push_back(Token.getRaw()); |
| } |
| auto Raw = RawSyntax::make(SyntaxKind::Unknown, Layout, |
| SourcePresence::Present, Arena); |
| return make<UnknownSyntax>(Raw); |
| } |
| |
| Syntax SyntaxFactory::makeBlankCollectionSyntax(SyntaxKind Kind) { |
| switch(Kind) { |
| % for node in SYNTAX_NODES + PARSEONLY_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<unsigned, unsigned> |
| SyntaxFactory::countChildren(SyntaxKind Kind){ |
| switch(Kind) { |
| % for node in SYNTAX_NODES + PARSEONLY_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::canServeAsCollectionMemberRaw(SyntaxKind CollectionKind, |
| SyntaxKind MemberKind) { |
| switch (CollectionKind) { |
| % for node in SYNTAX_NODES + PARSEONLY_NODES: |
| % if node.is_syntax_collection(): |
| case SyntaxKind::${node.syntax_kind}: |
| % if node.collection_element_choices: |
| % element_checks = [] |
| % for choice in node.collection_element_choices: |
| % element_checks.append("" + choice + "Syntax::kindof(MemberKind)") |
| % end |
| return ${' || '.join(element_checks)}; |
| % else: |
| return ${node.collection_element_type}::kindof(MemberKind); |
| % end |
| % end |
| % end |
| default: |
| llvm_unreachable("Not collection kind."); |
| } |
| } |
| |
| bool SyntaxFactory::canServeAsCollectionMemberRaw(SyntaxKind CollectionKind, |
| const RC<RawSyntax> &Member) { |
| return canServeAsCollectionMemberRaw(CollectionKind, Member->getKind()); |
| } |
| |
| bool SyntaxFactory:: |
| canServeAsCollectionMember(SyntaxKind CollectionKind, Syntax Member) { |
| return canServeAsCollectionMemberRaw(CollectionKind, Member.getRaw()); |
| } |
| |
| RC<RawSyntax> SyntaxFactory::createRaw(SyntaxKind Kind, |
| llvm::ArrayRef<RC<RawSyntax>> Elements, |
| RC<SyntaxArena> Arena) { |
| switch (Kind) { |
| % for node in SYNTAX_NODES + PARSEONLY_NODES: |
| case SyntaxKind::${node.syntax_kind}: { |
| % if node.children: |
| % child_count = len(node.children) |
| RC<RawSyntax> Layout[${child_count}]; |
| unsigned I = 0; |
| % for (child_idx, child) in enumerate(node.children): |
| // child[${child_idx}] ${child.name} |
| if (I == Elements.size() || |
| !${check_child_condition_raw(child)}(Elements[I])) { |
| % if child.is_optional: |
| Layout[${child_idx}] = nullptr; |
| % else: |
| return nullptr; |
| % end |
| } else { |
| Layout[${child_idx}] = Elements[I]; |
| ++I; |
| } |
| % end |
| if (I != Elements.size()) |
| return nullptr; |
| return RawSyntax::make(Kind, Layout, SourcePresence::Present, Arena); |
| % elif node.is_syntax_collection(): |
| for (auto &E : Elements) { |
| if (!canServeAsCollectionMemberRaw(SyntaxKind::${node.syntax_kind}, E)) |
| return nullptr; |
| } |
| return RawSyntax::make(Kind, Elements, SourcePresence::Present, Arena); |
| % else: |
| return nullptr; |
| % end |
| } |
| % end |
| default: |
| return nullptr; |
| } |
| } |
| |
| Optional<Syntax> SyntaxFactory::createSyntax(SyntaxKind Kind, |
| llvm::ArrayRef<Syntax> Elements, |
| RC<SyntaxArena> Arena) { |
| std::vector<RC<RawSyntax>> Layout; |
| Layout.reserve(Elements.size()); |
| for (auto &E : Elements) |
| Layout.emplace_back(E.getRaw()); |
| |
| if (auto Raw = createRaw(Kind, Layout, Arena)) |
| return make<Syntax>(Raw); |
| else |
| return None; |
| } |
| |
| % for node in SYNTAX_NODES + PARSEONLY_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}, |
| RC<SyntaxArena> Arena) { |
| auto Raw = RawSyntax::make(SyntaxKind::${node.syntax_kind}, { |
| % for child in node.children: |
| % if child.is_optional: |
| ${child.name}.hasValue() ? ${child.name}->getRaw() : nullptr, |
| % else: |
| ${child.name}.getRaw(), |
| % end |
| % end |
| }, SourcePresence::Present, Arena); |
| 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, |
| RC<SyntaxArena> Arena) { |
| std::vector<RC<RawSyntax>> layout; |
| layout.reserve(elements.size()); |
| for (auto &element : elements) { |
| layout.push_back(element.getRaw()); |
| } |
| auto raw = RawSyntax::make(SyntaxKind::${node.syntax_kind}, |
| layout, SourcePresence::Present, Arena); |
| return make<${node.name}>(raw); |
| } |
| % end |
| |
| ${node.name} |
| SyntaxFactory::makeBlank${node.syntax_kind}(RC<SyntaxArena> Arena) { |
| auto raw = RawSyntax::make(SyntaxKind::${node.syntax_kind}, { |
| % for child in node.children: |
| % if child.is_optional: |
| nullptr, |
| % else: |
| ${make_missing_child(child)}, |
| % end |
| % end |
| }, SourcePresence::Present, Arena); |
| 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, |
| RC<SyntaxArena> Arena) { |
| return makeToken(tok::${token.kind}, |
| OwnedString::makeUnowned("${token.text}"), |
| LeadingTrivia, TrailingTrivia, |
| SourcePresence::Present, Arena); |
| } |
| % elif token.text: |
| TokenSyntax |
| SyntaxFactory::make${token.name}Token(const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeToken(tok::${token.kind}, |
| OwnedString::makeUnowned("${token.text}"), |
| LeadingTrivia, TrailingTrivia, |
| SourcePresence::Present, Arena); |
| } |
| % else: |
| TokenSyntax |
| SyntaxFactory::make${token.name}(OwnedString Text, |
| const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeToken(tok::${token.kind}, Text, |
| LeadingTrivia, TrailingTrivia, |
| SourcePresence::Present, Arena); |
| } |
| % end |
| % end |
| |
| TupleTypeSyntax SyntaxFactory::makeVoidTupleType(RC<SyntaxArena> Arena) { |
| return makeTupleType(makeLeftParenToken({}, {}, Arena), |
| makeBlankTupleTypeElementList(Arena), |
| makeRightParenToken({}, {}, Arena), |
| Arena); |
| } |
| |
| TupleTypeElementSyntax |
| SyntaxFactory::makeTupleTypeElement(llvm::Optional<TokenSyntax> Label, |
| llvm::Optional<TokenSyntax> Colon, |
| TypeSyntax Type, |
| llvm::Optional<TokenSyntax> TrailingComma, |
| RC<SyntaxArena> Arena) { |
| return makeTupleTypeElement(None, Label, None, Colon, Type, None, None, |
| TrailingComma, Arena); |
| } |
| |
| TupleTypeElementSyntax |
| SyntaxFactory::makeTupleTypeElement(TypeSyntax Type, |
| llvm::Optional<TokenSyntax> TrailingComma, |
| RC<SyntaxArena> Arena) { |
| return makeTupleTypeElement(None, None, None, None, Type, None, None, |
| TrailingComma, Arena); |
| } |
| |
| GenericParameterSyntax |
| SyntaxFactory::makeGenericParameter(TokenSyntax Name, |
| llvm::Optional<TokenSyntax> TrailingComma, |
| RC<SyntaxArena> Arena) { |
| return makeGenericParameter(None, Name, None, None, TrailingComma, Arena); |
| } |
| |
| TypeSyntax SyntaxFactory::makeTypeIdentifier(OwnedString TypeName, |
| const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| auto identifier = |
| makeIdentifier(TypeName, LeadingTrivia, TrailingTrivia, Arena); |
| return makeSimpleTypeIdentifier(identifier, None, Arena); |
| } |
| |
| TypeSyntax SyntaxFactory::makeAnyTypeIdentifier(const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeTypeIdentifier(OwnedString::makeUnowned("Any"), LeadingTrivia, |
| TrailingTrivia, Arena); |
| } |
| |
| TypeSyntax SyntaxFactory::makeSelfTypeIdentifier(const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeTypeIdentifier(OwnedString::makeUnowned("Self"), |
| LeadingTrivia, TrailingTrivia, Arena); |
| } |
| |
| TokenSyntax SyntaxFactory::makeTypeToken(const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeIdentifier(OwnedString::makeUnowned("Type"), |
| LeadingTrivia, TrailingTrivia, Arena); |
| } |
| |
| TokenSyntax SyntaxFactory::makeProtocolToken(const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeIdentifier(OwnedString::makeUnowned("Protocol"), |
| LeadingTrivia, TrailingTrivia, Arena); |
| } |
| |
| TokenSyntax SyntaxFactory::makeEqualityOperator(const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia, |
| RC<SyntaxArena> Arena) { |
| return makeToken(tok::oper_binary_spaced, OwnedString::makeUnowned("=="), |
| LeadingTrivia, TrailingTrivia, SourcePresence::Present, |
| Arena); |
| } |