Files
swift-mirror/include/swift/Syntax/StmtSyntax.h
David Farler c958cd65eb [Syntax] Allow UnknownSyntax to have children
This will make it easier to incrementally implement syntax nodes,
while allowing us to embed nodes that we do know about inside ones
that we don't.

https://bugs.swift.org/browse/SR-4062
2017-02-28 14:30:57 -08:00

479 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 {
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