| %{ |
| 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, SourcePresence Presence, |
| const Trivia &LeadingTrivia, |
| const Trivia &TrailingTrivia) { |
| return make<TokenSyntax>(RawTokenSyntax::make(Kind, Text, Presence, |
| LeadingTrivia, TrailingTrivia)); |
| } |
| |
| UnknownSyntax |
| SyntaxFactory::makeUnknownSyntax(llvm::ArrayRef<TokenSyntax> Tokens) { |
| RawSyntax::LayoutList Layout; |
| for (auto &Token : Tokens) { |
| Layout.push_back(Token.getRaw()); |
| } |
| auto Raw = RawSyntax::make(SyntaxKind::Unknown, Layout, |
| SourcePresence::Present); |
| return make<UnknownSyntax>(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<unsigned, unsigned> |
| 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<Syntax> |
| SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements) { |
| switch(Kind) { |
| % for node in SYNTAX_NODES: |
| case SyntaxKind::${node.syntax_kind}: { |
| % if node.children: |
| % child_count = len(node.children) |
| static std::pair<bool, std::function<bool(const Syntax&)>> |
| 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<TokenSyntax>()) { |
| 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; |
| } |
| }, |
| % else: |
| { ${option}, |
| [](const Syntax &S) { |
| // check ${child.name}. |
| return S.getAs<${child.type_name}>().hasValue(); |
| } |
| }, |
| % end |
| % end |
| }; |
| Optional<Syntax> 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; |
| } |
| } |
| |
| SyntaxKind |
| SyntaxFactory::getUnknownKind(SyntaxKind Kind) { |
| switch(Kind) { |
| % for node in SYNTAX_NODES: |
| % if node.syntax_kind.endswith('Expr'): |
| % Result = 'SyntaxKind::UnknownExpr' |
| % elif node.syntax_kind.endswith('Stmt'): |
| % Result = 'SyntaxKind::UnknownStmt' |
| % elif node.syntax_kind.endswith('Decl'): |
| % Result = 'SyntaxKind::UnknownDecl' |
| % elif node.syntax_kind.endswith('Token'): |
| % Result = 'SyntaxKind::UnknownToken' |
| % else: |
| % Result = 'SyntaxKind::Unknown' |
| % end |
| case SyntaxKind::${node.syntax_kind}: return ${Result}; |
| % end |
| default: |
| return SyntaxKind::Unknown; |
| } |
| } |
| |
| % 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<RawSyntax>(${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<TokenSyntax> Label, |
| llvm::Optional<TokenSyntax> Colon, TypeSyntax Type, |
| llvm::Optional<TokenSyntax> TrailingComma) { |
| auto annotation = makeTypeAnnotation(makeBlankAttributeList(), None, Type); |
| return makeTupleTypeElement(Label, Colon, annotation, TrailingComma); |
| } |
| |
| TupleTypeElementSyntax SyntaxFactory::makeTupleTypeElement(TypeSyntax Type, |
| llvm::Optional<TokenSyntax> TrailingComma) { |
| return makeTupleTypeElement(None, None, Type, TrailingComma); |
| } |
| |
| GenericParameterSyntax |
| SyntaxFactory::makeGenericParameter(TokenSyntax Name, |
| llvm::Optional<TokenSyntax> 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); |
| } |