blob: d4c93a5716ae039203d1e898029227f6cabf87db [file] [log] [blame]
//===--- 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 {
protected:
StmtSyntax(const RC<SyntaxData> Root, const StmtSyntaxData *Data);
public:
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;
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
class StmtListSyntaxData final : public StmtSyntaxData {
friend class SyntaxData;
friend class StmtListSyntax;
friend class StmtListSyntaxBuilder;
StmtListSyntaxData(RC<RawSyntax> Raw,
const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0);
static RC<StmtListSyntaxData> make(RC<RawSyntax> Raw,
const SyntaxData *Parent = nullptr,
CursorIndex IndexInParent = 0);
static RC<StmtListSyntaxData> makeBlank();
public:
static bool classof(const SyntaxData *SD) {
return SD->getKind() == SyntaxKind::StmtList;
}
};
#pragma mark -
#pragma mark statements API
/// statements -> statement
/// | statement statements
class StmtListSyntax final : public Syntax {
friend struct SyntaxFactory;
friend class StmtListSyntaxBuilder;
friend class SyntaxData;
using DataType = StmtListSyntaxData;
StmtListSyntax(const RC<SyntaxData> Root, const StmtListSyntaxData *Data);
public:
/// Returns a new statement list with an additional statement.
StmtListSyntax withAddedStatement(Syntax AdditionalStatement) const;
static bool classof(const Syntax *S) {
return S->getKind() == SyntaxKind::StmtList;
}
};
#pragma mark -
#pragma mark statements Builder
class StmtListSyntaxBuilder final {
RawSyntax::LayoutList StmtListLayout;
public:
StmtListSyntaxBuilder &addStatement(Syntax Statement);
StmtListSyntax build() const;
};
#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