//===--- Parser.h - Swift Language Parser -----------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://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/AST.h" #include "swift/AST/Diagnostics.h" #include "swift/Basic/Optional.h" #include "swift/Parse/Lexer.h" #include "swift/Parse/Scope.h" #include "swift/Parse/Token.h" #include "llvm/ADT/SetVector.h" namespace llvm { class SourceMgr; template class PointerUnion3; } namespace swift { class DiagnosticEngine; class Lexer; class ScopeInfo; struct TypeLoc; class TupleType; class SILParserState; class CodeCompletionCallbacks; struct OneOfElementInfo; /// 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 property getter or setter. The list /// is terminated by a closing brace or a 'get:' or 'set:' label. Property, /// 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 }; class Parser { Parser(const Parser&) = delete; void operator=(const Parser&) = delete; public: typedef llvm::PointerUnion3 ExprStmtOrDecl; llvm::SourceMgr &SourceMgr; DiagnosticEngine &Diags; TranslationUnit *TU; Lexer *L; SILParserState *SIL; // Non-null when parsing a .sil file. DeclContext *CurDeclContext; swift::Component *Component; ASTContext &Context; CodeCompletionCallbacks *CodeCompletion = nullptr; ScopeInfo ScopeInfo; std::vector> AnonClosureVars; unsigned VarPatternDepth = 0; bool IsMainModule; /// \brief True if we are doing a second pass over the AST during delayed /// parsing. We should not delay anything in this case. bool IsDelayedParsingSecondPass = false; void setDelayedParsingSecondPass() { IsDelayedParsingSecondPass = true; } void setCodeCompletion(unsigned Offset, CodeCompletionCallbacks *Callbacks) { CodeCompletion = Callbacks; IsDelayedParsingSecondPass = true; L->setCodeCompletion(Offset); } /// Tok - This is the current token being considered by the parser. Token Tok; /// \brief The location of the previous token. SourceLoc PreviousLoc; /// A RAII object for temporarily changing CurDeclContext. class ContextChange { Parser &P; DeclContext *OldContext; public: ContextChange(Parser &P, DeclContext *DC) : P(P), OldContext(P.CurDeclContext) { assert(DC && "pushing null context?"); P.CurDeclContext = DC; } /// Prematurely pop the DeclContext installed by the constructor. /// Makes the destructor a no-op. void pop() { assert(OldContext && "already popped context!"); P.CurDeclContext = OldContext; OldContext = nullptr; } ~ContextChange() { if (OldContext) P.CurDeclContext = OldContext; } }; Parser(unsigned BufferID, TranslationUnit *TU, bool IsMainModule, SILParserState *SIL); Parser(TranslationUnit *TU, llvm::StringRef fragment, DiagnosticEngine &Diags, SILParserState *SIL); ~Parser(); bool isInSILMode() const { return SIL != nullptr; } //===--------------------------------------------------------------------===// // Routines to save and restore parser state. class ParserPosition { public: ParserPosition() = default; ParserPosition &operator=(const ParserPosition &) = default; private: ParserPosition(Lexer::State LS, SourceLoc PreviousLoc): LS(LS), PreviousLoc(PreviousLoc) {} Lexer::State LS; SourceLoc PreviousLoc; friend class Parser; }; ParserPosition getParserPosition() { return ParserPosition(L->getStateForBeginningOfToken(Tok), PreviousLoc); } void restoreParserPosition(ParserPosition PP) { L->restoreState(PP.LS); PreviousLoc = PP.PreviousLoc; // We might be at tok::eof now, so ensure that consumeToken() does not // assert about lexing past eof. Tok.setKind(tok::unknown); consumeToken(); } void backtrackToPosition(ParserPosition PP) { L->backtrackToState(PP.LS); PreviousLoc = PP.PreviousLoc; // We might be at tok::eof now, so ensure that consumeToken() does not // assert about lexing past eof. Tok.setKind(tok::unknown); consumeToken(); } /// 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; public: BacktrackingScope(Parser &P) : P(P), PP(P.getParserPosition()) {} ~BacktrackingScope() { P.backtrackToPosition(PP); } }; /// RAII object for managing 'var' patterns. Inside a 'var' pattern, bare /// identifiers are parsed as new VarDecls instead of references to existing /// ones. class VarPatternScope { Parser &P; public: VarPatternScope(Parser &P) : P(P) { ++P.VarPatternDepth; } ~VarPatternScope() { --P.VarPatternDepth; } }; /// 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); } }; class FunctionBodyParserState { FunctionBodyParserState(ParserPosition BeginParserPosition, SavedScope &&Scope, unsigned Flags): BeginParserPosition(BeginParserPosition), Scope(std::move(Scope)), Flags(Flags) {} ParserPosition BeginParserPosition; SavedScope Scope; unsigned Flags; friend class Parser; SavedScope takeScope() { return std::move(Scope); } }; //===--------------------------------------------------------------------===// // Utilities /// \brief Return the next token that will be installed by \c consumeToken. const Token &peekToken(); SourceLoc consumeToken(); SourceLoc consumeToken(tok K) { assert(Tok.is(K) && "Consuming wrong token kind"); return consumeToken(); } /// \brief Retrieve the location just past the end of the previous /// source location. SourceLoc getEndOfPreviousLoc(); /// consumeIf - 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; } bool consumeIfNotAtStartOfLine(tok K) { if (Tok.isAtStartOfLine()) return false; return consumeIf(K); } /// skipUntil - 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 skipUntil(tok T1, tok T2 = tok::unknown); void skipUntilAnyOperator(); /// skipUntilDeclStmtRBrace - Skip to the next decl or '}'. void skipUntilDeclRBrace(); /// skipUntilDeclStmtRBrace - Skip to the next decl, statement or '}'. void skipUntilDeclStmtRBrace(); private: /// 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 skipSingle(); public: template InFlightDiagnostic diagnose(SourceLoc Loc, ArgTypes... Args) { return Diags.diagnose(Loc, Diagnostic(Args...)); } template InFlightDiagnostic diagnose(Token Tok, ArgTypes... Args) { return Diags.diagnose(Tok.getLoc(), Diagnostic(Args...)); } void diagnoseRedefinition(ValueDecl *Prev, ValueDecl *New); /// \brief Check whether the current token starts with '<'. bool startsWithLess(Token Tok) { return Tok.isAnyOperator() && Tok.getText()[0] == '<'; } /// \brief Check whether the current token starts with '>'. bool startsWithGreater(Token Tok) { return Tok.isAnyOperator() && Tok.getText()[0] == '>'; } /// \brief Consume the starting '<' of the current token, which may either /// be a complete '<' token or some kind of operator token starting with '<', /// e.g., '<>'. SourceLoc consumeStartingLess(); /// \brief Consume the starting '>' of the current token, which may either /// be a complete '>' token or some kind of operator token starting with '>', /// e.g., '>>'. SourceLoc consumeStartingGreater(); //===--------------------------------------------------------------------===// // Primitive Parsing /// parseIdentifier - Consume an identifier (but not an operator) if /// present and return its name in Result. Otherwise, emit an error and /// return true. bool parseIdentifier(Identifier &Result, SourceLoc &Loc, const Diagnostic &D); template bool parseIdentifier(Identifier &Result, Diag ID, ArgTypes... Args) { SourceLoc L; return parseIdentifier(Result, L, Diagnostic(ID, Args...)); } template bool parseIdentifier(Identifier &Result, SourceLoc &L, Diag ID, ArgTypes... Args) { return parseIdentifier(Result, L, Diagnostic(ID, Args...)); } /// parseAnyIdentifier - Consume an identifier or operator if present and /// return its name in Result. Otherwise, emit an error and return true. bool parseAnyIdentifier(Identifier &Result, SourceLoc &Loc, const Diagnostic &D); template bool parseAnyIdentifier(Identifier &Result, Diag ID, ArgTypes... Args) { SourceLoc L; return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...)); } template bool parseAnyIdentifier(Identifier &Result, SourceLoc &L, Diag ID, ArgTypes... Args) { return parseAnyIdentifier(Result, L, Diagnostic(ID, Args...)); } /// parseToken - The parser expects that 'K' is next 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); template bool parseToken(tok K, Diag ID, ArgTypes... Args) { SourceLoc L; return parseToken(K, L, Diagnostic(ID, Args...)); } template bool parseToken(tok K, SourceLoc &L, Diag ID, ArgTypes... Args) { return parseToken(K, L, Diagnostic(ID, Args...)); } /// parseMatchingToken - Parse the specified expected token and return its /// location on success. On failure, emit the specified error diagnostic, and /// a note at the specified note location. bool parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag, SourceLoc OtherLoc); /// parseList - Parse the list of statements, expressions, or declarations. bool parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc, tok SeparatorK, bool OptionalSep, Diag<> ErrorDiag, std::function callback); void parseBraceItems(SmallVectorImpl &Decls, bool IsTopLevel, BraceItemListKind Kind = BraceItemListKind::Brace); NullablePtr parseBraceItemList(Diag<> ID); //===--------------------------------------------------------------------===// // Decl Parsing static bool isStartOfDecl(const Token &Tok, const Token &Tok2); static bool isStartOfOperatorDecl(const Token &Tok, const Token &Tok2); bool parseTranslationUnit(TranslationUnit *TU); bool parseDecl(SmallVectorImpl &Entries, unsigned Flags); enum { PD_Default = 0, PD_AllowTopLevel = 1 << 1, PD_DisallowVar = 1 << 2, PD_HasContainerType = 1 << 3, PD_DisallowProperty = 1 << 4, PD_DisallowNominalTypes = 1 << 5, PD_DisallowFuncDef = 1 << 6, PD_DisallowInit = 1 << 7, PD_DisallowTypeAliasDef = 1 << 8, PD_AllowDestructor = 1 << 9, PD_AllowOneOfElement = 1 << 10, }; TypeAliasDecl *parseDeclTypeAlias(bool WantDefinition); /// addVarsToScope - Add the variables in the given pattern to the current /// scope, collecting the variables in the vector \c Decls and applying /// \c Attributes to each one. void addVarsToScope(Pattern *Pat, SmallVectorImpl &Decls, DeclAttributes &Attributes); bool parseAttributeList(DeclAttributes &Attributes) { if (Tok.is(tok::l_square)) return parseAttributeListPresent(Attributes); return false; } bool parseAttributeListPresent(DeclAttributes &Attributes); bool parseAttribute(DeclAttributes &Attributes); Decl *parseDeclImport(unsigned Flags); bool parseInheritance(SmallVectorImpl &Inherited); Decl *parseDeclExtension(unsigned Flags); bool parseDeclOneOf(unsigned Flags, SmallVectorImpl &Decls); bool parseDeclOneOfElement(unsigned Flags, SmallVectorImpl &Decls); bool parseNominalDeclMembers(SmallVectorImpl &memberDecls, SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag, unsigned flags); bool parseDeclStruct(unsigned Flags, SmallVectorImpl &Decls); bool parseDeclClass(unsigned Flags, SmallVectorImpl &Decls); bool parseDeclVar(unsigned Flags, SmallVectorImpl &Decls); bool parseGetSet(bool HasContainerType, Pattern *Indices, Type ElementTy, FuncDecl *&Get, FuncDecl *&Set, SourceLoc &LastValidLoc); void parseDeclVarGetSet(Pattern &pattern, bool hasContainerType); Pattern *buildImplicitThisParameter(); Optional consumeFunctionBody(unsigned Flags); FuncDecl *parseDeclFunc(unsigned Flags); bool parseDeclFuncBodyDelayed(FuncDecl *FD); Decl *parseDeclProtocol(unsigned Flags); bool parseDeclSubscript(bool HasContainerType, bool NeedDefinition, SmallVectorImpl &Decls); ConstructorDecl *parseDeclConstructor(bool HasContainerType); DestructorDecl *parseDeclDestructor(unsigned Flags); OperatorDecl *parseDeclOperator(bool AllowTopLevel); OperatorDecl *parseDeclPrefixOperator(SourceLoc OperatorLoc, SourceLoc PrefixLoc, Identifier Name, SourceLoc NameLoc); OperatorDecl *parseDeclPostfixOperator(SourceLoc OperatorLoc, SourceLoc PostfixLoc, Identifier Name, SourceLoc NameLoc); OperatorDecl *parseDeclInfixOperator(SourceLoc OperatorLoc, SourceLoc InfixLoc, Identifier Name, SourceLoc NameLoc); //===--------------------------------------------------------------------===// // SIL Parsing. bool parseDeclSIL(); //===--------------------------------------------------------------------===// // Type Parsing bool parseType(TypeLoc &ResultLoc); bool parseType(TypeLoc &ResultLoc, Diag<> ID); bool parseTypeAnnotation(TypeLoc &ResultLoc); bool parseTypeAnnotation(TypeLoc &ResultLoc, Diag<> ID); bool parseGenericArguments(MutableArrayRef &Args, SourceLoc &LAngleLoc, SourceLoc &RAngleLoc); bool parseTypeIdentifier(TypeLoc &ResultLoc); bool parseTypeComposition(TypeLoc &ResultLoc); bool parseTypeTupleBody(TypeLoc &ResultLoc); bool parseTypeArray(TypeLoc &ResultLoc); bool applyAttributeToType(TypeLoc &ResultLoc, DeclAttributes &Attr); //===--------------------------------------------------------------------===// // Pattern Parsing bool parseFunctionArguments(SmallVectorImpl &argPatterns, SmallVectorImpl &bodyPatterns); bool parseFunctionSignature(SmallVectorImpl &argPatterns, SmallVectorImpl &bodyPatterns, TypeLoc &retLoc); NullablePtr parsePattern(); /// \brief Determine whether this token can start a pattern. bool isStartOfPattern(Token tok); /// \brief Determine whether this token can start a binding name, whether an /// identifier or the special discard-value binding '_'. bool isStartOfBindingName(Token tok); /// \brief Parse a tuple pattern element. /// /// \code /// pattern-tuple-element: /// pattern ('=' expr)? /// \endcode /// /// \param allowInitExpr Whether to allow initializers. /// /// \returns The tuple pattern element, if successful. Optional parsePatternTupleElement(bool allowInitExpr); NullablePtr parsePatternTuple(bool AllowInitExpr); NullablePtr parsePatternAtom(); NullablePtr parsePatternIdentifier(); Pattern *createBindingFromPattern(SourceLoc loc, Identifier name); //===--------------------------------------------------------------------===// // Pattern Parsing // TODO: Depending on how robust our distributive-var design works out, we // may be able to integrate exhaustive pattern parsing in var/func decls // with matching pattern parsing when it matures. NullablePtr parseMatchingPattern(); NullablePtr parseMatchingPatternVar(); NullablePtr parseMatchingPatternIsa(); /// \brief 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 canParseTypeComposition(); bool canParseTypeTupleBody(); bool canParseTypeArray(); bool canParseGenericArguments(); //===--------------------------------------------------------------------===// // Expression Parsing // Each of these parsing methods returns null (in a NullablePtr) on a parse // error, or an ErrorExpr on a semantic error. If the method cannot fail, it // returns a raw Expr*. NullablePtr parseExpr(Diag<> ID, bool isExprBasic = false); NullablePtr parseExprBasic(Diag<> ID) { return parseExpr(ID, /*isExprBasic=*/true); } NullablePtr parseExprIs(); NullablePtr parseExprAs(); NullablePtr parseExprSequence(Diag<> ID); NullablePtr parseExprPostfix(Diag<> ID); NullablePtr parseExprUnary(Diag<> ID); NullablePtr parseExprNew(); NullablePtr parseExprSuper(); Expr *parseExprStringLiteral(); Expr *parseExprIdentifier(); /// Parse a closure expression after the opening brace. /// /// 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 Expr *parseExprClosure(); /// Parse the closure signature, if present. /// /// closure-signature: /// pattern-tuple func-signature-result? 'in' /// identifier (',' identifier)* func-signature-result? 'in' /// /// \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(Pattern *¶ms, SourceLoc &arrowLoc, TypeLoc &explicitResultType, SourceLoc &inLoc); Expr *parseExprAnonClosureArg(); NullablePtr parseExprList(tok LeftTok, tok RightTok); NullablePtr parseExprCollection(); NullablePtr parseExprArray(SourceLoc LSquareLoc, Expr *FirstExpr); NullablePtr parseExprDictionary(SourceLoc LSquareLoc, Expr *FirstKey); Expr *parseExprOperator(); Expr *actOnIdentifierExpr(Identifier Text, SourceLoc Loc); FuncExpr *actOnFuncExprStart(SourceLoc FuncLoc, TypeLoc FuncRetTy, ArrayRef ArgPatterns, ArrayRef BodyPatterns); //===--------------------------------------------------------------------===// // Statement Parsing // Each of these returns null (in a NullablePtr) on a parse error, or an // ErrorStmt on a semantic error. static bool isStartOfStmt(const Token &Tok); NullablePtr parseStmt(); bool parseExprOrStmt(ExprStmtOrDecl &Results); NullablePtr parseStmtReturn(); NullablePtr parseStmtIf(); NullablePtr parseStmtWhile(); NullablePtr parseStmtDoWhile(); NullablePtr parseStmtFor(); NullablePtr parseStmtForCStyle(SourceLoc ForLoc); NullablePtr parseStmtForEach(SourceLoc ForLoc); NullablePtr parseStmtSwitch(); NullablePtr parseStmtCase(); bool parseStmtCaseLabels(llvm::SmallVectorImpl &labels, llvm::SmallVectorImpl &boundDecls); //===--------------------------------------------------------------------===// // Generics Parsing GenericParamList *parseGenericParameters(); GenericParamList *parseGenericParameters(SourceLoc LAngleLoc); GenericParamList *maybeParseGenericParams(); bool parseGenericWhereClause(SourceLoc &WhereLoc, SmallVectorImpl &Requirements); }; } // end namespace swift #endif