%{ from gyb_syntax_support import * # -*- mode: C++ -*- # Ignore the following admonition; it applies to the resulting .cpp file only }% //// Automatically Generated From SyntaxClassifier.cpp.gyb. //// Do Not Edit Directly! //===----- SyntaxClassifier.cpp - Syntax Classifier implementations -------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 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 Syntax Classifier, which walks the syntax tree and // creates a classification table for all tokens in the syntax tree, mapping it // to a \c SyntaxClassification by its ID. // //===----------------------------------------------------------------------===// #include "swift/Basic/EditorPlaceholder.h" #include "swift/Syntax/SyntaxClassifier.h" using namespace swift; using namespace swift::syntax; % for node in SYNTAX_NODES: % if is_visitable(node): void SyntaxClassifier::visit(${node.name} Node) { % if node.is_unknown() or node.is_syntax_collection(): SyntaxVisitor::visit(Node); % else: % for child in node.children: % if child.classification: visit(Node.get${child.name}(), SyntaxClassification::${child.classification}, ${"true" if child.force_classification else "false"}); % else: visit(Node.get${child.name}()); % end % end % end } % end % end /// Returns the SyntaxClassficiation a token node should receive if it is not /// inside a special context. Returns \c None if the token has no context-free /// classification and should always inherit from the context. llvm::Optional getContextFreeClassificationForToken(TokenSyntax TokenNode) { switch (TokenNode.getTokenKind()) { #define KEYWORD(KW) case tok::kw_##KW: return SyntaxClassification::Keyword; #define POUND_KEYWORD(KW) case tok::pound_##KW: return SyntaxClassification::Keyword; #define POUND_OBJECT_LITERAL(KW, desc, proto) case tok::pound_##KW: return SyntaxClassification::ObjectLiteral; #define POUND_DIRECTIVE_KEYWORD(KW) case tok::pound_##KW: return SyntaxClassification::PoundDirectiveKeyword; #define POUND_COND_DIRECTIVE_KEYWORD(KW) case tok::pound_##KW: return SyntaxClassification::BuildConfigKeyword; #include "swift/Syntax/TokenKinds.def" // Punctuators case tok::l_paren: case tok::r_paren: case tok::l_brace: case tok::r_brace: case tok::l_square: case tok::r_square: case tok::l_angle: case tok::r_angle: case tok::period: case tok::period_prefix: case tok::comma: case tok::colon: case tok::semi: case tok::equal: case tok::pound: case tok::amp_prefix: case tok::arrow: case tok::backtick: case tok::backslash: case tok::exclaim_postfix: case tok::question_postfix: case tok::question_infix: case tok::sil_dollar: case tok::sil_exclamation: return SyntaxClassification::None; case tok::string_quote: case tok::multiline_string_quote: return SyntaxClassification::StringLiteral; case tok::at_sign: return SyntaxClassification::Attribute; // Literals case tok::integer_literal: return SyntaxClassification::IntegerLiteral; case tok::floating_literal: return SyntaxClassification::FloatingLiteral; case tok::string_literal: return SyntaxClassification::StringLiteral; // Miscelaneous case tok::identifier: { if (isEditorPlaceholder(TokenNode.getText())) { return SyntaxClassification::EditorPlaceholder; } else { return llvm::None; } } case tok::unknown: if (TokenNode.getText().startswith("\"")) { // Unterminated string literal return SyntaxClassification::StringLiteral; } else { return SyntaxClassification::None; } break; case tok::eof: case tok::code_complete: case tok::oper_binary_unspaced: case tok::oper_binary_spaced: case tok::oper_postfix: case tok::oper_prefix: return SyntaxClassification::None; case tok::dollarident: return SyntaxClassification::DollarIdentifier; case tok::sil_local_name: return SyntaxClassification::None; case tok::comment: llvm_unreachable("Comments should be in trivia"); case tok::contextual_keyword: case tok::kw_yield: return SyntaxClassification::Keyword; case tok::string_segment: return SyntaxClassification::StringLiteral; case tok::string_interpolation_anchor: return SyntaxClassification::StringInterpolationAnchor; case tok::NUM_TOKENS: llvm_unreachable(""); } } void SyntaxClassifier::visit(TokenSyntax TokenNode) { SyntaxClassification Classification = ContextStack.top().Classification; bool ForceClassification = ContextStack.top().ForceClassification; if (!ForceClassification) { auto NativeClassification = getContextFreeClassificationForToken(TokenNode); if (NativeClassification.hasValue()) { Classification = NativeClassification.getValue(); } if (Classification == SyntaxClassification::None && TokenNode.getTokenKind() == tok::identifier) { Classification = SyntaxClassification::Identifier; } } assert(ClassifiedTokens.count(TokenNode.getId()) == 0 && "Token already classified"); ClassifiedTokens[TokenNode.getId()] = Classification; }