| //===--- ExprSyntax.h - Swift Expression 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 expresion-specific syntax nodes, |
| // such as |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SYNTAX_EXPRSYNTAX_H |
| #define SWIFT_SYNTAX_EXPRSYNTAX_H |
| |
| #include "swift/Syntax/RawSyntax.h" |
| #include "swift/Syntax/References.h" |
| #include "swift/Syntax/Syntax.h" |
| #include "swift/Syntax/SyntaxData.h" |
| #include "swift/Syntax/SyntaxCollection.h" |
| #include "swift/Syntax/SyntaxCollectionData.h" |
| #include "swift/Syntax/TokenSyntax.h" |
| #include "swift/Syntax/UnknownSyntax.h" |
| |
| using llvm::Optional; |
| |
| namespace swift { |
| namespace syntax { |
| |
| class GenericArgumentClauseSyntax; |
| class GenericArgumentClauseSyntaxData; |
| |
| class ExprSyntaxData : public SyntaxData { |
| protected: |
| ExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0) |
| : SyntaxData(Raw, Parent, IndexInParent) { |
| assert(Raw->isExpr()); |
| } |
| public: |
| static RC<ExprSyntaxData> make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| static RC<ExprSyntaxData> makeBlank(); |
| static bool classof(const SyntaxData *S) { |
| return S->isExpr(); |
| } |
| }; |
| |
| class ExprSyntax : public Syntax { |
| friend class FunctionParameterSyntax; |
| public: |
| using DataType = ExprSyntaxData; |
| |
| ExprSyntax(const RC<SyntaxData> Root, const ExprSyntaxData *Data); |
| static bool classof(const Syntax *S) { |
| return S->isExpr(); |
| } |
| }; |
| |
| #pragma mark - unknown-expression Data |
| |
| class UnknownExprSyntaxData : public UnknownSyntaxData { |
| UnknownExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| public: |
| static RC<UnknownExprSyntaxData> make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static bool classof(const SyntaxData *S) { |
| return S->getKind() == SyntaxKind::UnknownExpr; |
| } |
| }; |
| |
| #pragma mark - unknown-expression API |
| |
| class UnknownExprSyntax : public UnknownSyntax { |
| friend class SyntaxData; |
| friend class UnknownExprSyntaxData; |
| friend class LegacyASTTransformer; |
| |
| using DataType = UnknownExprSyntaxData; |
| |
| public: |
| UnknownExprSyntax(const RC<SyntaxData> Root, |
| const UnknownExprSyntaxData *Data); |
| |
| static bool classof(const Syntax *S) { |
| return S->getKind() == SyntaxKind::UnknownExpr; |
| } |
| }; |
| |
| #pragma mark - integer-literal-expression Data |
| |
| class IntegerLiteralExprSyntaxData : public ExprSyntaxData { |
| friend struct SyntaxFactory; |
| friend class SyntaxData; |
| |
| IntegerLiteralExprSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| static RC<IntegerLiteralExprSyntaxData> make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| static RC<IntegerLiteralExprSyntaxData> makeBlank(); |
| public: |
| static bool classof(const SyntaxData *S) { |
| return S->getKind() == SyntaxKind::IntegerLiteralExpr; |
| } |
| }; |
| |
| #pragma mark - integer-literal-expression API |
| |
| class IntegerLiteralExprSyntax : public ExprSyntax { |
| using DataType = IntegerLiteralExprSyntaxData; |
| friend struct SyntaxFactory; |
| friend class SyntaxData; |
| friend class IntegerLiteralExprSyntaxData; |
| |
| IntegerLiteralExprSyntax(const RC<SyntaxData> Root, |
| const IntegerLiteralExprSyntaxData *Data); |
| |
| enum class Cursor : CursorIndex { |
| Sign, |
| Digits |
| }; |
| |
| public: |
| |
| /// Get the '+' or '-' associated with this integer literal expression. |
| RC<TokenSyntax> getSign() const; |
| |
| /// Return a new IntegerLiteralExprSyntax with the given '+' or '-' sign. |
| IntegerLiteralExprSyntax withSign(RC<TokenSyntax> NewSign) const; |
| |
| /// Return the string of digits comprising the number part of the integer |
| /// literal expression. |
| RC<TokenSyntax> getDigits() const; |
| |
| /// Return a new IntegerLiteralExprSyntax with the given string of digits. |
| IntegerLiteralExprSyntax withDigits(RC<TokenSyntax> NewDigits) const; |
| |
| static bool classof(const Syntax *S) { |
| return S->getKind() == SyntaxKind::IntegerLiteralExpr; |
| } |
| }; |
| |
| #pragma mark - symbolic-reference Data |
| |
| class SymbolicReferenceExprSyntaxData : public ExprSyntaxData { |
| friend class SymbolicReferenceExprSyntax; |
| friend class SyntaxData; |
| friend struct SyntaxFactory; |
| |
| RC<GenericArgumentClauseSyntaxData> CachedGenericArgClause; |
| |
| SymbolicReferenceExprSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static RC<SymbolicReferenceExprSyntaxData> |
| make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static RC<SymbolicReferenceExprSyntaxData> makeBlank(); |
| |
| public: |
| static bool classof(const SyntaxData *S) { |
| return S->getKind() == SyntaxKind::SymbolicReferenceExpr; |
| } |
| }; |
| |
| #pragma mark - symbolic-reference API |
| |
| /// symbolic-reference-expression -> identifier generic-argument-clause? |
| /// |
| /// This is shown as primary-expression -> identifier generic-argument-clause? |
| /// in the grammar. It can be just an identifier referring to some |
| /// declaration, or it could perhaps be a constructor call to `Array<Int>`. |
| class SymbolicReferenceExprSyntax : public ExprSyntax { |
| |
| using DataType = SymbolicReferenceExprSyntaxData; |
| |
| friend struct SyntaxFactory; |
| friend class SyntaxData; |
| friend class Syntax; |
| friend class SymbolicReferenceExprSyntaxData; |
| |
| enum class Cursor : CursorIndex { |
| Identifier, |
| GenericArgumentClause |
| }; |
| |
| SymbolicReferenceExprSyntax(const RC<SyntaxData> Root, |
| const DataType *Data); |
| |
| public: |
| |
| /// Get the identifier for the symbol to which this expression refers. |
| RC<TokenSyntax> getIdentifier() const; |
| |
| /// Return a new `SymbolicReferenceExprSyntax` with the given identifier. |
| SymbolicReferenceExprSyntax |
| withIdentifier(RC<TokenSyntax> NewIdentifier) const; |
| |
| /// Return the generic arguments this symbolic reference has, if it has one. |
| llvm::Optional<GenericArgumentClauseSyntax> getGenericArgumentClause() const; |
| |
| /// Return a new `SymbolicReferenceExprSyntax` with the given generic |
| /// arguments. |
| SymbolicReferenceExprSyntax |
| withGenericArgumentClause(GenericArgumentClauseSyntax NewGenericArgs) const; |
| |
| static bool classof(const Syntax *S) { |
| return S->getKind() == SyntaxKind::SymbolicReferenceExpr; |
| } |
| }; |
| |
| #pragma mark - function-call-argument Data |
| |
| class FunctionCallArgumentSyntaxData : public SyntaxData { |
| friend struct SyntaxFactory; |
| friend class FunctionCallArgumentSyntax; |
| friend class SyntaxData; |
| |
| RC<ExprSyntaxData> CachedExpression; |
| |
| FunctionCallArgumentSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static RC<FunctionCallArgumentSyntaxData> |
| make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static RC<FunctionCallArgumentSyntaxData> makeBlank(); |
| |
| public: |
| static bool classof(const SyntaxData *S) { |
| return S->getKind() == SyntaxKind::FunctionCallArgument; |
| } |
| }; |
| |
| #pragma mark - function-call-argument API |
| |
| /// function-call-argument -> label? ':'? (expression | operator) ','? |
| class FunctionCallArgumentSyntax : public Syntax { |
| using DataType = FunctionCallArgumentSyntaxData; |
| |
| friend struct SyntaxFactory; |
| friend class SyntaxData; |
| friend class Syntax; |
| friend class FunctionCallArgumentSyntaxData; |
| friend class FunctionCallArgumentListSyntax; |
| friend class SyntaxCollectionData<SyntaxKind::FunctionCallArgumentList, |
| FunctionCallArgumentSyntax>; |
| friend class SyntaxCollection<SyntaxKind::FunctionCallArgumentList, |
| FunctionCallArgumentSyntax>; |
| |
| enum class Cursor { |
| Label, |
| Colon, |
| Expression, |
| Comma, |
| }; |
| |
| FunctionCallArgumentSyntax(const RC<SyntaxData> Root, |
| const DataType *Data); |
| |
| public: |
| |
| /// Return the label identifier for this argument, if it has one. |
| RC<TokenSyntax> getLabel() const; |
| |
| /// Return a new `FunctionCallArgumentSyntax` with the given label. |
| FunctionCallArgumentSyntax withLabel(RC<TokenSyntax> NewLabel) const; |
| |
| /// Get the colon ':' token in between the label and argument, |
| /// if there is one. |
| RC<TokenSyntax> getColonToken() const; |
| |
| /// Return a new `FunctionCallArgumentSyntax` with the given colon ':' token. |
| FunctionCallArgumentSyntax withColonToken(RC<TokenSyntax> NewColon) const; |
| |
| /// Returns the expression of the argument. |
| llvm::Optional<ExprSyntax> getExpression() const; |
| |
| /// Return a new `FunctionCallArgumentSyntax` with the given expression |
| /// argument. |
| FunctionCallArgumentSyntax withExpression(ExprSyntax NewExpression) const; |
| |
| /// Get the comma ',' token immediately following this argument, if there |
| /// is one. |
| RC<TokenSyntax> getTrailingComma() const; |
| |
| /// Return a new `FunctionCallArgumentSyntax` with the given comma attached |
| /// to the end of the argument. |
| FunctionCallArgumentSyntax |
| withTrailingComma(RC<TokenSyntax> NewTrailingComma) const; |
| |
| static bool classof(const Syntax *S) { |
| return S->getKind() == SyntaxKind::FunctionCallArgument; |
| } |
| }; |
| |
| #pragma mark - function-call-argument-list Data |
| |
| using FunctionCallArgumentListSyntaxData = |
| SyntaxCollectionData<SyntaxKind::FunctionCallArgumentList, |
| FunctionCallArgumentSyntax>; |
| |
| #pragma mark - function-call-argument-list API |
| |
| /// function-call-argument-list -> function-call-argument |
| /// function-call-argument-list? |
| class FunctionCallArgumentListSyntax |
| : public SyntaxCollection<SyntaxKind::FunctionCallArgumentList, |
| FunctionCallArgumentSyntax> { |
| friend struct SyntaxFactory; |
| friend class FunctionCallExprSyntax; |
| friend class Syntax; |
| friend class SyntaxData; |
| |
| using DataType = FunctionCallArgumentListSyntaxData; |
| |
| FunctionCallArgumentListSyntax(const RC<SyntaxData> Root, |
| const DataType *Data); |
| |
| public: |
| static bool classof(const Syntax *S) { |
| return S->getKind() == SyntaxKind::FunctionCallArgumentList; |
| } |
| }; |
| |
| #pragma mark - function-call-expression Data |
| |
| class FunctionCallExprSyntaxData : public ExprSyntaxData { |
| friend struct SyntaxFactory; |
| friend class FunctionCallExprSyntax; |
| friend class FunctionCallExprSyntaxBuilder; |
| friend class SyntaxData; |
| |
| RC<ExprSyntaxData> CachedCalledExpression; |
| RC<FunctionCallArgumentListSyntaxData> CachedArgumentList; |
| |
| FunctionCallExprSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static RC<FunctionCallExprSyntaxData> |
| make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr, |
| CursorIndex IndexInParent = 0); |
| |
| static RC<FunctionCallExprSyntaxData> makeBlank(); |
| |
| public: |
| static bool classof(const SyntaxData *S) { |
| return S->getKind() == SyntaxKind::FunctionCallExpr; |
| } |
| }; |
| |
| #pragma mark - function-call-expression API |
| |
| class FunctionCallExprSyntax : public ExprSyntax { |
| using DataType = FunctionCallExprSyntaxData; |
| friend struct SyntaxFactory; |
| friend class FunctionCallExprSyntaxData; |
| friend class FunctionCallExprSyntaxBuilder; |
| friend class Syntax; |
| friend class SyntaxData; |
| |
| enum class Cursor: CursorIndex { |
| CalledExpression, |
| LeftParen, |
| ArgumentList, |
| RightParen, |
| }; |
| |
| FunctionCallExprSyntax(const RC<SyntaxData> Root, const DataType *Data); |
| |
| public: |
| |
| /// Get the base expression getting called. |
| ExprSyntax getCalledExpression() const; |
| |
| /// Return a new `FunctionCallExprSyntax` with the given base expression |
| /// to be called. |
| FunctionCallExprSyntax |
| withCalledExpression(ExprSyntax NewBaseExpression) const; |
| |
| /// Return the left parenthesis '(' token in this call. |
| RC<TokenSyntax> getLeftParen() const; |
| |
| /// Return a new `FunctionCallExprSyntax` with the given left parenthesis '(' |
| /// token. |
| FunctionCallExprSyntax withLeftParen(RC<TokenSyntax> NewLeftParen) const; |
| |
| /// Get the list of arguments in this call expression. |
| FunctionCallArgumentListSyntax getArgumentList() const; |
| |
| /// Return a new `FunctionCallExprSyntax` with the given argument list. |
| FunctionCallExprSyntax |
| withArgumentList(FunctionCallArgumentListSyntax NewArgumentList) const; |
| |
| /// Return the right parenthesis ')' token in this call. |
| RC<TokenSyntax> getRightParen() const; |
| |
| /// Return a new `FunctionCallExprSyntax` with the given right parenthesis ')' |
| /// token. |
| FunctionCallExprSyntax withRightParen(RC<TokenSyntax> NewLeftParen) const; |
| |
| static bool classof(const Syntax *S) { |
| return S->getKind() == SyntaxKind::FunctionCallExpr; |
| } |
| }; |
| |
| #pragma mark - function-call-argument-list-builder |
| class FunctionCallExprSyntaxBuilder { |
| RawSyntax::LayoutList CallLayout; |
| RawSyntax::LayoutList ListLayout; |
| public: |
| |
| /// Start the builder with all elements marked as missing or empty. |
| FunctionCallExprSyntaxBuilder(); |
| |
| /// Use the given expression as the call target. |
| FunctionCallExprSyntaxBuilder & |
| useCalledExpression(ExprSyntax CalledExpression); |
| |
| /// Use the given left parenthesis '(' token in the function call. |
| FunctionCallExprSyntaxBuilder &useLeftParen(RC<TokenSyntax> LeftParen); |
| |
| /// Add an additional argument to the layout. |
| FunctionCallExprSyntaxBuilder & |
| appendArgument(FunctionCallArgumentSyntax AdditionalArgument); |
| |
| /// Use the given right parenthesis ')' token in the function call. |
| FunctionCallExprSyntaxBuilder &useRightParen(RC<TokenSyntax> RightParen); |
| |
| /// Return a `FunctionCallExprSyntax` with the arguments added so far. |
| FunctionCallExprSyntax build() const; |
| }; |
| |
| } // end namespace syntax |
| } // end namespace swift |
| |
| #endif // SWIFT_SYNTAX_EXPRSYNTAX_H |