blob: e136e77cfa1a2f62acb31a2f74ce340ed63bb208 [file] [log] [blame]
%{
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<SyntaxClassification>
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:
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;
}