[Syntax] Represent TokenSyntax as a Syntax node (#10606)

Previously, users of TokenSyntax would always deal with RC<TokenSyntax>
which is a subclass of RawSyntax. Instead, provide TokenSyntax as a
fully-realized Syntax node, that will always exist as a leaf in the
Syntax tree.

This hides the implementation detail of RawSyntax and SyntaxData
completely from clients of libSyntax, and paves the way for future
generation of Syntax nodes.
This commit is contained in:
Harlan
2017-06-27 11:08:10 -07:00
committed by GitHub
parent e89e7f58b2
commit 70089a7bcc
34 changed files with 1378 additions and 1340 deletions

View File

@@ -1,4 +1,4 @@
//===--- TokenSyntax.h - Swift Token Interface ------------------*- C++ -*-===//
//===----------- TokenSyntax.h - Swift Token Interface ----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
@@ -10,191 +10,88 @@
//
//===----------------------------------------------------------------------===//
//
// This file contains the interface for a `TokenSyntax`, which is a token that
// includes full-fidelity leading and trailing trivia.
//
// A TokenSyntax is an instance of `RawSyntax`, meaning it is immutable,
// reference counted, and able to be shared.
// This file contains the interface for a `TokenSyntax`, which is a token
// that includes full-fidelity leading and trailing trivia.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SYNTAX_TokenSyntax_H
#define SWIFT_SYNTAX_TokenSyntax_H
#ifndef SWIFT_SYNTAX_TOKENSYNTAX_H
#define SWIFT_SYNTAX_TOKENSYNTAX_H
#include "swift/Syntax/RawSyntax.h"
#include "swift/Syntax/RawTokenSyntax.h"
#include "swift/Syntax/References.h"
#include "swift/Syntax/Syntax.h"
#include "swift/Syntax/TokenKinds.h"
#include "swift/Syntax/Trivia.h"
namespace swift {
namespace syntax {
class AbsolutePosition;
struct TokenSyntax final : public RawSyntax {
friend struct SyntaxFactory;
const tok TokenKind;
const OwnedString Text;
const Trivia LeadingTrivia;
const Trivia TrailingTrivia;
private:
TokenSyntax();
TokenSyntax(tok TokenKind, OwnedString Text, const SourcePresence Presence);
TokenSyntax(tok TokenKind, OwnedString Text, const SourcePresence Presence,
const Trivia &LeadingTrivia, const Trivia &TrailingTrivia);
class TokenSyntax final : public Syntax {
protected:
virtual void validate() const override {
assert(getRaw()->isToken());
}
public:
/// Make a new token.
static RC<TokenSyntax> make(tok TokenKind, OwnedString Text,
const SourcePresence Presence,
const Trivia &LeadingTrivia,
const Trivia &TrailingTrivia) {
return RC<TokenSyntax> {
new TokenSyntax {
TokenKind, Text, Presence,
LeadingTrivia, TrailingTrivia
}
};
TokenSyntax(const RC<SyntaxData> Root, const SyntaxData *Data)
: Syntax(Root, Data) {}
RC<RawTokenSyntax> getRawToken() const {
return cast<RawTokenSyntax>(getRaw());
}
/// Return a token with the specified kind and text, but marked as missing.
static RC<TokenSyntax> missingToken(const tok Kind, OwnedString Text) {
return make(Kind, Text, SourcePresence::Missing, {}, {});
static TokenSyntax missingToken(const tok Kind, OwnedString Text) {
return make<TokenSyntax>(RawTokenSyntax::missingToken(Kind, Text));
}
/// Return a new token like this one, but with the given leading
/// trivia instead.
RC<TokenSyntax> withLeadingTrivia(const Trivia &NewLeadingTrivia) const {
return make(TokenKind, Text, Presence, NewLeadingTrivia, TrailingTrivia);
const Trivia &getLeadingTrivia() const {
return getRawToken()->LeadingTrivia;
}
/// Return a new token like this one, but with the given trailing
/// trivia instead.
RC<TokenSyntax> withTrailingTrivia(const Trivia &NewTrailingTrivia) const {
return make(TokenKind, Text, Presence, LeadingTrivia, NewTrailingTrivia);
const Trivia &getTrailingTrivia() const {
return getRawToken()->TrailingTrivia;
}
/// Returns true if the token is of the expected kind and has the given
/// expected text.
bool is(tok ExpectedKind, StringRef ExpectedText) const {
return getTokenKind() == ExpectedKind && ExpectedText == getText();
TokenSyntax withLeadingTrivia(const Trivia &Trivia) const {
auto NewRaw = getRawToken()->withLeadingTrivia(Trivia);
return Data->replaceSelf<TokenSyntax>(NewRaw);
}
/// Returns the kind of token this is.
tok getTokenKind() const { return TokenKind; }
TokenSyntax withTrailingTrivia(const Trivia &Trivia) const {
auto NewRaw = getRawToken()->withTrailingTrivia(Trivia);
return Data->replaceSelf<TokenSyntax>(NewRaw);
}
/// Returns a reference to the text of this token.
StringRef getText() const { return Text.str(); }
/// True if the token is any keyword.
bool isKeyword() const {
switch (TokenKind) {
#define KEYWORD(X) case tok::kw_##X: return true;
#include "swift/Syntax/TokenKinds.def"
default: return false;
}
return getRawToken()->isKeyword();
}
/// Returns true if the token is any literal.
bool isLiteral() const {
switch(TokenKind) {
case tok::integer_literal:
case tok::floating_literal:
case tok::string_literal:
case tok::pound_fileLiteral:
case tok::pound_colorLiteral:
case tok::pound_imageLiteral:
return true;
default:
return false;
}
bool isMissing() const {
return getRawToken()->isMissing();
}
/// Returns true if this token is of the specified kind.
bool is(tok K) const { return TokenKind == K; }
/// Returns true if this token is not of the specified kind.
bool isNot(tok K) const { return TokenKind != K; }
/// Base case for variadic `isAny`
bool isAny(tok K1) const {
return is(K1);
}
/// Returns true if this token is any of the provided kinds.
template <typename ...T>
bool isAny(tok K1, tok K2, T... K) const {
if (is(K1))
return true;
return isAny(K2, K...);
}
/// Returns true if this token is not any of the provided kinds.
template <typename ...T>
bool isNot(tok K1, T... K) const { return !isAny(K1, K...); }
bool isPunctuation() const {
switch (TokenKind) {
#define PUNCTUATOR(Name, Str) case tok::Name: return true;
#include "swift/Syntax/TokenKinds.def"
default: return false;
}
return getRawToken()->isPunctuation();
}
/// Returns true if this token is a binary operator.
bool isBinaryOperator() const {
return TokenKind == tok::oper_binary_spaced ||
TokenKind == tok::oper_binary_unspaced;
}
/// Returns true if this token is any kind of operator.
bool isOperator() const {
return isBinaryOperator() ||
TokenKind == tok::oper_postfix ||
TokenKind == tok::oper_prefix;
return getRawToken()->isOperator();
}
/// Returns true if this token is not an operator.
bool isNotOperator() const {
return !isOperator();
bool isLiteral() const {
return getRawToken()->isLiteral();
}
/// Print the leading trivia, text, and trailing trivia of this token to
/// the provided output stream.
void print(llvm::raw_ostream &OS, unsigned Indent = 0) const {
for (const auto &Leader : LeadingTrivia) {
Leader.print(OS);
}
if (!isMissing()) {
OS << getText();
}
for (const auto &Trailer : TrailingTrivia) {
Trailer.print(OS);
}
tok getTokenKind() const {
return getRawToken()->getTokenKind();
}
/// Advance the provided AbsolutePosition by the token's full width and
/// return the AbsolutePosition of the start of the token's nontrivial text.
AbsolutePosition accumulateAbsolutePosition(AbsolutePosition &Pos) const;
/// Dump the textual representation of this token's kind.
void dumpKind(llvm::raw_ostream &OS) const;
/// Dump the layout of this token: its leading trivia, kind, text, and
/// trailing trivia.
void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;
static bool classof(const RawSyntax *RS) {
return RS->Kind == SyntaxKind::Token;
StringRef getText() const {
return getRawToken()->getText();
}
};
} // end namespace syntax
} // end namespace swift
#endif // SWIFT_SYNTAX_TokenSyntax_H
#endif // SWIFT_SYNTAX_TOKENSYNTAX_H