| //===--- Parser.h - Swift Language Parser -----------------------*- 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 Parser interface. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_PARSER_H |
| #define SWIFT_PARSER_H |
| |
| #include "swift/AST/ASTContext.h" |
| #include "swift/AST/ASTNode.h" |
| #include "swift/AST/Expr.h" |
| #include "swift/AST/DiagnosticsParse.h" |
| #include "swift/AST/LayoutConstraint.h" |
| #include "swift/AST/Pattern.h" |
| #include "swift/AST/Stmt.h" |
| #include "swift/Basic/OptionSet.h" |
| #include "swift/Parse/ASTGen.h" |
| #include "swift/Parse/Lexer.h" |
| #include "swift/Parse/LocalContext.h" |
| #include "swift/Parse/PersistentParserState.h" |
| #include "swift/Parse/Token.h" |
| #include "swift/Parse/ParsedSyntaxNodes.h" |
| #include "swift/Parse/ParserPosition.h" |
| #include "swift/Parse/ParserResult.h" |
| #include "swift/Parse/SyntaxParserResult.h" |
| #include "swift/Parse/SyntaxParsingContext.h" |
| #include "swift/Syntax/References.h" |
| #include "swift/Config.h" |
| #include "llvm/ADT/SetVector.h" |
| |
| namespace llvm { |
| template <typename... PTs> class PointerUnion; |
| } |
| |
| namespace swift { |
| class CodeCompletionCallbacks; |
| class DefaultArgumentInitializer; |
| class DiagnosticEngine; |
| class Expr; |
| class Lexer; |
| class ParsedTypeSyntax; |
| class PersistentParserState; |
| class SILParserTUStateBase; |
| class ScopeInfo; |
| class SourceManager; |
| class TupleType; |
| struct TypeLoc; |
| |
| struct EnumElementInfo; |
| |
| namespace syntax { |
| class AbsolutePosition; |
| class RawSyntax; |
| enum class SyntaxKind; |
| }// end of syntax namespace |
| |
| /// Different contexts in which BraceItemList are parsed. |
| enum class BraceItemListKind { |
| /// A statement list terminated by a closing brace. The default. |
| Brace, |
| /// A statement list in a case block. The list is terminated |
| /// by a closing brace or a 'case' or 'default' label. |
| Case, |
| /// The top-level of a file, when not in parse-as-library mode (i.e. the |
| /// repl or a script). |
| TopLevelCode, |
| /// The top-level of a file, when in parse-as-library mode. |
| TopLevelLibrary, |
| /// The body of the inactive clause of an #if/#else/#endif block |
| InactiveConditionalBlock, |
| /// The body of the active clause of an #if/#else/#endif block |
| ActiveConditionalBlock, |
| }; |
| |
| /// The receiver will be fed with consumed tokens while parsing. The main purpose |
| /// is to generate a corrected token stream for tooling support like syntax |
| /// coloring. |
| class ConsumeTokenReceiver { |
| public: |
| /// This is called when a token is consumed. |
| virtual void receive(Token Tok) {} |
| |
| /// This is called to update the kind of a token whose start location is Loc. |
| virtual void registerTokenKindChange(SourceLoc Loc, tok NewKind) {}; |
| |
| /// This is called when a source file is fully parsed. |
| virtual void finalize() {}; |
| virtual ~ConsumeTokenReceiver() = default; |
| }; |
| |
| /// The main class used for parsing a source file (.swift or .sil). |
| /// |
| /// Rather than instantiating a Parser yourself, use one of the parsing APIs |
| /// provided in Subsystems.h. |
| class Parser { |
| Parser(const Parser&) = delete; |
| void operator=(const Parser&) = delete; |
| |
| bool IsInputIncomplete = false; |
| std::vector<Token> SplitTokens; |
| |
| public: |
| SourceManager &SourceMgr; |
| DiagnosticEngine &Diags; |
| SourceFile &SF; |
| Lexer *L; |
| SILParserTUStateBase *SIL; // Non-null when parsing a .sil file. |
| PersistentParserState *State; |
| std::unique_ptr<PersistentParserState> OwnedState; |
| DeclContext *CurDeclContext; |
| ASTContext &Context; |
| CodeCompletionCallbacks *CodeCompletion = nullptr; |
| std::vector<std::pair<SourceLoc, std::vector<ParamDecl*>>> AnonClosureVars; |
| |
| bool IsParsingInterfaceTokens = false; |
| |
| /// DisabledVars is a list of variables for whom local name lookup is |
| /// disabled. This is used when parsing a PatternBindingDecl to reject self |
| /// uses and to disable uses of the bound variables in a let/else block. The |
| /// diagnostic to emit is stored in DisabledVarReason. |
| ArrayRef<VarDecl *> DisabledVars; |
| Diag<> DisabledVarReason; |
| |
| llvm::SmallPtrSet<Decl *, 2> AlreadyHandledDecls; |
| enum { |
| /// InVarOrLetPattern has this value when not parsing a pattern. |
| IVOLP_NotInVarOrLet, |
| |
| /// InVarOrLetPattern has this value when we're in a matching pattern, but |
| /// not within a var/let pattern. In this phase, identifiers are references |
| /// to the enclosing scopes, not a variable binding. |
| IVOLP_InMatchingPattern, |
| |
| /// InVarOrLetPattern has this value when parsing a pattern in which bound |
| /// variables are implicitly immutable, but allowed to be marked mutable by |
| /// using a 'var' pattern. This happens in for-each loop patterns. |
| IVOLP_ImplicitlyImmutable, |
| |
| /// When InVarOrLetPattern has this value, bound variables are mutable, and |
| /// nested let/var patterns are not permitted. This happens when parsing a |
| /// 'var' decl or when parsing inside a 'var' pattern. |
| IVOLP_InVar, |
| |
| /// When InVarOrLetPattern has this value, bound variables are immutable,and |
| /// nested let/var patterns are not permitted. This happens when parsing a |
| /// 'let' decl or when parsing inside a 'let' pattern. |
| IVOLP_InLet |
| } InVarOrLetPattern = IVOLP_NotInVarOrLet; |
| |
| bool InPoundLineEnvironment = false; |
| bool InPoundIfEnvironment = false; |
| bool InSwiftKeyPath = false; |
| |
| LocalContext *CurLocalContext = nullptr; |
| |
| bool isDelayedParsingEnabled() const { |
| return DelayBodyParsing || SourceMgr.getCodeCompletionLoc().isValid(); |
| } |
| |
| void setCodeCompletionCallbacks(CodeCompletionCallbacks *Callbacks) { |
| CodeCompletion = Callbacks; |
| } |
| |
| bool isCodeCompletionFirstPass() { |
| return L->isCodeCompletion() && !CodeCompletion; |
| } |
| |
| bool allowTopLevelCode() const; |
| |
| const std::vector<Token> &getSplitTokens() const { return SplitTokens; } |
| |
| ParsedTokenSyntax markSplitTokenSyntax(tok Kind, StringRef Txt); |
| |
| void markSplitToken(tok Kind, StringRef Txt); |
| |
| /// Returns true if the parser reached EOF with incomplete source input, due |
| /// for example, a missing right brace. |
| bool isInputIncomplete() const { return IsInputIncomplete; } |
| |
| void checkForInputIncomplete() { |
| IsInputIncomplete = IsInputIncomplete || |
| // Check whether parser reached EOF but the real EOF, not the end of a |
| // string interpolation segment. |
| (Tok.is(tok::eof) && Tok.getText() != ")"); |
| } |
| |
| /// This is the current token being considered by the parser. |
| Token Tok; |
| |
| /// leading trivias for \c Tok. |
| /// Always empty if !SF.shouldBuildSyntaxTree(). |
| ParsedTrivia LeadingTrivia; |
| |
| /// trailing trivias for \c Tok. |
| /// Always empty if !SF.shouldBuildSyntaxTree(). |
| ParsedTrivia TrailingTrivia; |
| |
| /// Whether we should delay parsing nominal type and extension bodies, |
| /// and skip function bodies. |
| /// |
| /// This is false in primary files, since we want to type check all |
| /// declarations and function bodies. |
| /// |
| /// This is true for non-primary files, where declarations only need to be |
| /// lazily parsed and type checked. |
| bool DelayBodyParsing; |
| |
| /// The receiver to collect all consumed tokens. |
| ConsumeTokenReceiver *TokReceiver; |
| |
| /// The location of the previous token. |
| SourceLoc PreviousLoc; |
| |
| /// Stop parsing immediately. |
| void cutOffParsing() { |
| // Cut off parsing by acting as if we reached the end-of-file. |
| Tok.setKind(tok::eof); |
| } |
| |
| /// Use this to assert that the parser has advanced the lexing location, e.g. |
| /// before a specific parser function has returned. |
| class AssertParserMadeProgressBeforeLeavingScopeRAII { |
| Parser &P; |
| SourceLoc InitialLoc; |
| public: |
| AssertParserMadeProgressBeforeLeavingScopeRAII(Parser &parser) : P(parser) { |
| InitialLoc = P.Tok.getLoc(); |
| } |
| ~AssertParserMadeProgressBeforeLeavingScopeRAII() { |
| assert(InitialLoc != P.Tok.getLoc() && |
| "parser did not make progress, this can result in infinite loop"); |
| } |
| }; |
| |
| /// A RAII object for temporarily changing CurDeclContext. |
| class ContextChange { |
| protected: |
| Parser &P; |
| DeclContext *OldContext; // null signals that this has been popped |
| LocalContext *OldLocal; |
| |
| ContextChange(const ContextChange &) = delete; |
| ContextChange &operator=(const ContextChange &) = delete; |
| |
| public: |
| ContextChange(Parser &P, DeclContext *DC, |
| LocalContext *newLocal = nullptr) |
| : P(P), OldContext(P.CurDeclContext), OldLocal(P.CurLocalContext) { |
| assert(DC && "pushing null context?"); |
| P.CurDeclContext = DC; |
| P.CurLocalContext = newLocal; |
| } |
| |
| /// Prematurely pop the DeclContext installed by the constructor. |
| /// Makes the destructor a no-op. |
| void pop() { |
| assert(OldContext && "already popped context!"); |
| popImpl(); |
| OldContext = nullptr; |
| } |
| |
| ~ContextChange() { |
| if (OldContext) popImpl(); |
| } |
| |
| private: |
| void popImpl() { |
| P.CurDeclContext = OldContext; |
| P.CurLocalContext = OldLocal; |
| } |
| }; |
| |
| /// A RAII object for parsing a new local context. |
| class ParseFunctionBody : public LocalContext { |
| private: |
| ContextChange CC; |
| public: |
| ParseFunctionBody(Parser &P, DeclContext *DC) : CC(P, DC, this) { |
| assert(!isa<TopLevelCodeDecl>(DC) && |
| "top-level code should be parsed using TopLevelCodeContext!"); |
| } |
| |
| void pop() { |
| CC.pop(); |
| } |
| }; |
| |
| /// Describes the kind of a lexical structure marker, indicating |
| /// what kind of structural element we started parsing at a |
| /// particular location. |
| enum class StructureMarkerKind : uint8_t { |
| /// The start of a declaration. |
| Declaration, |
| /// The start of a statement. |
| Statement, |
| /// An open parentheses. |
| OpenParen, |
| /// An open brace. |
| OpenBrace, |
| /// An open square bracket. |
| OpenSquare, |
| /// An #if conditional clause. |
| IfConfig, |
| }; |
| |
| /// A structure marker, which identifies the location at which the |
| /// parser saw an entity it is parsing. |
| struct StructureMarker { |
| /// The location at which the marker occurred. |
| SourceLoc Loc; |
| |
| /// The kind of marker. |
| StructureMarkerKind Kind; |
| |
| /// The leading whitespace for this marker, if it has already been |
| /// computed. |
| Optional<StringRef> LeadingWhitespace; |
| }; |
| |
| /// An RAII object that notes when we have seen a structure marker. |
| class StructureMarkerRAII { |
| Parser *const P; |
| |
| /// Max nesting level |
| // TODO: customizable. |
| enum { MaxDepth = 256 }; |
| |
| StructureMarkerRAII(Parser *parser) : P(parser) {} |
| |
| /// Have the parser start the new Structure or fail if already too deep. |
| bool pushStructureMarker(Parser &parser, SourceLoc loc, |
| StructureMarkerKind kind); |
| |
| public: |
| StructureMarkerRAII(Parser &parser, SourceLoc loc, StructureMarkerKind kind) |
| : StructureMarkerRAII( |
| pushStructureMarker(parser, loc, kind) ? &parser : nullptr) {} |
| |
| StructureMarkerRAII(Parser &parser, const Token &tok); |
| |
| /// Did we fail to push the new structure? |
| bool isFailed() { |
| return P == nullptr; |
| } |
| |
| ~StructureMarkerRAII() { |
| if (P != nullptr) { |
| P->StructureMarkers.pop_back(); |
| } |
| } |
| }; |
| friend class StructureMarkerRAII; |
| |
| /// A RAII object that tells the SyntaxParsingContext to defer Syntax nodes. |
| class DeferringContextRAII { |
| SyntaxParsingContext &Ctx; |
| bool WasDeferring; |
| |
| public: |
| explicit DeferringContextRAII(SyntaxParsingContext &SPCtx) |
| : Ctx(SPCtx), WasDeferring(Ctx.shouldDefer()) { |
| Ctx.setShouldDefer(); |
| } |
| |
| ~DeferringContextRAII() { |
| Ctx.setShouldDefer(WasDeferring); |
| } |
| }; |
| |
| /// The stack of structure markers indicating the locations of |
| /// structural elements actively being parsed, including the start |
| /// of declarations, statements, and opening operators of various |
| /// kinds. |
| /// |
| /// This vector is managed by \c StructureMarkerRAII objects. |
| llvm::SmallVector<StructureMarker, 16> StructureMarkers; |
| |
| /// Current syntax parsing context where call backs should be directed to. |
| SyntaxParsingContext *SyntaxContext; |
| |
| /// The AST generator. |
| ASTGen Generator; |
| |
| public: |
| Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags, |
| SILParserTUStateBase *SIL, |
| PersistentParserState *PersistentState, |
| std::shared_ptr<SyntaxParseActions> SPActions = nullptr, |
| bool DelayBodyParsing = true); |
| Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL, |
| PersistentParserState *PersistentState = nullptr, |
| std::shared_ptr<SyntaxParseActions> SPActions = nullptr, |
| bool DelayBodyParsing = true); |
| Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF, |
| SILParserTUStateBase *SIL = nullptr, |
| PersistentParserState *PersistentState = nullptr, |
| std::shared_ptr<SyntaxParseActions> SPActions = nullptr, |
| bool DelayBodyParsing = true); |
| ~Parser(); |
| |
| bool isInSILMode() const { return SIL != nullptr; } |
| |
| /// Calling this function to finalize libSyntax tree creation without destroying |
| /// the parser instance. |
| OpaqueSyntaxNode finalizeSyntaxTree() { |
| assert(Tok.is(tok::eof) && "not done parsing yet"); |
| return SyntaxContext->finalizeRoot(); |
| } |
| |
| //===--------------------------------------------------------------------===// |
| // Routines to save and restore parser state. |
| |
| ParserPosition getParserPosition() { |
| return ParserPosition(L->getStateForBeginningOfToken(Tok, LeadingTrivia), |
| PreviousLoc); |
| } |
| |
| ParserPosition getParserPosition(const PersistentParserState::ParserPos &Pos){ |
| return ParserPosition(L->getStateForBeginningOfTokenLoc(Pos.Loc), |
| Pos.PrevLoc); |
| } |
| |
| void restoreParserPosition(ParserPosition PP, bool enableDiagnostics = false) { |
| L->restoreState(PP.LS, enableDiagnostics); |
| L->lex(Tok, LeadingTrivia, TrailingTrivia); |
| PreviousLoc = PP.PreviousLoc; |
| } |
| |
| void backtrackToPosition(ParserPosition PP) { |
| assert(PP.isValid()); |
| L->backtrackToState(PP.LS); |
| L->lex(Tok, LeadingTrivia, TrailingTrivia); |
| PreviousLoc = PP.PreviousLoc; |
| } |
| |
| /// RAII object that, when it is destructed, restores the parser and lexer to |
| /// their positions at the time the object was constructed. Will not jump |
| /// forward in the token stream. |
| class BacktrackingScope { |
| Parser &P; |
| ParserPosition PP; |
| DiagnosticTransaction DT; |
| /// This context immediately deconstructed with transparent accumulation |
| /// on cancelBacktrack(). |
| llvm::Optional<SyntaxParsingContext> SynContext; |
| bool Backtrack = true; |
| |
| /// A token receiver used by the parser in the back tracking scope. This |
| /// receiver will save any consumed tokens during this back tracking scope. |
| /// After the scope ends, it either transfers the saved tokens to the old receiver |
| /// or discard them. |
| struct DelayedTokenReceiver: ConsumeTokenReceiver { |
| /// Keep track of the old token receiver in the parser so that we can recover |
| /// after the backtracking sope ends. |
| llvm::SaveAndRestore<ConsumeTokenReceiver*> savedConsumer; |
| |
| // Whether the tokens should be transferred to the original receiver. |
| // When the back tracking scope will actually back track, this should be false; |
| // otherwise true. |
| bool shouldTransfer = false; |
| std::vector<Token> delayedTokens; |
| DelayedTokenReceiver(ConsumeTokenReceiver *&receiver): |
| savedConsumer(receiver, this) {} |
| void receive(Token tok) override { |
| delayedTokens.push_back(tok); |
| } |
| ~DelayedTokenReceiver() { |
| if (!shouldTransfer) |
| return; |
| for (auto tok: delayedTokens) { |
| savedConsumer.get()->receive(tok); |
| } |
| } |
| } TempReceiver; |
| |
| public: |
| BacktrackingScope(Parser &P) |
| : P(P), PP(P.getParserPosition()), DT(P.Diags), |
| TempReceiver(P.TokReceiver) { |
| SynContext.emplace(P.SyntaxContext); |
| SynContext->setBackTracking(); |
| } |
| |
| ~BacktrackingScope(); |
| bool willBacktrack() const { return Backtrack; } |
| |
| void cancelBacktrack() { |
| Backtrack = false; |
| SynContext->setTransparent(); |
| SynContext.reset(); |
| DT.commit(); |
| TempReceiver.shouldTransfer = true; |
| } |
| }; |
| |
| /// RAII object that, when it is destructed, restores the parser and lexer to |
| /// their positions at the time the object was constructed. |
| struct ParserPositionRAII { |
| private: |
| Parser &P; |
| ParserPosition PP; |
| |
| public: |
| ParserPositionRAII(Parser &P) : P(P), PP(P.getParserPosition()) {} |
| |
| ~ParserPositionRAII() { |
| P.restoreParserPosition(PP); |
| } |
| }; |
| |
| //===--------------------------------------------------------------------===// |
| // Utilities |
| |
| /// Return the next token that will be installed by \c consumeToken. |
| const Token &peekToken(); |
| |
| /// Consume a token that we created on the fly to correct the original token |
| /// stream from lexer. |
| void consumeExtraToken(Token K); |
| SourceLoc consumeTokenWithoutFeedingReceiver(); |
| SourceLoc consumeToken(); |
| SourceLoc consumeToken(tok K) { |
| assert(Tok.is(K) && "Consuming wrong token kind"); |
| return consumeToken(); |
| } |
| /// Consume a token without providing it to the SyntaxParsingContext. |
| ParsedTokenSyntax consumeTokenSyntax(); |
| ParsedTokenSyntax consumeTokenSyntax(tok K) { |
| assert(Tok.is(K) && "Consuming wrong token kind"); |
| return consumeTokenSyntax(); |
| } |
| SourceLoc leadingTriviaLoc() { |
| return Tok.getLoc().getAdvancedLoc(-LeadingTrivia.getLength()); |
| } |
| |
| ParsedTokenSyntax consumeIdentifierSyntax(bool allowDollarIdentifier = false) { |
| assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self)); |
| |
| if (Tok.getText()[0] == '$' && !allowDollarIdentifier) |
| diagnoseDollarIdentifier(Tok); |
| |
| Tok.setKind(tok::identifier); |
| return consumeTokenSyntax(); |
| } |
| |
| SourceLoc consumeIdentifier(Identifier *Result = nullptr, |
| bool allowDollarIdentifier = false) { |
| assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self)); |
| if (Result) |
| *Result = Context.getIdentifier(Tok.getText()); |
| |
| if (Tok.getText()[0] == '$' && !allowDollarIdentifier) |
| diagnoseDollarIdentifier(Tok); |
| |
| return consumeToken(); |
| } |
| |
| SourceLoc consumeArgumentLabel(Identifier &Result) { |
| assert(Tok.canBeArgumentLabel()); |
| assert(Result.empty()); |
| if (!Tok.is(tok::kw__)) { |
| Tok.setKind(tok::identifier); |
| Result = Context.getIdentifier(Tok.getText()); |
| |
| if (Tok.getText()[0] == '$') |
| diagnoseDollarIdentifier(Tok); |
| } |
| return consumeToken(); |
| } |
| |
| ParsedTokenSyntax consumeArgumentLabelSyntax() { |
| assert(Tok.canBeArgumentLabel()); |
| if (!Tok.is(tok::kw__)) { |
| Tok.setKind(tok::identifier); |
| |
| if (Tok.getText()[0] == '$') |
| diagnoseDollarIdentifier(Tok); |
| } |
| return consumeTokenSyntax(); |
| } |
| |
| /// When we have a token that is an identifier starting with '$', |
| /// diagnose it if not permitted in this mode. |
| void diagnoseDollarIdentifier(const Token &tok) { |
| assert(tok.getText()[0] == '$'); |
| |
| if (tok.getText().size() == 1 || |
| Context.LangOpts.EnableDollarIdentifiers || |
| isInSILMode() || L->isSwiftInterface()) |
| return; |
| |
| diagnose(tok.getLoc(), diag::dollar_identifier_decl, |
| Context.getIdentifier(tok.getText())); |
| } |
| |
| /// Retrieve the location just past the end of the previous |
| /// source location. |
| SourceLoc getEndOfPreviousLoc() const; |
| |
| /// If the current token is the specified kind, consume it and |
| /// return it. Otherwise, return None without consuming it. |
| llvm::Optional<ParsedTokenSyntax> consumeTokenSyntaxIf(tok K) { |
| if (Tok.isNot(K)) |
| return llvm::None; |
| return consumeTokenSyntax(); |
| } |
| |
| /// If the current token is the specified kind, consume it and |
| /// return true. Otherwise, return false without consuming it. |
| bool consumeIf(tok K) { |
| if (Tok.isNot(K)) return false; |
| consumeToken(K); |
| return true; |
| } |
| |
| /// If the current token is the specified kind, consume it and |
| /// return true. Otherwise, return false without consuming it. |
| bool consumeIf(tok K, SourceLoc &consumedLoc) { |
| if (Tok.isNot(K)) return false; |
| consumedLoc = consumeToken(K); |
| return true; |
| } |
| |
| bool consumeIfNotAtStartOfLine(tok K) { |
| if (Tok.isAtStartOfLine()) return false; |
| return consumeIf(K); |
| } |
| |
| bool isContextualYieldKeyword() { |
| return (Tok.isContextualKeyword("yield") && |
| isa<AccessorDecl>(CurDeclContext) && |
| cast<AccessorDecl>(CurDeclContext)->isCoroutine()); |
| } |
| |
| /// Read tokens until we get to one of the specified tokens, then |
| /// return without consuming it. Because we cannot guarantee that the token |
| /// will ever occur, this skips to some likely good stopping point. |
| void skipUntilSyntax(llvm::SmallVectorImpl<ParsedSyntax> &Skipped, tok T1, |
| tok T2 = tok::NUM_TOKENS); |
| void skipUntil(tok T1, tok T2 = tok::NUM_TOKENS); |
| void skipUntilAnyOperator(); |
| |
| /// Skip until a token that starts with '>', and consume it if found. |
| /// Applies heuristics that are suitable when trying to find the end of a list |
| /// of generic parameters, generic arguments, or list of types in a protocol |
| /// composition. |
| void |
| skipUntilGreaterInTypeListSyntax(llvm::SmallVectorImpl<ParsedSyntax> &Skipped, |
| bool protocolComposition = false); |
| SourceLoc skipUntilGreaterInTypeList(bool protocolComposition = false); |
| |
| /// skipUntilDeclStmtRBrace - Skip to the next decl or '}'. |
| void skipUntilDeclRBrace(); |
| |
| void skipUntilDeclStmtRBrace(tok T1); |
| void skipUntilDeclStmtRBrace(tok T1, tok T2); |
| |
| void skipUntilDeclRBrace(tok T1, tok T2); |
| |
| void skipListUntilDeclRBrace(SourceLoc startLoc, tok T1, tok T2); |
| void skipListUntilDeclRBraceSyntax(SmallVectorImpl<ParsedSyntax> &Skipped, |
| SourceLoc startLoc, tok T1, tok T2); |
| |
| /// Skip a single token, but match parentheses, braces, and square brackets. |
| /// |
| /// Note: this does \em not match angle brackets ("<" and ">")! These are |
| /// matched in the source when they refer to a generic type, |
| /// but not when used as comparison operators. |
| void skipSingleSyntax(llvm::SmallVectorImpl<ParsedSyntax> &Skipped); |
| void skipSingle(); |
| |
| /// Skip until the next '#else', '#endif' or until eof. |
| void skipUntilConditionalBlockClose(); |
| |
| /// Skip until either finding \c T1 or reaching the end of the line. |
| /// |
| /// This uses \c skipSingle and so matches parens etc. After calling, one or |
| /// more of the following will be true: Tok.is(T1), Tok.isStartOfLine(), |
| /// Tok.is(tok::eof). The "or more" case is the first two: if the next line |
| /// starts with T1. |
| /// |
| /// \returns true if there is an instance of \c T1 on the current line (this |
| /// avoids the foot-gun of not considering T1 starting the next line for a |
| /// plain Tok.is(T1) check). |
| bool skipUntilTokenOrEndOfLine(tok T1); |
| |
| //-------------------------------------------------------------------------// |
| // Ignore token APIs. |
| // This is used when we skip gabage text in the source text. |
| |
| /// Ignore the current single token. |
| void ignoreToken(); |
| void ignoreToken(tok Kind) { |
| /// Ignore the current single token asserting its kind. |
| assert(Tok.is(Kind)); |
| ignoreToken(); |
| } |
| /// Conditionally ignore the current single token if it matches with the \p |
| /// Kind. |
| bool ignoreIf(tok Kind) { |
| if (!Tok.is(Kind)) |
| return false; |
| ignoreToken(); |
| return true; |
| } |
| void ignoreSingle(); |
| void ignoreUntil(tok Kind); |
| |
| /// Ignore tokens until a token that starts with '>', and return true it if |
| /// found. Applies heuristics that are suitable when trying to find the end |
| /// of a list of generic parameters, generic arguments. |
| bool ignoreUntilGreaterInTypeList(); |
| |
| /// If the parser is generating only a syntax tree, try loading the current |
| /// node from a previously generated syntax tree. |
| /// Returns \c true if the node has been loaded and inserted into the current |
| /// syntax tree. In this case the parser should behave as if the node has |
| /// successfully been created. |
| bool loadCurrentSyntaxNodeFromCache(); |
| |
| /// Parse an #endif. |
| bool parseEndIfDirective(SourceLoc &Loc); |
| |
| /// Given that the current token is a string literal, |
| /// - if it is not interpolated, returns the contents; |
| /// - otherwise, diagnoses and returns None. |
| /// |
| /// \param Loc where to diagnose. |
| /// \param DiagText name for the string literal in the diagnostic. |
| Optional<StringRef> |
| getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText); |
| |
| public: |
| InFlightDiagnostic diagnose(SourceLoc Loc, Diagnostic Diag) { |
| if (Diags.isDiagnosticPointsToFirstBadToken(Diag.getID()) && |
| Loc == Tok.getLoc() && Tok.isAtStartOfLine()) |
| Loc = getEndOfPreviousLoc(); |
| return Diags.diagnose(Loc, Diag); |
| } |
| |
| InFlightDiagnostic diagnose(Token Tok, Diagnostic Diag) { |
| return diagnose(Tok.getLoc(), Diag); |
| } |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| InFlightDiagnostic diagnose(SourceLoc Loc, Diag<DiagArgTypes...> DiagID, |
| ArgTypes &&...Args) { |
| return diagnose(Loc, Diagnostic(DiagID, std::forward<ArgTypes>(Args)...)); |
| } |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| InFlightDiagnostic diagnose(Token Tok, Diag<DiagArgTypes...> DiagID, |
| ArgTypes &&...Args) { |
| return diagnose(Tok.getLoc(), |
| Diagnostic(DiagID, std::forward<ArgTypes>(Args)...)); |
| } |
| |
| void diagnoseRedefinition(ValueDecl *Prev, ValueDecl *New); |
| |
| /// Add a fix-it to remove the space in consecutive identifiers. |
| /// Add a camel-cased option if it is different than the first option. |
| void diagnoseConsecutiveIDs(StringRef First, SourceLoc FirstLoc, |
| StringRef DeclKindName); |
| |
| bool startsWithSymbol(Token Tok, char symbol) { |
| return (Tok.isAnyOperator() || Tok.isPunctuation()) && |
| Tok.getText()[0] == symbol; |
| } |
| /// Check whether the current token starts with '<'. |
| bool startsWithLess(Token Tok) { return startsWithSymbol(Tok, '<'); } |
| |
| /// Check whether the current token starts with '>'. |
| bool startsWithGreater(Token Tok) { return startsWithSymbol(Tok, '>'); } |
| |
| /// Consume the starting '<' of the current token, which may either |
| /// be a complete '<' token or some kind of operator token starting with '<', |
| /// e.g., '<>'. |
| ParsedTokenSyntax consumeStartingLessSyntax(); |
| SourceLoc consumeStartingLess(); |
| |
| /// Consume the starting '>' of the current token, which may either |
| /// be a complete '>' token or some kind of operator token starting with '>', |
| /// e.g., '>>'. |
| ParsedTokenSyntax consumeStartingGreaterSyntax(); |
| SourceLoc consumeStartingGreater(); |
| |
| /// Consume the starting character of the current token, and split the |
| /// remainder of the token into a new token (or tokens). |
| ParsedTokenSyntax |
| consumeStartingCharacterOfCurrentTokenSyntax(tok Kind, size_t Len = 1); |
| SourceLoc consumeStartingCharacterOfCurrentToken(tok Kind, size_t Len = 1); |
| |
| swift::ScopeInfo &getScopeInfo() { return State->getScopeInfo(); } |
| |
| /// Add the given Decl to the current scope. |
| void addToScope(ValueDecl *D, bool diagnoseRedefinitions = true) { |
| if (Context.LangOpts.DisableParserLookup) |
| return; |
| |
| getScopeInfo().addToScope(D, *this, diagnoseRedefinitions); |
| } |
| |
| ValueDecl *lookupInScope(DeclName Name) { |
| if (Context.LangOpts.DisableParserLookup) |
| return nullptr; |
| |
| return getScopeInfo().lookupValueName(Name); |
| } |
| |
| //===--------------------------------------------------------------------===// |
| // Primitive Parsing |
| |
| /// Consume an identifier (but not an operator) if present and return |
| /// its name in \p Result. Otherwise, emit an error. |
| /// |
| /// \returns false on success, true on error. |
| bool parseIdentifier(Identifier &Result, SourceLoc &Loc, const Diagnostic &D); |
| llvm::Optional<ParsedTokenSyntax> parseIdentifierSyntax(const Diagnostic &D); |
| |
| /// Consume an identifier with a specific expected name. This is useful for |
| /// contextually sensitive keywords that must always be present. |
| bool parseSpecificIdentifier(StringRef expected, SourceLoc &Loc, |
| const Diagnostic &D); |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID, |
| ArgTypes... Args) { |
| SourceLoc L; |
| return parseIdentifier(Result, L, Diagnostic(ID, Args...)); |
| } |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseIdentifier(Identifier &Result, SourceLoc &L, |
| Diag<DiagArgTypes...> ID, ArgTypes... Args) { |
| return parseIdentifier(Result, L, Diagnostic(ID, Args...)); |
| } |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseSpecificIdentifier(StringRef expected, |
| Diag<DiagArgTypes...> ID, ArgTypes... Args) { |
| SourceLoc L; |
| return parseSpecificIdentifier(expected, L, Diagnostic(ID, Args...)); |
| } |
| |
| /// Consume an identifier or operator if present and return its name |
| /// in \p Result. Otherwise, emit an error and return true. |
| bool parseAnyIdentifier(Identifier &Result, SourceLoc &Loc, |
| const Diagnostic &D); |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseAnyIdentifier(Identifier &Result, Diag<DiagArgTypes...> ID, |
| ArgTypes... Args) { |
| SourceLoc L; |
| return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...)); |
| } |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseAnyIdentifier(Identifier &Result, SourceLoc &L, |
| Diag<DiagArgTypes...> ID, ArgTypes... Args) { |
| return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...)); |
| } |
| |
| /// The parser expects that \p K is next token in the input. If so, |
| /// it is consumed and false is returned. |
| /// |
| /// If the input is malformed, this emits the specified error diagnostic. |
| bool parseToken(tok K, SourceLoc &TokLoc, const Diagnostic &D); |
| llvm::Optional<ParsedTokenSyntax> parseTokenSyntax(tok K, SourceLoc &TokLoc, |
| const Diagnostic &D); |
| |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseToken(tok K, Diag<DiagArgTypes...> ID, ArgTypes... Args) { |
| SourceLoc L; |
| return parseToken(K, L, Diagnostic(ID, Args...)); |
| } |
| template<typename ...DiagArgTypes, typename ...ArgTypes> |
| bool parseToken(tok K, SourceLoc &L, |
| Diag<DiagArgTypes...> ID, ArgTypes... Args) { |
| return parseToken(K, L, Diagnostic(ID, Args...)); |
| } |
| |
| /// Parse the specified expected token and return its location on success. On failure, emit the specified |
| /// error diagnostic, a note at the specified note location, and return the location of the previous token. |
| bool parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag, |
| SourceLoc OtherLoc); |
| |
| /// SWIFT_ENABLE_TENSORFLOW |
| /// \brief Parse an unsigned integer and returns it in \p Result. On failure |
| /// emit the specified error diagnostic, and a note at the specified note |
| /// location. |
| bool parseUnsignedInteger(unsigned &Result, SourceLoc &Loc, |
| const Diagnostic &D); |
| |
| ParsedSyntaxResult<ParsedTokenSyntax> |
| parseMatchingTokenSyntax(tok K, Diag<> ErrorDiag, SourceLoc OtherLoc, |
| bool silenceDiag = false); |
| |
| /// Returns the proper location for a missing right brace, parenthesis, etc. |
| SourceLoc getLocForMissingMatchingToken() const; |
| |
| /// When encountering an error or a missing matching token (e.g. '}'), return |
| /// the location to use for it. This value should be at the last token in |
| /// the ASTNode being parsed so that it nests within any enclosing nodes, and, |
| /// for ASTScope lookups, it does not preceed any identifiers to be looked up. |
| /// However, the latter case does not hold when parsing an interpolated |
| /// string literal because there may be identifiers to be looked up in the |
| /// literal and their locations will not precede the location of a missing |
| /// close brace. |
| SourceLoc getErrorOrMissingLoc() const; |
| |
| /// Parse a comma separated list of some elements. |
| ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc, |
| bool AllowSepAfterLast, Diag<> ErrorDiag, |
| syntax::SyntaxKind Kind, |
| llvm::function_ref<ParserStatus()> callback); |
| ParserStatus parseListSyntax(tok RightK, SourceLoc LeftLoc, |
| llvm::Optional<ParsedTokenSyntax> &LastComma, |
| llvm::Optional<ParsedTokenSyntax> &Right, |
| llvm::SmallVectorImpl<ParsedSyntax>& Junk, |
| bool AllowSepAfterLast, Diag<> ErrorDiag, |
| llvm::function_ref<ParserStatus()> callback); |
| |
| void consumeTopLevelDecl(ParserPosition BeginParserPosition, |
| TopLevelCodeDecl *TLCD); |
| |
| ParserStatus parseBraceItems(SmallVectorImpl<ASTNode> &Decls, |
| BraceItemListKind Kind = |
| BraceItemListKind::Brace, |
| BraceItemListKind ConditionalBlockKind = |
| BraceItemListKind::Brace); |
| ParserResult<BraceStmt> parseBraceItemList(Diag<> ID); |
| |
| void parseTopLevelCodeDeclDelayed(); |
| |
| //===--------------------------------------------------------------------===// |
| // Decl Parsing |
| |
| /// Return true if parser is at the start of a decl or decl-import. |
| bool isStartOfDecl(); |
| |
| bool parseTopLevel(); |
| |
| /// Flags that control the parsing of declarations. |
| enum ParseDeclFlags { |
| PD_Default = 0, |
| PD_AllowTopLevel = 1 << 1, |
| PD_HasContainerType = 1 << 2, |
| PD_DisallowInit = 1 << 3, |
| PD_AllowDestructor = 1 << 4, |
| PD_AllowEnumElement = 1 << 5, |
| PD_InProtocol = 1 << 6, |
| PD_InClass = 1 << 7, |
| PD_InExtension = 1 << 8, |
| PD_InStruct = 1 << 9, |
| PD_InEnum = 1 << 10, |
| }; |
| |
| /// Options that control the parsing of declarations. |
| using ParseDeclOptions = OptionSet<ParseDeclFlags>; |
| |
| void delayParseFromBeginningToHere(ParserPosition BeginParserPosition, |
| ParseDeclOptions Flags); |
| void consumeDecl(ParserPosition BeginParserPosition, ParseDeclOptions Flags, |
| bool IsTopLevel); |
| |
| // When compiling for the Debugger, some Decl's need to be moved from the |
| // current scope. In which case although the Decl will be returned in the |
| // ParserResult, it should not be inserted into the Decl list for the current |
| // context. markWasHandled asserts that the Decl is already where it |
| // belongs, and declWasHandledAlready is used to check this assertion. |
| // To keep the handled decl array small, we remove the Decl when it is |
| // checked, so you can only call declWasAlreadyHandled once for a given |
| // decl. |
| |
| void markWasHandled(Decl *D) { |
| AlreadyHandledDecls.insert(D); |
| } |
| |
| bool declWasHandledAlready(Decl *D) { |
| return AlreadyHandledDecls.erase(D); |
| } |
| |
| ParserResult<Decl> parseDecl(ParseDeclOptions Flags, |
| bool IsAtStartOfLineOrPreviousHadSemi, |
| llvm::function_ref<void(Decl*)> Handler); |
| |
| void parseDeclDelayed(); |
| |
| std::vector<Decl *> parseDeclListDelayed(IterableDeclContext *IDC); |
| |
| bool parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, |
| SourceLoc PosBeforeLB, |
| Diag<> ErrorDiag, |
| IterableDeclContext *IDC); |
| |
| bool canDelayMemberDeclParsing(bool &HasOperatorDeclarations, |
| bool &HasNestedClassDeclarations); |
| |
| bool delayParsingDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, |
| IterableDeclContext *IDC); |
| |
| ParsedSyntaxResult<ParsedTypeInheritanceClauseSyntax> |
| parseTypeInheritanceClauseSyntax(bool allowClassRequirement, |
| bool allowAnyObject); |
| |
| ParsedSyntaxResult<ParsedDeclSyntax> |
| parseDeclAssociatedTypeSyntax(ParseDeclOptions flags, |
| Optional<ParsedAttributeListSyntax> attrs, |
| Optional<ParsedModifierListSyntax> modifiers); |
| |
| ParsedSyntaxResult<ParsedDeclSyntax> |
| parseDeclTypeAliasSyntax(ParseDeclOptions flags, |
| Optional<ParsedAttributeListSyntax> attrs, |
| Optional<ParsedModifierListSyntax> modifiers); |
| |
| ParserResult<TypeDecl> parseDeclTypeAlias(ParseDeclOptions Flags, |
| DeclAttributes &Attributes, |
| SourceLoc leadingLoc); |
| |
| ParserResult<TypeDecl> parseDeclAssociatedType(ParseDeclOptions Flags, |
| DeclAttributes &Attributes, |
| SourceLoc leadingLoc); |
| |
| /// Parse a #if ... #endif directive. |
| /// Delegate callback function to parse elements in the blocks. |
| ParserResult<IfConfigDecl> parseIfConfig( |
| llvm::function_ref<void(SmallVectorImpl<ASTNode> &, bool)> parseElements); |
| |
| /// Parse a #error or #warning diagnostic. |
| ParserResult<PoundDiagnosticDecl> parseDeclPoundDiagnostic(); |
| |
| /// Parse a #line/#sourceLocation directive. |
| /// 'isLine = true' indicates parsing #line instead of #sourcelocation |
| ParserStatus parseLineDirective(bool isLine = false); |
| |
| void setLocalDiscriminator(ValueDecl *D); |
| void setLocalDiscriminatorToParamList(ParameterList *PL); |
| |
| /// Parse the optional attributes before a declaration. |
| ParserStatus parseDeclAttributeList(DeclAttributes &Attributes); |
| |
| /// Parse the optional modifiers before a declaration. |
| bool parseDeclModifierList(DeclAttributes &Attributes, SourceLoc &StaticLoc, |
| StaticSpellingKind &StaticSpelling); |
| |
| /// Parse an availability attribute of the form |
| /// @available(*, introduced: 1.0, deprecated: 3.1). |
| /// \return \p nullptr if the platform name is invalid |
| ParserResult<AvailableAttr> |
| parseExtendedAvailabilitySpecList(SourceLoc AtLoc, SourceLoc AttrLoc, |
| StringRef AttrName); |
| |
| /// Parse the Objective-C selector inside @objc |
| void parseObjCSelector(SmallVector<Identifier, 4> &Names, |
| SmallVector<SourceLoc, 4> &NameLocs, |
| bool &IsNullarySelector); |
| |
| /// Parse the @_specialize attribute. |
| /// \p closingBrace is the expected closing brace, which can be either ) or ] |
| /// \p Attr is where to store the parsed attribute |
| bool parseSpecializeAttribute(swift::tok ClosingBrace, SourceLoc AtLoc, |
| SourceLoc Loc, SpecializeAttr *&Attr); |
| |
| /// Parse the arguments inside the @_specialize attribute |
| bool parseSpecializeAttributeArguments( |
| swift::tok ClosingBrace, bool &DiscardAttribute, Optional<bool> &Exported, |
| Optional<SpecializeAttr::SpecializationKind> &Kind, |
| TrailingWhereClause *&TrailingWhereClause); |
| |
| /// Parse the @_implements attribute. |
| /// \p Attr is where to store the parsed attribute |
| ParserResult<ImplementsAttr> parseImplementsAttribute(SourceLoc AtLoc, |
| SourceLoc Loc); |
| |
| /// SWIFT_ENABLE_TENSORFLOW |
| /// Parse the @differentiable attribute. |
| ParserResult<DifferentiableAttr> parseDifferentiableAttribute(SourceLoc AtLoc, |
| SourceLoc Loc); |
| |
| /// Parse the arguments inside the @differentiable attribute. |
| bool parseDifferentiableAttributeArguments( |
| bool &linear, SmallVectorImpl<ParsedAutoDiffParameter> ¶ms, |
| Optional<DeclNameWithLoc> &jvpSpec, Optional<DeclNameWithLoc> &vjpSpec, |
| TrailingWhereClause *&whereClause); |
| |
| /// Parse a differentiation parameters clause. |
| bool parseDifferentiationParametersClause( |
| SmallVectorImpl<ParsedAutoDiffParameter> ¶ms, StringRef attrName); |
| |
| /// Parse a transposing parameters clause. |
| bool parseTransposingParametersClause( |
| SmallVectorImpl<ParsedAutoDiffParameter> ¶ms, StringRef attrName); |
| |
| /// Parse the @differentiating attribute. |
| ParserResult<DifferentiatingAttr> |
| parseDifferentiatingAttribute(SourceLoc AtLoc, SourceLoc Loc); |
| |
| ParserResult<TransposingAttr> parseTransposingAttribute(SourceLoc AtLoc, |
| SourceLoc Loc); |
| |
| /// Parse the @quoted attribute. |
| ParserResult<QuotedAttr> parseQuotedAttribute(SourceLoc AtLoc, SourceLoc Loc); |
| |
| /// Parse a specific attribute. |
| ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc); |
| |
| bool parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc, |
| DeclAttrKind DK); |
| |
| /// Parse a version tuple of the form x[.y[.z]]. Returns true if there was |
| /// an error parsing. |
| bool parseVersionTuple(llvm::VersionTuple &Version, SourceRange &Range, |
| const Diagnostic &D); |
| bool parseTypeAttributeList(ParamDecl::Specifier &Specifier, |
| SourceLoc &SpecifierLoc, |
| TypeAttributes &Attributes); |
| ParserStatus parseTypeAttributeListSyntax(Optional<ParsedTokenSyntax> &specifier, |
| Optional<ParsedAttributeListSyntax> &attrs); |
| ParsedSyntaxResult<ParsedAttributeSyntax> parseTypeAttributeSyntax(); |
| |
| ParserResult<ImportDecl> parseDeclImport(ParseDeclOptions Flags, |
| DeclAttributes &Attributes); |
| ParserStatus parseInheritance(MutableArrayRef<TypeLoc> &Inherited, |
| bool allowClassRequirement, |
| bool allowAnyObject); |
| ParserStatus parseDeclItem(bool &PreviousHadSemi, |
| Parser::ParseDeclOptions Options, |
| llvm::function_ref<void(Decl*)> handler); |
| std::vector<Decl *> parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, |
| Diag<> ErrorDiag, ParseDeclOptions Options, |
| IterableDeclContext *IDC, |
| bool &hadError); |
| ParserResult<ExtensionDecl> parseDeclExtension(ParseDeclOptions Flags, |
| DeclAttributes &Attributes); |
| ParserResult<EnumDecl> parseDeclEnum(ParseDeclOptions Flags, |
| DeclAttributes &Attributes); |
| ParserResult<EnumCaseDecl> |
| parseDeclEnumCase(ParseDeclOptions Flags, DeclAttributes &Attributes, |
| SmallVectorImpl<Decl *> &decls); |
| ParserResult<StructDecl> |
| parseDeclStruct(ParseDeclOptions Flags, DeclAttributes &Attributes); |
| ParserResult<ClassDecl> |
| parseDeclClass(ParseDeclOptions Flags, DeclAttributes &Attributes); |
| ParserResult<PatternBindingDecl> |
| parseDeclVar(ParseDeclOptions Flags, DeclAttributes &Attributes, |
| SmallVectorImpl<Decl *> &Decls, |
| SourceLoc StaticLoc, |
| StaticSpellingKind StaticSpelling, |
| SourceLoc TryLoc, |
| bool HasLetOrVarKeyword = true); |
| |
| struct ParsedAccessors; |
| ParserStatus parseGetSet(ParseDeclOptions Flags, |
| GenericParamList *GenericParams, |
| ParameterList *Indices, |
| ParsedAccessors &accessors, |
| AbstractStorageDecl *storage, |
| SourceLoc StaticLoc); |
| ParserResult<VarDecl> parseDeclVarGetSet(Pattern *pattern, |
| ParseDeclOptions Flags, |
| SourceLoc StaticLoc, |
| StaticSpellingKind StaticSpelling, |
| SourceLoc VarLoc, |
| bool hasInitializer, |
| const DeclAttributes &Attributes, |
| SmallVectorImpl<Decl *> &Decls); |
| |
| void consumeAbstractFunctionBody(AbstractFunctionDecl *AFD, |
| const DeclAttributes &Attrs); |
| ParserResult<FuncDecl> parseDeclFunc(SourceLoc StaticLoc, |
| StaticSpellingKind StaticSpelling, |
| ParseDeclOptions Flags, |
| DeclAttributes &Attributes, |
| bool HasFuncKeyword = true); |
| void parseAbstractFunctionBody(AbstractFunctionDecl *AFD); |
| BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD); |
| ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags, |
| DeclAttributes &Attributes); |
| |
| ParserResult<SubscriptDecl> |
| parseDeclSubscript(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, |
| ParseDeclOptions Flags, DeclAttributes &Attributes, |
| SmallVectorImpl<Decl *> &Decls); |
| |
| ParserResult<ConstructorDecl> |
| parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes); |
| ParserResult<DestructorDecl> |
| parseDeclDeinit(ParseDeclOptions Flags, DeclAttributes &Attributes); |
| |
| void addPatternVariablesToScope(ArrayRef<Pattern *> Patterns); |
| void addParametersToScope(ParameterList *PL); |
| |
| ParserResult<OperatorDecl> parseDeclOperator(ParseDeclOptions Flags, |
| DeclAttributes &Attributes); |
| ParserResult<OperatorDecl> parseDeclOperatorImpl(SourceLoc OperatorLoc, |
| Identifier Name, |
| SourceLoc NameLoc, |
| DeclAttributes &Attrs); |
| |
| ParserResult<PrecedenceGroupDecl> |
| parseDeclPrecedenceGroup(ParseDeclOptions flags, DeclAttributes &attributes); |
| |
| ParserResult<TypeRepr> parseDeclResultType(Diag<> MessageID); |
| |
| /// Get the location for a type error. |
| SourceLoc getTypeErrorLoc() const; |
| |
| //===--------------------------------------------------------------------===// |
| // Type Parsing |
| |
| ParserResult<TypeRepr> parseType(); |
| ParserResult<TypeRepr> parseType(Diag<> MessageID, |
| bool HandleCodeCompletion = true, |
| bool IsSILFuncDecl = false); |
| ParserStatus parseGenericArguments(llvm::SmallVectorImpl<TypeRepr *> &ArgsAST, |
| SourceLoc &LAngleLoc, |
| SourceLoc &RAngleLoc); |
| TypeRepr *applyAttributeToType(TypeRepr *Ty, const TypeAttributes &Attr, |
| ParamDecl::Specifier Specifier, |
| SourceLoc SpecifierLoc); |
| ParserResult<TypeRepr> parseAnyTypeAST(); |
| |
| ParsedSyntaxResult<ParsedLayoutConstraintSyntax> |
| parseLayoutConstraintSyntax(); |
| |
| ParsedSyntaxResult<ParsedTypeSyntax> parseTypeSyntax(); |
| ParsedSyntaxResult<ParsedTypeSyntax> |
| parseTypeSyntax(Diag<> MessageID, bool HandleCodeCompletion = true, |
| bool IsSILFuncDecl = false); |
| |
| ParsedSyntaxResult<ParsedGenericArgumentClauseSyntax> |
| parseGenericArgumentClauseSyntax(); |
| |
| ParsedSyntaxResult<ParsedTypeSyntax> |
| parseTypeSimple(Diag<> MessageID, bool HandleCodeCompletion); |
| ParsedSyntaxResult<ParsedTypeSyntax> |
| parseTypeSimpleOrComposition(Diag<> MessageID, bool HandleCodeCompletion); |
| // SWIFT_ENABLE_TENSORFLOW: Added `isParsingQualifiedDeclName` flag. |
| /// Parses a type identifier (e.g. 'Foo' or 'Foo.Bar.Baz'). |
| /// |
| /// When `isParsingQualifiedDeclName` is true: |
| /// - Parses the type qualifier from a qualified decl name, and returns a |
| /// parser result for the type of the qualifier. |
| /// - Positions the parser at the '.' before the final declaration name. |
| /// - For example, 'Foo.Bar.f' parses as 'Foo.Bar' and the parser gets |
| /// positioned at '.f'. |
| /// - If there is no type qualification (e.g. when parsing just 'f'), returns |
| /// an empty parser error. |
| ParsedSyntaxResult<ParsedTypeSyntax> parseTypeIdentifier(bool isParsingQualifiedDeclName = false); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseAnyType(); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseTypeTupleBody(); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseTypeCollection(); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseMetatypeType(ParsedTypeSyntax Base); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseOptionalType(ParsedTypeSyntax Base); |
| ParsedSyntaxResult<ParsedTypeSyntax> |
| parseImplicitlyUnwrappedOptionalType(ParsedTypeSyntax Base); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseSILBoxTypeSyntax( |
| Optional<ParsedGenericParameterClauseListSyntax> genericParams); |
| |
| ParsedSyntaxResult<ParsedTypeSyntax> parseTypeArray(ParsedTypeSyntax Base, |
| SourceLoc BaseLoc); |
| ParsedSyntaxResult<ParsedTypeSyntax> parseOldStyleProtocolComposition(); |
| |
| bool isOptionalToken(const Token &T) const; |
| ParsedTokenSyntax consumeOptionalTokenSyntax(); |
| SourceLoc consumeOptionalToken(); |
| |
| bool isImplicitlyUnwrappedOptionalToken(const Token &T) const; |
| ParsedTokenSyntax consumeImplicitlyUnwrappedOptionalTokenSyntax(); |
| SourceLoc consumeImplicitlyUnwrappedOptionalToken(); |
| |
| ParsedSyntaxResult<ParsedTypeSyntax> |
| applyAttributeToTypeSyntax(ParsedSyntaxResult<ParsedTypeSyntax> &&ty, |
| Optional<ParsedTokenSyntax> specifier, |
| Optional<ParsedAttributeListSyntax> attrs); |
| |
| //===--------------------------------------------------------------------===// |
| // Pattern Parsing |
| |
| /// A structure for collecting information about the default |
| /// arguments of a context. |
| struct DefaultArgumentInfo { |
| llvm::SmallVector<DefaultArgumentInitializer *, 4> ParsedContexts; |
| unsigned NextIndex : 31; |
| |
| /// Track whether or not one of the parameters in a signature's argument |
| /// list accepts a default argument. |
| unsigned HasDefaultArgument : 1; |
| |
| /// Claim the next argument index. It's important to do this for |
| /// all the arguments, not just those that have default arguments. |
| unsigned claimNextIndex() { return NextIndex++; } |
| |
| /// Set the parsed context of all default argument initializers to |
| /// the given function, enum case or subscript. |
| void setFunctionContext(DeclContext *DC, ParameterList *paramList); |
| |
| DefaultArgumentInfo() { |
| NextIndex = 0; |
| HasDefaultArgument = false; |
| } |
| }; |
| |
| /// Describes a parsed parameter. |
| struct ParsedParameter { |
| /// Any declaration attributes attached to the parameter. |
| DeclAttributes Attrs; |
| |
| /// The location of the 'inout' keyword, if present. |
| SourceLoc SpecifierLoc; |
| |
| /// The parsed specifier kind, if present. |
| ParamDecl::Specifier SpecifierKind = ParamDecl::Specifier::Default; |
| |
| /// The location of the first name. |
| /// |
| /// \c FirstName is the name. |
| SourceLoc FirstNameLoc; |
| |
| /// The location of the second name, if present. |
| /// |
| /// \p SecondName is the name. |
| SourceLoc SecondNameLoc; |
| |
| /// The location of the '...', if present. |
| SourceLoc EllipsisLoc; |
| |
| /// The first name. |
| Identifier FirstName; |
| |
| /// The second name, the presence of which is indicated by \c SecondNameLoc. |
| Identifier SecondName; |
| |
| /// The type following the ':'. |
| TypeRepr *Type = nullptr; |
| |
| /// The default argument for this parameter. |
| Expr *DefaultArg = nullptr; |
| |
| /// True if this parameter inherits a default argument via '= super' |
| bool hasInheritedDefaultArg = false; |
| |
| /// True if we emitted a parse error about this parameter. |
| bool isInvalid = false; |
| }; |
| |
| /// Describes the context in which the given parameter is being parsed. |
| enum class ParameterContextKind { |
| /// An operator. |
| Operator, |
| /// A function. |
| Function, |
| /// An initializer. |
| Initializer, |
| /// A closure. |
| Closure, |
| /// A subscript. |
| Subscript, |
| /// A curried argument clause. |
| Curried, |
| /// An enum element. |
| EnumElement, |
| }; |
| |
| /// Parse a parameter-clause. |
| /// |
| /// \verbatim |
| /// parameter-clause: |
| /// '(' ')' |
| /// '(' parameter (',' parameter)* '...'? )' |
| /// |
| /// parameter: |
| /// 'inout'? ('let' | 'var')? '`'? identifier-or-none identifier-or-none? |
| /// (':' type)? ('...' | '=' expr)? |
| /// |
| /// identifier-or-none: |
| /// identifier |
| /// '_' |
| /// \endverbatim |
| ParserStatus parseParameterClause(SourceLoc &leftParenLoc, |
| SmallVectorImpl<ParsedParameter> ¶ms, |
| SourceLoc &rightParenLoc, |
| DefaultArgumentInfo *defaultArgs, |
| ParameterContextKind paramContext); |
| |
| ParserResult<ParameterList> parseSingleParameterClause( |
| ParameterContextKind paramContext, |
| SmallVectorImpl<Identifier> *namePieces = nullptr, |
| DefaultArgumentInfo *defaultArgs = nullptr); |
| |
| ParserStatus parseFunctionArguments(SmallVectorImpl<Identifier> &NamePieces, |
| ParameterList *&BodyParams, |
| ParameterContextKind paramContext, |
| DefaultArgumentInfo &defaultArgs); |
| ParserStatus parseFunctionSignature(Identifier functionName, |
| DeclName &fullName, |
| ParameterList *&bodyParams, |
| DefaultArgumentInfo &defaultArgs, |
| SourceLoc &throws, |
| bool &rethrows, |
| TypeRepr *&retType); |
| |
| //===--------------------------------------------------------------------===// |
| // Pattern Parsing |
| |
| ParserResult<Pattern> parseTypedPattern(); |
| ParserResult<Pattern> parsePattern(); |
| |
| /// Parse a tuple pattern element. |
| /// |
| /// \code |
| /// pattern-tuple-element: |
| /// pattern ('=' expr)? |
| /// \endcode |
| /// |
| /// \returns The tuple pattern element, if successful. |
| std::pair<ParserStatus, Optional<TuplePatternElt>> |
| parsePatternTupleElement(); |
| ParserResult<Pattern> parsePatternTuple(); |
| |
| ParserResult<Pattern> |
| parseOptionalPatternTypeAnnotation(ParserResult<Pattern> P, |
| bool isOptional); |
| ParserResult<Pattern> parseMatchingPattern(bool isExprBasic); |
| ParserResult<Pattern> parseMatchingPatternAsLetOrVar(bool isLet, |
| SourceLoc VarLoc, |
| bool isExprBasic); |
| |
| |
| Pattern *createBindingFromPattern(SourceLoc loc, Identifier name, |
| VarDecl::Introducer introducer); |
| |
| |
| /// Determine whether this token can only start a matching pattern |
| /// production and not an expression. |
| bool isOnlyStartOfMatchingPattern(); |
| |
| //===--------------------------------------------------------------------===// |
| // Speculative type list parsing |
| //===--------------------------------------------------------------------===// |
| |
| /// Returns true if we can parse a generic argument list at the current |
| /// location in expression context. This parses types without generating |
| /// AST nodes from the '<' at the current location up to a matching '>'. If |
| /// the type list parse succeeds, and the closing '>' is followed by one |
| /// of the following tokens: |
| /// lparen_following rparen lsquare_following rsquare lbrace rbrace |
| /// period_following comma semicolon |
| /// then this function returns true, and the expression will parse as a |
| /// generic parameter list. If the parse fails, or the closing '>' is not |
| /// followed by one of the above tokens, then this function returns false, |
| /// and the expression will parse with the '<' as an operator. |
| bool canParseAsGenericArgumentList(); |
| |
| bool canParseType(); |
| bool canParseTypeIdentifier(); |
| bool canParseTypeIdentifierOrTypeComposition(); |
| bool canParseOldStyleProtocolComposition(); |
| bool canParseTypeTupleBody(); |
| bool canParseTypeAttribute(); |
| bool canParseGenericArguments(); |
| |
| bool canParseTypedPattern(); |
| |
| // SWIFT_ENABLE_TENSORFLOW |
| /// Determines whether a type qualifier for a decl name can be parsed. e.g.: |
| /// 'Foo.f' -> true |
| /// 'Foo.Bar.f' -> true |
| /// 'f' -> false |
| bool canParseTypeQualifierForDeclName(); |
| |
| //===--------------------------------------------------------------------===// |
| // Expression Parsing |
| ParserResult<Expr> parseExpr(Diag<> ID) { |
| return parseExprImpl(ID, /*isExprBasic=*/false); |
| } |
| ParserResult<Expr> parseExprBasic(Diag<> ID) { |
| return parseExprImpl(ID, /*isExprBasic=*/true); |
| } |
| ParserResult<Expr> parseExprImpl(Diag<> ID, bool isExprBasic); |
| ParserResult<Expr> parseExprIs(); |
| ParserResult<Expr> parseExprAs(); |
| ParserResult<Expr> parseExprArrow(); |
| ParserResult<Expr> parseExprSequence(Diag<> ID, |
| bool isExprBasic, |
| bool isForConditionalDirective = false); |
| ParserResult<Expr> parseExprSequenceElement(Diag<> ID, |
| bool isExprBasic); |
| ParserResult<Expr> parseExprPostfixSuffix(ParserResult<Expr> inner, |
| bool isExprBasic, |
| bool periodHasKeyPathBehavior, |
| bool &hasBindOptional); |
| ParserResult<Expr> parseExprPostfix(Diag<> ID, bool isExprBasic); |
| ParserResult<Expr> parseExprPrimary(Diag<> ID, bool isExprBasic); |
| ParserResult<Expr> parseExprUnary(Diag<> ID, bool isExprBasic); |
| ParserResult<Expr> parseExprKeyPathObjC(); |
| ParserResult<Expr> parseExprKeyPath(); |
| ParserResult<Expr> parseExprSelector(); |
| ParserResult<Expr> parseExprSuper(); |
| ParserResult<Expr> parseExprStringLiteral(); |
| |
| // todo [gsoc]: create new result type for ParsedSyntax |
| // todo [gsoc]: turn into proper non-templated methods later |
| template <typename SyntaxNode> |
| ParsedExprSyntax parseExprSyntax(); |
| |
| // todo [gsoc]: remove when possible |
| template <typename SyntaxNode> |
| ParserResult<Expr> parseExprAST(); |
| |
| StringRef copyAndStripUnderscores(StringRef text); |
| |
| ParserStatus parseStringSegments(SmallVectorImpl<Lexer::StringSegment> &Segments, |
| Token EntireTok, |
| VarDecl *InterpolationVar, |
| SmallVectorImpl<ASTNode> &Stmts, |
| unsigned &LiteralCapacity, |
| unsigned &InterpolationCount); |
| |
| /// Parse an argument label `identifier ':'`, if it exists. |
| /// |
| /// \param name The parsed name of the label (empty if it doesn't exist, or is |
| /// _) |
| /// \param loc The location of the label (empty if it doesn't exist) |
| void parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc); |
| bool parseOptionalArgumentLabelSyntax(Optional<ParsedTokenSyntax> &name, |
| Optional<ParsedTokenSyntax> &colon); |
| |
| /// Parse an unqualified-decl-name. |
| /// |
| /// unqualified-decl-name: |
| /// identifier |
| /// identifier '(' ((identifier | '_') ':') + ')' |
| /// |
| /// \param afterDot Whether this identifier is coming after a period, which |
| /// enables '.init' and '.default' like expressions. |
| /// \param loc Will be populated with the location of the name. |
| /// \param diag The diagnostic to emit if this is not a name. |
| /// \param allowOperators Whether to allow operator basenames too. |
| /// \param allowZeroArgCompoundNames Whether to allow empty argument lists. |
| DeclName parseUnqualifiedDeclName(bool afterDot, DeclNameLoc &loc, |
| const Diagnostic &diag, |
| bool allowOperators=false, |
| bool allowZeroArgCompoundNames=false, |
| bool allowDeinitAndSubscript=false); |
| ParserStatus |
| parseUnqualifiedDeclNameSyntax(Optional<ParsedTokenSyntax> &identTok, |
| Optional<ParsedDeclNameArgumentsSyntax> &declNameArg, |
| bool afterDot, const Diagnostic &diag, |
| bool allowOperators=false, |
| bool allowZeroArgCompoundNames=false, |
| bool allowDeinitAndSubscript=false); |
| |
| ParsedSyntaxResult<ParsedExprSyntax> parseExprIdentifierSyntax(); |
| ParsedSyntaxResult<ParsedExprSyntax> |
| parseExprSpecializeSyntax(ParsedExprSyntax &&); |
| |
| Expr *parseExprIdentifier(); |
| Expr *parseExprEditorPlaceholder(SourceLoc loc, StringRef text); |
| |
| /// Parse a closure expression after the opening brace. |
| /// |
| /// \verbatim |
| /// expr-closure: |
| /// '{' closure-signature? brace-item-list* '}' |
| /// |
| /// closure-signature: |
| /// '|' closure-signature-arguments? '|' closure-signature-result? |
| /// |
| /// closure-signature-arguments: |
| /// pattern-tuple-element (',' pattern-tuple-element)* |
| /// |
| /// closure-signature-result: |
| /// '->' type |
| /// \endverbatim |
| ParserResult<Expr> parseExprClosure(); |
| |
| /// Parse the closure signature, if present. |
| /// |
| /// \verbatim |
| /// closure-signature: |
| /// parameter-clause func-signature-result? 'in' |
| /// identifier (',' identifier)* func-signature-result? 'in' |
| /// \endverbatim |
| /// |
| /// \param captureList The entries in the capture list. |
| /// \param params The parsed parameter list, or null if none was provided. |
| /// \param arrowLoc The location of the arrow, if present. |
| /// \param explicitResultType The explicit result type, if specified. |
| /// \param inLoc The location of the 'in' keyword, if present. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool parseClosureSignatureIfPresent( |
| SmallVectorImpl<CaptureListEntry> &captureList, |
| ParameterList *¶ms, |
| SourceLoc &throwsLoc, |
| SourceLoc &arrowLoc, |
| TypeRepr *&explicitResultType, |
| SourceLoc &inLoc); |
| |
| Expr *parseExprAnonClosureArg(); |
| ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok, |
| syntax::SyntaxKind Kind); |
| |
| /// Parse an expression list, keeping all of the pieces separated. |
| ParserStatus parseExprList(tok leftTok, tok rightTok, |
| bool isPostfix, |
| bool isExprBasic, |
| SourceLoc &leftLoc, |
| SmallVectorImpl<Expr *> &exprs, |
| SmallVectorImpl<Identifier> &exprLabels, |
| SmallVectorImpl<SourceLoc> &exprLabelLocs, |
| SourceLoc &rightLoc, |
| Expr *&trailingClosure, |
| syntax::SyntaxKind Kind); |
| |
| ParserResult<Expr> parseTrailingClosure(SourceRange calleeRange); |
| |
| /// Parse an object literal. |
| /// |
| /// \param LK The literal kind as determined by the first token. |
| ParserResult<Expr> parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LK, |
| bool isExprBasic); |
| ParserResult<Expr> parseExprQuoteLiteral(); |
| ParserResult<Expr> parseExprUnquote(); |
| ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn, |
| bool isExprBasic); |
| ParserResult<Expr> parseExprCollection(); |
| ParserResult<Expr> parseExprCollectionElement(Optional<bool> &isDictionary); |
| ParserResult<Expr> parseExprPoundAssert(); |
| ParserResult<Expr> parseExprArray(SourceLoc LSquareLoc); |
| ParserResult<Expr> parseExprDictionary(SourceLoc LSquareLoc); |
| ParserResult<Expr> parseExprPoundUnknown(SourceLoc LSquareLoc); |
| ParserResult<Expr> |
| parseExprPoundCodeCompletion(Optional<StmtKind> ParentKind); |
| |
| UnresolvedDeclRefExpr *parseExprOperator(); |
| |
| void validateCollectionElement(ParserResult<Expr> element); |
| |
| //===--------------------------------------------------------------------===// |
| // Statement Parsing |
| |
| bool isStartOfStmt(); |
| bool isTerminatorForBraceItemListKind(BraceItemListKind Kind, |
| ArrayRef<ASTNode> ParsedDecls); |
| ParserResult<Stmt> parseStmt(); |
| ParserStatus parseExprOrStmt(ASTNode &Result); |
| ParserResult<Stmt> parseStmtBreak(); |
| ParserResult<Stmt> parseStmtContinue(); |
| ParserResult<Stmt> parseStmtReturn(SourceLoc tryLoc); |
| ParserResult<Stmt> parseStmtYield(SourceLoc tryLoc); |
| ParserResult<Stmt> parseStmtThrow(SourceLoc tryLoc); |
| ParserResult<Stmt> parseStmtDefer(); |
| ParserStatus |
| parseStmtConditionElement(SmallVectorImpl<StmtConditionElement> &result, |
| Diag<> DefaultID, StmtKind ParentKind, |
| StringRef &BindingKindStr); |
| ParserStatus parseStmtCondition(StmtCondition &Result, Diag<> ID, |
| StmtKind ParentKind); |
| ParserResult<PoundAvailableInfo> parseStmtConditionPoundAvailable(); |
| ParserResult<Stmt> parseStmtIf(LabeledStmtInfo LabelInfo, |
| bool IfWasImplicitlyInserted = false); |
| ParserResult<Stmt> parseStmtGuard(); |
| ParserResult<Stmt> parseStmtWhile(LabeledStmtInfo LabelInfo); |
| ParserResult<Stmt> parseStmtRepeat(LabeledStmtInfo LabelInfo); |
| ParserResult<Stmt> parseStmtDo(LabeledStmtInfo LabelInfo); |
| ParserResult<CatchStmt> parseStmtCatch(); |
| ParserResult<Stmt> parseStmtForEach(LabeledStmtInfo LabelInfo); |
| ParserResult<Stmt> parseStmtSwitch(LabeledStmtInfo LabelInfo); |
| ParserStatus parseStmtCases(SmallVectorImpl<ASTNode> &cases, bool IsActive); |
| ParserResult<CaseStmt> parseStmtCase(bool IsActive); |
| ParserResult<Stmt> parseStmtPoundAssert(); |
| |
| //===--------------------------------------------------------------------===// |
| // Generics Parsing |
| |
| ParserResult<GenericParamList> parseSILGenericParams(); |
| |
| ParserStatus parseSILGenericParamsSyntax( |
| Optional<ParsedGenericParameterClauseListSyntax> &result); |
| |
| ParsedSyntaxResult<ParsedGenericParameterClauseSyntax> |
| parseGenericParameterClauseSyntax(); |
| |
| ParsedSyntaxResult<ParsedGenericWhereClauseSyntax> |
| parseGenericWhereClauseSyntax(bool &FirstTypeInComplete, |
| bool AllowLayoutConstraints = false); |
| |
| ParserResult<GenericParamList> parseGenericParameters(); |
| ParserStatus parseGenericParametersBeforeWhere(SourceLoc LAngleLoc, |
| SmallVectorImpl<GenericTypeParamDecl *> &GenericParams); |
| ParserResult<GenericParamList> maybeParseGenericParams(); |
| void |
| diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams, |
| SourceLoc whereLoc); |
| void |
| diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams); |
| |
| enum class WhereClauseKind : unsigned { |
| Declaration, |
| Protocol, |
| AssociatedType |
| }; |
| ParserStatus |
| parseFreestandingGenericWhereClause(GenericParamList *GPList, |
| WhereClauseKind kind=WhereClauseKind::Declaration); |
| |
| ParserStatus parseGenericWhereClause( |
| SourceLoc &WhereLoc, SmallVectorImpl<RequirementRepr> &Requirements, |
| bool &FirstTypeInComplete, bool AllowLayoutConstraints = false); |
| |
| ParserStatus |
| parseProtocolOrAssociatedTypeWhereClause(TrailingWhereClause *&trailingWhere, |
| bool isProtocol); |
| |
| //===--------------------------------------------------------------------===// |
| // Availability Specification Parsing |
| |
| /// Parse a comma-separated list of availability specifications. |
| ParserStatus |
| parseAvailabilitySpecList(SmallVectorImpl<AvailabilitySpec *> &Specs); |
| |
| ParserResult<AvailabilitySpec> parseAvailabilitySpec(); |
| ParserResult<PlatformVersionConstraintAvailabilitySpec> |
| parsePlatformVersionConstraintSpec(); |
| ParserResult<PlatformAgnosticVersionConstraintAvailabilitySpec> |
| parsePlatformAgnosticVersionConstraintSpec(); |
| }; |
| |
| /// Describes a parsed declaration name. |
| struct ParsedDeclName { |
| /// The name of the context of which the corresponding entity should |
| /// become a member. |
| StringRef ContextName; |
| |
| /// The base name of the declaration. |
| StringRef BaseName; |
| |
| /// The argument labels for a function declaration. |
| SmallVector<StringRef, 4> ArgumentLabels; |
| |
| /// Whether this is a function name (vs. a value name). |
| bool IsFunctionName = false; |
| |
| /// Whether this is a getter for the named property. |
| bool IsGetter = false; |
| |
| /// Whether this is a setter for the named property. |
| bool IsSetter = false; |
| |
| /// For a declaration name that makes the declaration into an |
| /// instance member, the index of the "Self" parameter. |
| Optional<unsigned> SelfIndex; |
| |
| /// Determine whether this is a valid name. |
| explicit operator bool() const { return !BaseName.empty(); } |
| |
| /// Whether this declaration name turns the declaration into a |
| /// member of some named context. |
| bool isMember() const { return !ContextName.empty(); } |
| |
| /// Whether the result is translated into an instance member. |
| bool isInstanceMember() const { |
| return isMember() && static_cast<bool>(SelfIndex); |
| } |
| |
| /// Whether the result is translated into a static/class member. |
| bool isClassMember() const { |
| return isMember() && !static_cast<bool>(SelfIndex); |
| } |
| |
| /// Whether this is a property accessor. |
| bool isPropertyAccessor() const { return IsGetter || IsSetter; } |
| |
| /// Whether this is an operator. |
| bool isOperator() const { |
| return Lexer::isOperator(BaseName); |
| } |
| |
| /// Form a declaration name from this parsed declaration name. |
| DeclName formDeclName(ASTContext &ctx) const; |
| }; |
| |
| /// Parse a stringified Swift declaration name, |
| /// e.g. "Foo.translateBy(self:x:y:)". |
| ParsedDeclName parseDeclName(StringRef name) LLVM_READONLY; |
| |
| /// Form a Swift declaration name from its constituent parts. |
| DeclName formDeclName(ASTContext &ctx, |
| StringRef baseName, |
| ArrayRef<StringRef> argumentLabels, |
| bool isFunctionName, |
| bool isInitializer); |
| |
| /// Parse a stringified Swift declaration name, e.g. "init(frame:)". |
| DeclName parseDeclName(ASTContext &ctx, StringRef name); |
| |
| /// Whether a given token can be the start of a decl. |
| bool isKeywordPossibleDeclStart(const Token &Tok); |
| |
| /// Lex and return a vector of `TokenSyntax` tokens, which include |
| /// leading and trailing trivia. |
| std::vector<std::pair<RC<syntax::RawSyntax>, |
| syntax::AbsolutePosition>> |
| tokenizeWithTrivia(const LangOptions &LangOpts, |
| const SourceManager &SM, |
| unsigned BufferID, |
| unsigned Offset = 0, |
| unsigned EndOffset = 0, |
| DiagnosticEngine *Diags = nullptr); |
| } // end namespace swift |
| |
| #endif |