mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
457 lines
14 KiB
C++
457 lines
14 KiB
C++
//===--- StmtSyntax.h - Swift Statement Syntax Interface --------*- C++ -*-===//
|
|
//
|
|
// 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 interface for statement-specific syntax nodes,
|
|
// such as for if- and while- statements.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SYNTAX_STMTSYNTAX_H
|
|
#define SWIFT_SYNTAX_STMTSYNTAX_H
|
|
|
|
#include "swift/Syntax/RawSyntax.h"
|
|
#include "swift/Syntax/References.h"
|
|
#include "swift/Syntax/Syntax.h"
|
|
#include "swift/Syntax/SyntaxData.h"
|
|
#include "swift/Syntax/UnknownSyntax.h"
|
|
|
|
using llvm::Optional;
|
|
|
|
namespace swift {
|
|
namespace syntax {
|
|
|
|
class ExprSyntax;
|
|
class ExprSyntaxData;
|
|
|
|
#pragma mark - statement Data
|
|
|
|
class StmtSyntaxData : public SyntaxData {
|
|
protected:
|
|
StmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0)
|
|
: SyntaxData(Raw, Parent, IndexInParent) {}
|
|
public:
|
|
static bool classof(const SyntaxData *S) {
|
|
return S->isStmt();
|
|
}
|
|
};
|
|
|
|
#pragma mark - statement API
|
|
|
|
/// statement -> expression ';'?
|
|
/// | declaration ';'?
|
|
/// | loop-statement ';'?
|
|
/// | branch-statement ';'?
|
|
/// | labeled-statement ';'?
|
|
/// | control-transfer-statement ';'?
|
|
/// | defer-statement ';'?
|
|
/// | do-statement ';'?
|
|
/// | compiler-control-statement ';'?
|
|
class StmtSyntax : public Syntax {
|
|
friend class Syntax;
|
|
protected:
|
|
StmtSyntax(const RC<SyntaxData> Root, const StmtSyntaxData *Data);
|
|
public:
|
|
using DataType = StmtSyntaxData;
|
|
static bool classof(const Syntax *S) {
|
|
return S->isStmt();
|
|
}
|
|
};
|
|
|
|
#pragma mark - unknown-statement Data
|
|
|
|
class UnknownStmtSyntaxData : public UnknownSyntaxData {
|
|
UnknownStmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
public:
|
|
static RC<UnknownStmtSyntaxData> make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
|
|
static bool classof(const SyntaxData *S) {
|
|
return S->getKind() == SyntaxKind::UnknownStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark - unknown-statement API
|
|
|
|
class UnknownStmtSyntax : public UnknownSyntax {
|
|
friend class SyntaxData;
|
|
friend class UnknownStmtSyntaxData;
|
|
friend class LegacyASTTransformer;
|
|
|
|
using DataType = UnknownStmtSyntaxData;
|
|
|
|
UnknownStmtSyntax(const RC<SyntaxData> Root,
|
|
const UnknownStmtSyntaxData *Data);
|
|
|
|
public:
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::UnknownStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark -
|
|
#pragma mark code-block Data
|
|
|
|
class CodeBlockStmtSyntaxData final : public StmtSyntaxData {
|
|
friend class SyntaxData;
|
|
friend class CodeBlockStmtSyntax;
|
|
friend struct SyntaxFactory;
|
|
|
|
CodeBlockStmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<CodeBlockStmtSyntaxData> make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<CodeBlockStmtSyntaxData> makeBlank();
|
|
public:
|
|
static bool classof(const SyntaxData *SD) {
|
|
return SD->getKind() == SyntaxKind::CodeBlockStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark -
|
|
#pragma mark code-block API
|
|
|
|
/// code-block -> '{' statements? '}'
|
|
class CodeBlockStmtSyntax : public StmtSyntax {
|
|
enum class Cursor {
|
|
LeftBrace,
|
|
Elements,
|
|
RightBrace,
|
|
};
|
|
friend struct SyntaxFactory;
|
|
friend class CodeBlockStmtSyntaxData;
|
|
friend class FunctionDeclSyntax;
|
|
|
|
CodeBlockStmtSyntax(const RC<SyntaxData> Root, CodeBlockStmtSyntaxData *Data);
|
|
|
|
public:
|
|
/// Returns the left brace of the code block.
|
|
RC<TokenSyntax> getLeftBraceToken() const;
|
|
|
|
/// Returns a new `CodeBlockSyntax` with the specified left brace token.
|
|
CodeBlockStmtSyntax withLeftBraceToken(RC<TokenSyntax> NewLeftBrace) const;
|
|
|
|
/// Return the n-th element in the code block.
|
|
Syntax getElement(size_t n) const;
|
|
|
|
/// Return a new `CodeBlockSyntax` with the added statement at the end,
|
|
/// before the right brace token.
|
|
CodeBlockStmtSyntax withAddedElement(Syntax AdditionalElement) const;
|
|
|
|
/// Returns a new `CodeBlockSyntax` with `NewElements` substituted into
|
|
/// the body.
|
|
CodeBlockStmtSyntax
|
|
withElements(const std::vector<Syntax> NewElements) const;
|
|
|
|
/// Returns the right brace of the code block.
|
|
RC<TokenSyntax> getRightBraceToken() const;
|
|
|
|
/// Returns a new `CodeBlockSyntax` with the specified right brace token.
|
|
CodeBlockStmtSyntax withRightBraceToken(RC<TokenSyntax> NewRightBraces) const;
|
|
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::CodeBlockStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark -
|
|
#pragma mark statements Data
|
|
|
|
using StmtListSyntaxData =
|
|
SyntaxCollectionData<SyntaxKind::StmtList, StmtSyntax>;
|
|
|
|
#pragma mark -
|
|
#pragma mark statements API
|
|
|
|
/// statements -> statement
|
|
/// | statement statements
|
|
class StmtListSyntax final
|
|
: public SyntaxCollection<SyntaxKind::StmtList, StmtSyntax> {
|
|
friend struct SyntaxFactory;
|
|
friend class Syntax;
|
|
friend class SyntaxData;
|
|
friend class FunctionDeclSyntax;
|
|
|
|
using DataType = StmtListSyntaxData;
|
|
|
|
StmtListSyntax(const RC<SyntaxData> Root, const DataType *Data)
|
|
: SyntaxCollection(Root, Data) {}
|
|
|
|
public:
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::StmtList;
|
|
}
|
|
};
|
|
|
|
#pragma mark -
|
|
#pragma mark fallthrough-statement Data
|
|
|
|
class FallthroughStmtSyntaxData final : public StmtSyntaxData {
|
|
friend class SyntaxData;
|
|
friend class FallthroughStmtSyntax;
|
|
friend struct SyntaxFactory;
|
|
|
|
FallthroughStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<FallthroughStmtSyntaxData> make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<FallthroughStmtSyntaxData> makeBlank();
|
|
|
|
public:
|
|
static bool classof(const SyntaxData *SD) {
|
|
return SD->getKind() == SyntaxKind::FallthroughStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark -
|
|
#pragma mark fallthrough-statement API
|
|
|
|
/// fallthrough-statement -> 'fallthrough'
|
|
class FallthroughStmtSyntax : public StmtSyntax {
|
|
friend struct SyntaxFactory;
|
|
friend class SyntaxData;
|
|
friend class FallthroughStmtSyntaxData;
|
|
|
|
using DataType = FallthroughStmtSyntaxData;
|
|
|
|
enum class Cursor : CursorIndex {
|
|
FallthroughKeyword,
|
|
};
|
|
|
|
FallthroughStmtSyntax(const RC<SyntaxData> Root,
|
|
const FallthroughStmtSyntaxData *Data);
|
|
|
|
static FallthroughStmtSyntax make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static FallthroughStmtSyntax makeBlank();
|
|
|
|
public:
|
|
|
|
/// Get the 'fallthrough' keyword associated comprising this
|
|
/// fallthrough statement.
|
|
RC<TokenSyntax> getFallthroughKeyword() const;
|
|
|
|
/// Return a new FallthroughStmtSyntax with the given fallthrough
|
|
/// keyword.
|
|
FallthroughStmtSyntax
|
|
withFallthroughKeyword(RC<TokenSyntax> NewFallthroughKeyword) const;
|
|
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::FallthroughStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark - break-statement Data
|
|
|
|
class BreakStmtSyntaxData : public StmtSyntaxData {
|
|
friend class SyntaxData;
|
|
friend class BreakStmtSyntax;
|
|
friend struct SyntaxFactory;
|
|
BreakStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<BreakStmtSyntaxData> make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<BreakStmtSyntaxData> makeBlank();
|
|
|
|
public:
|
|
static bool classof(const SyntaxData *SD) {
|
|
return SD->getKind() == SyntaxKind::BreakStmt;
|
|
}
|
|
|
|
};
|
|
|
|
#pragma mark - break-statement API
|
|
|
|
/// break-statement -> 'break' label-name?
|
|
/// label-name -> identifier
|
|
class BreakStmtSyntax : public StmtSyntax {
|
|
friend struct SyntaxFactory;
|
|
friend class BreakStmtSyntaxData;
|
|
friend class SyntaxData;
|
|
|
|
using DataType = BreakStmtSyntaxData;
|
|
|
|
enum class Cursor : CursorIndex {
|
|
BreakKeyword,
|
|
Label
|
|
};
|
|
|
|
BreakStmtSyntax(const RC<SyntaxData> Root,
|
|
BreakStmtSyntaxData *Data);
|
|
|
|
static BreakStmtSyntax make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static BreakStmtSyntax makeBlank();
|
|
public:
|
|
|
|
/// Return the 'break' keyword associated with this break statement.
|
|
RC<TokenSyntax> getBreakKeyword() const;
|
|
|
|
/// Return a new `BreakStmtSyntax` with the given 'break' keyword.
|
|
BreakStmtSyntax withBreakKeyword(RC<TokenSyntax> NewBreakKeyword) const;
|
|
|
|
/// Return the destination label of this break statement. If it doesn't
|
|
/// have one, the token is marked as missing.
|
|
RC<TokenSyntax> getLabel() const;
|
|
|
|
/// Return a new `BreakStmtSyntax` with the given destination label.
|
|
BreakStmtSyntax withLabel(RC<TokenSyntax> NewLabel) const;
|
|
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::BreakStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark - continue-statement Data
|
|
|
|
class ContinueStmtSyntaxData : public StmtSyntaxData {
|
|
friend class SyntaxData;
|
|
friend class ContinueStmtSyntax;
|
|
friend struct SyntaxFactory;
|
|
ContinueStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<ContinueStmtSyntaxData> make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<ContinueStmtSyntaxData> makeBlank();
|
|
|
|
public:
|
|
static bool classof(const SyntaxData *SD) {
|
|
return SD->getKind() == SyntaxKind::ContinueStmt;
|
|
}
|
|
|
|
};
|
|
|
|
#pragma mark - continue-statement API
|
|
|
|
/// continue-statement -> 'continue' label-name?
|
|
/// label-name -> identifier
|
|
class ContinueStmtSyntax : public StmtSyntax {
|
|
friend struct SyntaxFactory;
|
|
friend class ContinueStmtSyntaxData;
|
|
friend class SyntaxData;
|
|
|
|
using DataType = ContinueStmtSyntaxData;
|
|
|
|
enum class Cursor : CursorIndex {
|
|
ContinueKeyword,
|
|
Label
|
|
};
|
|
|
|
ContinueStmtSyntax(const RC<SyntaxData> Root,
|
|
ContinueStmtSyntaxData *Data);
|
|
|
|
static ContinueStmtSyntax make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static ContinueStmtSyntax makeBlank();
|
|
public:
|
|
|
|
/// Return the 'continue' keyword associated with this continue statement.
|
|
RC<TokenSyntax> getContinueKeyword() const;
|
|
|
|
/// Return a new `ContinueStmtSyntax` with the given 'continue' keyword.
|
|
ContinueStmtSyntax withContinueKeyword(RC<TokenSyntax> NewBreakKeyword) const;
|
|
|
|
/// Return the destination label of this break statement. If it doesn't
|
|
/// have one, the token is marked as continue.
|
|
RC<TokenSyntax> getLabel() const;
|
|
|
|
/// Return a new `ContinueStmtSyntax` with the given destination label.
|
|
ContinueStmtSyntax withLabel(RC<TokenSyntax> NewLabel) const;
|
|
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::ContinueStmt;
|
|
}
|
|
};
|
|
|
|
#pragma mark - return-statement Data
|
|
|
|
class ReturnStmtSyntaxData : public StmtSyntaxData {
|
|
friend class SyntaxData;
|
|
friend class ReturnStmtSyntax;
|
|
friend struct SyntaxFactory;
|
|
|
|
RC<ExprSyntaxData> CachedExpression;
|
|
|
|
ReturnStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<ReturnStmtSyntaxData> make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static RC<ReturnStmtSyntaxData> makeBlank();
|
|
|
|
public:
|
|
static bool classof(const SyntaxData *SD) {
|
|
return SD->getKind() == SyntaxKind::ReturnStmt;
|
|
}
|
|
|
|
};
|
|
|
|
#pragma mark - return-statement API
|
|
|
|
/// return-statement -> 'return' expression? ';'?
|
|
class ReturnStmtSyntax : public StmtSyntax {
|
|
friend struct SyntaxFactory;
|
|
friend class ReturnStmtSyntaxData;
|
|
friend class SyntaxData;
|
|
friend class Syntax;
|
|
|
|
using DataType = ReturnStmtSyntaxData;
|
|
|
|
enum class Cursor : CursorIndex {
|
|
ReturnKeyword,
|
|
Expression
|
|
};
|
|
|
|
ReturnStmtSyntax(const RC<SyntaxData> Root,
|
|
const ReturnStmtSyntaxData *Data);
|
|
|
|
static ReturnStmtSyntax make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent = nullptr,
|
|
CursorIndex IndexInParent = 0);
|
|
static ReturnStmtSyntax makeBlank();
|
|
public:
|
|
|
|
/// Return the 'return' keyword associated with this return statement.
|
|
RC<TokenSyntax> getReturnKeyword() const;
|
|
|
|
/// Return a new `ReturnStmtSyntax` with the given 'return' keyword.
|
|
ReturnStmtSyntax withReturnKeyword(RC<TokenSyntax> NewReturnKeyword) const;
|
|
|
|
/// Return the expression of this return statement.
|
|
Optional<ExprSyntax> getExpression() const;
|
|
|
|
/// Return a new `ReturnStmtSyntax` with the given destination label.
|
|
ReturnStmtSyntax withExpression(ExprSyntax NewExpression) const;
|
|
|
|
static bool classof(const Syntax *S) {
|
|
return S->getKind() == SyntaxKind::ReturnStmt;
|
|
}
|
|
};
|
|
|
|
} // end namespace syntax
|
|
} // end namespace swift
|
|
|
|
#endif
|