//===--- 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 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 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 Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); public: static RC make(RC 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 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 Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC 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 Root, CodeBlockStmtSyntaxData *Data); public: /// Returns the left brace of the code block. RC getLeftBraceToken() const; /// Returns a new `CodeBlockSyntax` with the specified left brace token. CodeBlockStmtSyntax withLeftBraceToken(RC 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 NewElements) const; /// Returns the right brace of the code block. RC getRightBraceToken() const; /// Returns a new `CodeBlockSyntax` with the specified right brace token. CodeBlockStmtSyntax withRightBraceToken(RC NewRightBraces) const; static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::CodeBlockStmt; } }; #pragma mark - #pragma mark statements Data using StmtListSyntaxData = SyntaxCollectionData; #pragma mark - #pragma mark statements API /// statements -> statement /// | statement statements class StmtListSyntax final : public SyntaxCollection { friend struct SyntaxFactory; friend class Syntax; friend class SyntaxData; friend class FunctionDeclSyntax; using DataType = StmtListSyntaxData; StmtListSyntax(const RC 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 Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC 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 Root, const FallthroughStmtSyntaxData *Data); static FallthroughStmtSyntax make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static FallthroughStmtSyntax makeBlank(); public: /// Get the 'fallthrough' keyword associated comprising this /// fallthrough statement. RC getFallthroughKeyword() const; /// Return a new FallthroughStmtSyntax with the given fallthrough /// keyword. FallthroughStmtSyntax withFallthroughKeyword(RC 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 Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC 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 Root, BreakStmtSyntaxData *Data); static BreakStmtSyntax make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static BreakStmtSyntax makeBlank(); public: /// Return the 'break' keyword associated with this break statement. RC getBreakKeyword() const; /// Return a new `BreakStmtSyntax` with the given 'break' keyword. BreakStmtSyntax withBreakKeyword(RC NewBreakKeyword) const; /// Return the destination label of this break statement. If it doesn't /// have one, the token is marked as missing. RC getLabel() const; /// Return a new `BreakStmtSyntax` with the given destination label. BreakStmtSyntax withLabel(RC 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 Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC 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 Root, ContinueStmtSyntaxData *Data); static ContinueStmtSyntax make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static ContinueStmtSyntax makeBlank(); public: /// Return the 'continue' keyword associated with this continue statement. RC getContinueKeyword() const; /// Return a new `ContinueStmtSyntax` with the given 'continue' keyword. ContinueStmtSyntax withContinueKeyword(RC NewBreakKeyword) const; /// Return the destination label of this break statement. If it doesn't /// have one, the token is marked as continue. RC getLabel() const; /// Return a new `ContinueStmtSyntax` with the given destination label. ContinueStmtSyntax withLabel(RC 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 CachedExpression; ReturnStmtSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC 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 Root, const ReturnStmtSyntaxData *Data); static ReturnStmtSyntax make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static ReturnStmtSyntax makeBlank(); public: /// Return the 'return' keyword associated with this return statement. RC getReturnKeyword() const; /// Return a new `ReturnStmtSyntax` with the given 'return' keyword. ReturnStmtSyntax withReturnKeyword(RC NewReturnKeyword) const; /// Return the expression of this return statement. Optional 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