//===--- Parser.cpp - Swift Language Parser -------------------------------===// // // 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 implements the Swift parser. // //===----------------------------------------------------------------------===// #include "swift/Parse/Parser.h" #include "swift/Parse/Lexer.h" #include "swift/Sema/Sema.h" #include "swift/Sema/Scope.h" #include "swift/AST/ASTConsumer.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" #include "swift/AST/Type.h" #include "llvm/Support/SourceMgr.h" #include "llvm/ADT/NullablePtr.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" using namespace swift; using llvm::SMLoc; using llvm::NullablePtr; //===----------------------------------------------------------------------===// // Setup and Helper Methods //===----------------------------------------------------------------------===// Parser::Parser(unsigned BufferID, ASTConsumer &consumer) : Consumer(consumer), SourceMgr(Consumer.getContext().SourceMgr), L(*new Lexer(BufferID, SourceMgr)), S(*new Sema(Consumer.getContext())) { } Parser::~Parser() { delete &L; delete &S; } void Parser::Note(SMLoc Loc, const llvm::Twine &Message) { SourceMgr.PrintMessage(Loc, Message, "note"); } void Parser::Warning(SMLoc Loc, const llvm::Twine &Message) { SourceMgr.PrintMessage(Loc, Message, "warning"); } void Parser::Error(SMLoc Loc, const llvm::Twine &Message) { SourceMgr.PrintMessage(Loc, Message, "error"); } void Parser::ConsumeToken() { assert(Tok.isNot(tok::eof) && "Lexing past eof!"); L.Lex(Tok); } /// SkipUntil - Read tokens until we get to the specified token, then return. /// Because we cannot guarantee that the token will ever occur, this skips to /// some likely good stopping point. /// void Parser::SkipUntil(tok::TokenKind T) { // tok::unknown is a sentinel that means "don't skip". if (T == tok::unknown) return; while (Tok.isNot(tok::eof) && Tok.isNot(T)) { switch (Tok.getKind()) { default: ConsumeToken(); break; // TODO: Handle paren/brace/bracket recovery. } } } //===----------------------------------------------------------------------===// // Primitive Parsing //===----------------------------------------------------------------------===// /// ParseIdentifier - Consume an identifier if present and return its name in /// Result. Otherwise, emit an error and return true. bool Parser::ParseIdentifier(llvm::StringRef &Result,const llvm::Twine &Message, tok::TokenKind SkipToTok) { if (Tok.is(tok::identifier)) { Result = Tok.getText(); ConsumeToken(tok::identifier); return false; } Error(Tok.getLoc(), Message); return true; } /// 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. /// Next, if SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, /// true is returned. bool Parser::ParseToken(tok::TokenKind K, const char *Message, tok::TokenKind SkipToTok) { if (Tok.is(K)) { ConsumeToken(K); return false; } Error(Tok.getLoc(), Message); SkipUntil(SkipToTok); // If we skipped ahead to the missing token and found it, consume it as if // there were no error. if (K == SkipToTok && Tok.is(SkipToTok)) ConsumeToken(); return true; } //===----------------------------------------------------------------------===// // Decl Parsing //===----------------------------------------------------------------------===// /// ParseTranslationUnit /// translation-unit: /// decl-top-level* void Parser::ParseTranslationUnit() { // Prime the lexer. ConsumeToken(); { // The entire translation unit is in a big scope. Scope OuterScope(S.decl); while (Tok.isNot(tok::eof)) { if (Decl *D = ParseDeclTopLevel()) Consumer.HandleTopLevelDecl(D); } } // Notify consumer about the end of the translation unit. Consumer.HandleEndOfTranslationUnit(); } /// ParseDeclTopLevel /// decl-top-level: /// ';' /// decl-oneof /// decl-struct /// decl-func /// decl-typealias /// decl-var Decl *Parser::ParseDeclTopLevel() { switch (Tok.getKind()) { default: Error(Tok.getLoc(), "expected a top level declaration"); break; case tok::semi: ConsumeToken(tok::semi); return 0; // Could do a top-level semi decl. case tok::kw_typealias: if (ParseDeclTypeAlias()) break; return 0; case tok::kw_oneof: if (OneOfDecl *O = ParseDeclOneOf()) return O; break; case tok::kw_struct: if (OneOfDecl *D = ParseDeclStruct()) return D; break; case tok::kw_func: if (FuncDecl *D = ParseDeclFunc()) { S.decl.ActOnTopLevelDecl(D); return D; } break; case tok::kw_var: if (VarDecl *D = ParseDeclVar()) { S.decl.ActOnTopLevelDecl(D); return D; } break; } S.decl.ActOnTopLevelDeclError(); // On error, skip to the next top level declaration. while (Tok.isNot(tok::eof) && Tok.isNot(tok::kw_var) && Tok.isNot(tok::kw_func)) ConsumeToken(); return 0; } /// ParseAttribute /// attribute: /// 'infix' '=' numeric_constant bool Parser::ParseAttribute(DeclAttributes &Attributes) { if (Tok.is(tok::identifier) && Tok.getText() == "infix") { if (Attributes.InfixPrecedence != -1) Error(Tok.getLoc(), "infix precedence repeatedly specified"); ConsumeToken(tok::identifier); // The default infix precedence is 100. Attributes.InfixPrecedence = 100; if (ConsumeIf(tok::equal)) { SMLoc PrecLoc = Tok.getLoc(); llvm::StringRef Text = Tok.getText(); if (!ParseToken(tok::numeric_constant, "expected precedence number in 'infix' attribute")) { long long Value; if (Text.getAsInteger(10, Value) || Value > 255 || Value < 0) Error(PrecLoc, "invalid precedence: value must be between 0 and 255"); else Attributes.InfixPrecedence = Value; } } return false; } Error(Tok.getLoc(), "unknown declaration attribute"); SkipUntil(tok::r_square); return true; } /// ParseAttributeList /// attribute-list: /// '[' ']' /// '[' attribute (',' attribute)* ']' void Parser::ParseAttributeList(DeclAttributes &Attributes) { Attributes.LSquareLoc = Tok.getLoc(); ConsumeToken(tok::l_square); // If this is an empty attribute list, consume it and return. if (Tok.is(tok::r_square)) { Attributes.RSquareLoc = Tok.getLoc(); ConsumeToken(tok::r_square); return; } bool HadError = ParseAttribute(Attributes); while (Tok.is(tok::comma)) { ConsumeToken(tok::comma); HadError |= ParseAttribute(Attributes); } Attributes.RSquareLoc = Tok.getLoc(); if (ConsumeIf(tok::r_square)) return; // Otherwise, there was an error parsing the attribute list. If we already // reported an error, skip to a ], otherwise report the error. if (!HadError) ParseToken(tok::r_square, "expected ']' or ',' in attribute list", tok::r_square); else { SkipUntil(tok::r_square); ConsumeIf(tok::r_square); } } /// NameRecord - This represents either a single identifier or a tree with /// children. namespace swift { class NameRecord { public: Identifier Name; // In the identifier case, this is the identifier. llvm::SMLoc Loc; // This is the first character of this name record. unsigned NumChildren; NameRecord *Children; NameRecord() : NumChildren(0), Children(0) {} }; } /// ParseVarName /// var-name: /// identifier /// '(' ')' /// '(' name (',' name)* ')' bool Parser::ParseVarName(NameRecord &Record) { Record.Loc = Tok.getLoc(); // Single name case. if (Tok.is(tok::identifier)) { Record.Name = S.Context.getIdentifier(Tok.getText()); ConsumeToken(tok::identifier); return false; } if (ParseToken(tok::l_paren, "expected identifier or '(' in var name")) return true; llvm::SmallVector ChildNames; if (Tok.isNot(tok::r_paren)) { do { ChildNames.push_back(NameRecord()); if (ParseVarName(ChildNames.back())) return true; } while (ConsumeIf(tok::comma)); } Record.Children = (NameRecord *)S.Context.Allocate(sizeof(NameRecord)*ChildNames.size(), 8); memcpy(Record.Children, ChildNames.data(), sizeof(NameRecord)*ChildNames.size()); Record.NumChildren = ChildNames.size(); if (ParseToken(tok::r_paren, "expected ')' at end of var name")) Note(Record.Loc, "to match this '('"); return false; } /// ParseDeclTypeAlias /// decl-typealias: /// 'typealias' identifier ':' type bool Parser::ParseDeclTypeAlias() { SMLoc TypeAliasLoc = Tok.getLoc(); ConsumeToken(tok::kw_typealias); llvm::StringRef Identifier; Type *Ty = 0; if (ParseIdentifier(Identifier, "expected identifier in var declaration") || ParseToken(tok::colon, "expected ':' in typealias declaration") || ParseType(Ty, "expected type in var declaration")) return true; S.decl.ActOnTypeAlias(TypeAliasLoc, Identifier, Ty); return false; } /// AddElementNamesForVarDecl - This recursive function walks a name specifier /// adding ElementRefDecls for the named subcomponents and checking that types /// match up correctly. static void AddElementNamesForVarDecl(const NameRecord &Name, llvm::SmallVectorImpl &AccessPath, VarDecl *VD, SemaDecl &SD) { // If this is a leaf name, ask sema to create a ElementRefDecl for us with the // specified access path. if (Name.Name.get()) { ValueDecl *END = SD.ActOnElementName(Name.Name, Name.Loc, VD, AccessPath.data(), AccessPath.size()); SD.AddToScope(END); return; } // Otherwise, we have the paren case. Verify that the currently named type // has the right number of elements. If so, we recursively process each. if (SD.CheckAccessPathArity(Name.NumChildren, Name.Loc, VD, AccessPath.data(), AccessPath.size())) return; AccessPath.push_back(0); for (unsigned i = 0, e = Name.NumChildren; i != e; ++i) { AccessPath.back() = i; AddElementNamesForVarDecl(Name.Children[i], AccessPath, VD, SD); } AccessPath.pop_back(); } /// ParseDeclVar - Parse a 'var' declaration, returning null (and doing no /// token skipping) on error. /// /// decl-var: /// 'var' attribute-list? var-name ':' type /// 'var' attribute-list? var-name ':' type '=' expr /// 'var' attribute-list? var-name '=' expr VarDecl *Parser::ParseDeclVar() { SMLoc VarLoc = Tok.getLoc(); ConsumeToken(tok::kw_var); DeclAttributes Attributes; if (Tok.is(tok::l_square)) ParseAttributeList(Attributes); // FIXME: Use ParseTypeTupleElement to parse this once tuple elements are // allowed to have initializers! NameRecord Name; if (ParseVarName(Name)) return 0; Type *Ty = 0; if (ConsumeIf(tok::colon) && ParseType(Ty, "expected type in var declaration")) return 0; NullablePtr Init; if (ConsumeIf(tok::equal)) { if (ParseExpr(Init, "expected expression in var declaration")) return 0; // If there was an expression, but it had a parse error, give the var decl // an artificial int type to avoid chained errors. // FIXME: We really need to distinguish erroneous expr from missing expr in // ActOnVarDecl. if (Init.isNull() && Ty == 0) Ty = S.Context.TheInt32Type; } VarDecl *VD = S.decl.ActOnVarDecl(VarLoc, Name.Name, Ty, Init.getPtrOrNull(), Attributes); if (VD == 0) return 0; // Enter the declaration into the current scope. Since var's are not allowed // to be recursive, so they are entered after its initializer is parsed. This // does mean that stuff like this is different than C: // var x = 1; { var x = x+1; assert(x == 2); } if (Name.Name.get()) S.decl.AddToScope(VD); else { // If there is a more interesting name presented here, then we need to walk // through it and synthesize the decls that reference the var elements as // appropriate. llvm::SmallVector AccessPath; AddElementNamesForVarDecl(Name, AccessPath, VD, S.decl); } return VD; } /// ParseDeclFunc - Parse a 'func' declaration, returning null on error. The /// caller handles this case and does recovery as appropriate. /// /// decl-func: /// 'func' attribute-list? identifier arg-list-type '=' expr /// 'func' attribute-list? identifier arg-list-type expr-brace /// 'func' attribute-list? identifier arg-list-type FuncDecl *Parser::ParseDeclFunc() { SMLoc FuncLoc = Tok.getLoc(); ConsumeToken(tok::kw_func); DeclAttributes Attributes; // FIXME: Implicitly add immutable attribute. if (Tok.is(tok::l_square)) ParseAttributeList(Attributes); llvm::StringRef Identifier; if (ParseIdentifier(Identifier, "expected identifier in func declaration")) return 0; // We force first type of a func declaration to be a tuple for consistency. if (Tok.isNot(tok::l_paren)) { Error(Tok.getLoc(), "expected '(' in argument list of func declaration"); return 0; } Type *FuncTy = 0; if (ParseType(FuncTy)) return 0; // If the parsed function type is not a function, then it is implicitly a // function that returns void. if (!llvm::isa(FuncTy)) FuncTy = S.type.ActOnFunctionType(FuncTy, SMLoc(), S.Context.TheEmptyTupleType); // Build the decl for the function. FuncDecl *FD = S.decl.ActOnFuncDecl(FuncLoc, Identifier, FuncTy, Attributes); // Enter the func into the current scope, which allows it to be visible and // used within its body. if (FD) S.decl.AddToScope(FD); // Enter the arguments for the function into a new function-body scope. We // need this even if there is no function body to detect argument name // duplication. Scope FnBodyScope(S.decl); if (FD) S.decl.CreateArgumentDeclsForFunc(FD); // Then parse the expression. llvm::NullablePtr Body; // Check to see if we have a "= expr" or "{" which is a brace expr. if (ConsumeIf(tok::equal)) { if (ParseExpr(Body, "expected expression parsing func body") || Body.isNull()) return 0; // FIXME: Need to call a new ActOnFuncBodyError? } else if (Tok.is(tok::l_brace)) { if (ParseExprBrace(Body) || Body.isNull()) return 0; // FIXME: Need to call a new ActOnFuncBodyError? } // If this is a declaration, we're done. if (Body.isNull()) return FD; return S.decl.ActOnFuncBody(FD, Body.get()); } /// ParseDeclOneOf - Parse a 'oneof' declaration, returning null (and doing no /// token skipping) on error. /// /// decl-oneof: /// 'oneof' attribute-list? identifier '{' oneof-element-list '}' /// oneof-element-list: /// oneof-element ','? /// oneof-element ',' oneof-element-list /// oneof-element: /// identifier /// identifier type /// OneOfDecl *Parser::ParseDeclOneOf() { SMLoc OneOfLoc = Tok.getLoc(); ConsumeToken(tok::kw_oneof); DeclAttributes Attributes; if (Tok.is(tok::l_square)) ParseAttributeList(Attributes); llvm::StringRef OneOfName; if (ParseIdentifier(OneOfName, "expected identifier in oneof declaration") || ParseToken(tok::l_brace, "expected '{' in oneof declaration")) return 0; Identifier OneOfIdentifier = S.Context.getIdentifier(OneOfName); // Give the information about the decl to Sema. This registers the oneof for // name lookup allowing recursive oneof's. OneOfDecl *TheOneOfDecl = S.decl.ActOnOneOfDecl(OneOfLoc, OneOfIdentifier, Attributes); llvm::SmallVector ElementInfos; // Parse the comma separated list of oneof elements. while (Tok.is(tok::identifier)) { SemaDecl::OneOfElementInfo ElementInfo; ElementInfo.Name = Tok.getText(); ElementInfo.NameLoc = Tok.getLoc(); ElementInfo.EltType = 0; ConsumeToken(tok::identifier); // See if we have a type specifier for this oneof element. If so, parse it. if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_brace)) if (ParseType(ElementInfo.EltType, "expected type while parsing oneof element '" + OneOfName + "'")) { SkipUntil(tok::r_brace); return 0; } ElementInfos.push_back(ElementInfo); // Require comma separation. if (!ConsumeIf(tok::comma)) break; } ParseToken(tok::r_brace, "expected '}' at end of oneof declaration"); S.decl.ActOnCompleteOneOfDecl(TheOneOfDecl, ElementInfos.data(), ElementInfos.size()); return TheOneOfDecl; } /// ParseDeclStruct - Parse a 'struct' declaration, returning null (and doing no /// token skipping) on error. A 'struct' is just syntactic sugar for a oneof /// with a single element. /// /// decl-struct: /// 'struct' attribute-list? identifier type /// OneOfDecl *Parser::ParseDeclStruct() { SMLoc StructLoc = Tok.getLoc(); ConsumeToken(tok::kw_struct); DeclAttributes Attributes; if (Tok.is(tok::l_square)) ParseAttributeList(Attributes); llvm::StringRef StructName; if (ParseIdentifier(StructName, "expected identifier in struct declaration")) return 0; Identifier StructIdentifier = S.Context.getIdentifier(StructName); if (Tok.isNot(tok::l_paren)) { Error(Tok.getLoc(), "expected '(' in struct declaration"); return 0; } Type *Ty = 0; if (ParseType(Ty)) return 0; // If we got here, then the 'struct' is syntactically fine, invoke the // semantic actions for the syntactically expanded oneof declaration. OneOfDecl *TheOneOfDecl = S.decl.ActOnOneOfDecl(StructLoc, StructIdentifier, Attributes); SemaDecl::OneOfElementInfo ElementInfo; ElementInfo.Name = StructName; ElementInfo.NameLoc = StructLoc; ElementInfo.EltType = Ty; S.decl.ActOnCompleteOneOfDecl(TheOneOfDecl, &ElementInfo, 1); // In addition to defining the oneof declaration, structs also inject their // constructor into the global scope. assert(TheOneOfDecl->NumElements == 1 && "Struct has exactly one element"); S.decl.AddToScope(TheOneOfDecl->Elements[0]); return TheOneOfDecl; } //===----------------------------------------------------------------------===// // Type Parsing //===----------------------------------------------------------------------===// /// ParseType /// type: /// type-simple /// type-function /// type-array /// /// type-function: /// type-simple '->' type /// /// type-array: /// type '[' ']' /// type '[' expr ']' /// /// type-simple: /// '__builtin_int32_type' /// identifier /// type-tuple /// bool Parser::ParseType(Type *&Result, const llvm::Twine &Message) { // Parse type-simple first. switch (Tok.getKind()) { case tok::identifier: Result = S.type.ActOnTypeName(Tok.getLoc(), Tok.getText()); if (Result == 0) { Error(Tok.getLoc(), Message); return true; } ConsumeToken(tok::identifier); break; case tok::kw___builtin_int32_type: Result = S.type.ActOnInt32Type(Tok.getLoc()); ConsumeToken(tok::kw___builtin_int32_type); break; case tok::l_paren: if (ParseTypeTuple(Result)) return true; break; default: Error(Tok.getLoc(), Message); return true; } while (1) { // If there is an arrow, parse the rest of the type. SMLoc TokLoc = Tok.getLoc(); if (ConsumeIf(tok::arrow)) { Type *SecondHalf = 0; if (ParseType(SecondHalf, "expected type in result of function type")) return true; Result = S.type.ActOnFunctionType(Result, TokLoc, SecondHalf); continue; } // If there is a square bracket, we have an array. if (ConsumeIf(tok::l_square)) { llvm::NullablePtr Size; if (!Tok.is(tok::r_square) && ParseExpr(Size, "expected expression for array type size")) return true; SMLoc RArrayTok = Tok.getLoc(); if (ParseToken(tok::r_square, "expected ']' in array type")) { Note(TokLoc, "to match this '['"); return true; } Result = S.type.ActOnArrayType(Result, TokLoc, Size.getPtrOrNull(), RArrayTok); continue; } break; } return false; } bool Parser::ParseType(Type *&Result) { return ParseType(Result, "expected type"); } /// ParseTypeTupleElement /// type-tuple-element: /// identifier? ':' type bool Parser::ParseTypeTupleElement(TupleTypeElt &Result) { llvm::StringRef Name; if ((Tok.is(tok::identifier) && ParseIdentifier(Name, "expected identifier in tuple element")) || ParseToken(tok::colon, "expected ':' after tuple element name") || ParseType(Result.Ty, "expected type in tuple element")) return true; Result.Name = S.Context.getIdentifier(Name); return false; } /// ParseTypeTuple /// type-tuple: /// '(' ')' /// '(' type-tuple-element (',' type-tuple-element)* ')' /// bool Parser::ParseTypeTuple(Type *&Result) { assert(Tok.is(tok::l_paren) && "Not start of type tuple"); SMLoc LPLoc = Tok.getLoc(); ConsumeToken(tok::l_paren); llvm::SmallVector Elements; if (Tok.isNot(tok::r_paren)) { bool HadError = false; do { Elements.push_back(TupleTypeElt()); if ((HadError = ParseTypeTupleElement(Elements.back()))) break; } while (ConsumeIf(tok::comma)); if (HadError) { SkipUntil(tok::r_paren); if (Tok.is(tok::r_paren)) ConsumeToken(tok::r_paren); return true; } } SMLoc RPLoc = Tok.getLoc(); if (ParseToken(tok::r_paren, "expected ')' at end of tuple list", tok::r_paren)) { Note(LPLoc, "to match this opening '('"); return true; } Result = S.type.ActOnTupleType(LPLoc, Elements.data(), Elements.size(),RPLoc); return false; } //===----------------------------------------------------------------------===// // Expression Parsing //===----------------------------------------------------------------------===// bool Parser::isStartOfExpr(Token &Tok) const { if (Tok.is(tok::identifier)) { // If this is a binary operator, then it isn't the start of an expr. ValueDecl *VD = S.decl.LookupValueName(S.Context.getIdentifier(Tok.getText())); // Use of undeclared identifier. if (VD == 0) return true; return VD->Attrs.InfixPrecedence == -1; } return Tok.is(tok::numeric_constant) || Tok.is(tok::colon) || Tok.is(tok::l_paren) || Tok.is(tok::l_brace); } /// ParseExpr /// expr: /// expr-single+ bool Parser::ParseExpr(NullablePtr &Result, const char *Message) { llvm::SmallVector SequencedExprs; Expr *LastExpr = 0; do { // Parse the expr-single. Result = 0; if (ParseExprSingle(Result) || Result.isNull()) return true; // Check to see if this juxtaposition is application of a function with its // arguments. If so, bind the function application, otherwise, we have a // sequence. if (LastExpr == 0) LastExpr = Result.get(); else { llvm::PointerIntPair ApplyRes = S.expr.ActOnJuxtaposition(LastExpr, Result.get()); if (!ApplyRes.getInt()) { // Function application. LastExpr = ApplyRes.getPointer(); if (LastExpr == 0) return true; } else { // Sequencing. assert(ApplyRes.getPointer() == 0 && "Sequencing with a result?"); SequencedExprs.push_back(LastExpr); LastExpr = Result.get(); } } } while (isStartOfExpr(Tok)); assert(LastExpr && "Should have parsed at least one valid expression"); // If there is exactly one element in the sequence, it is a degenerate // sequence that just returns the last value anyway, shortcut ActOnSequence. if (SequencedExprs.empty()) { Result = LastExpr; return false; } SequencedExprs.push_back(LastExpr); Result = S.expr.ActOnSequence(SequencedExprs.data(), SequencedExprs.size()); return false; } /// ParseExprSingle /// expr-single: /// expr-primary (binary-operator expr-primary)* bool Parser::ParseExprSingle(llvm::NullablePtr &Result, const char *Message) { return ParseExprPrimary(Result, Message) || ParseExprBinaryRHS(Result); } /// ParseExprPrimary /// expr-primary: /// expr-literal /// expr-identifier /// ':' identifier /// expr-paren /// expr-brace /// expr-field /// expr-subscript /// expr-primary-fn expr-primary /// /// expr-primary-fn: /// expr-primary Type sensitive: iff expr has fn type /// /// expr-literal: /// numeric_constant /// /// expr-field: /// expr-primary '.' identifier /// /// expr-subscript: /// expr-primary '[' expr-single ']' bool Parser::ParseExprPrimary(NullablePtr &Result, const char *Message) { switch (Tok.getKind()) { case tok::numeric_constant: Result = S.expr.ActOnNumericConstant(Tok.getText(), Tok.getLoc()); ConsumeToken(tok::numeric_constant); break; case tok::identifier: // foo and foo::bar if (ParseExprIdentifier(Result)) return true; break; case tok::colon: { // :foo SMLoc ColonLoc = Tok.getLoc(); ConsumeToken(tok::colon); llvm::StringRef Name; SMLoc NameLoc = Tok.getLoc(); if (ParseIdentifier(Name, "expected identifier after ':' expression")) return true; Result = S.expr.ActOnUnresolvedMemberExpr(ColonLoc, NameLoc, Name); break; } case tok::l_paren: if (ParseExprParen(Result)) return true; break; case tok::l_brace: if (ParseExprBrace(Result)) return true; break; default: Error(Tok.getLoc(), Message ? Message : "expected expression"); return true; } // Handle suffix expressions. while (1) { // Check for a .foo suffix. SMLoc TokLoc = Tok.getLoc(); if (ConsumeIf(tok::period)) { if (Tok.isNot(tok::identifier)) { Error(Tok.getLoc(), "expected field name"); return true; } if (!Result.isNull()) Result = S.expr.ActOnDotIdentifier(Result.get(), TokLoc, Tok.getText(), Tok.getLoc()); ConsumeToken(tok::identifier); continue; } // Check for a [expr] suffix. if (ConsumeIf(tok::l_square)) { NullablePtr Idx; if (ParseExprSingle(Idx, "expected expression parsing array index")) return true; SMLoc RLoc = Tok.getLoc(); if (ParseToken(tok::r_square, "expected ']'")) { Note(TokLoc, "to match this '['"); return true; } if (!Result.isNull() && !Idx.isNull()) Result = S.expr.ActOnArraySubscript(Result.get(), TokLoc, Idx.get(), RLoc); } break; } // Okay, we parsed the expression primary and any suffix expressions. If the // result has function type and if this is followed by another expression, // then we have a juxtaposition case which is parsed. Note that this // production is ambiguous with the higher level "expr: expr-single+" // production, as witnessed by examples like: // A + B C * D // Which can be parsed either as: // A + (B C) * D <-- Juxtaposition here // (A + B) (C * D) <-- Juxtaposition in the expr production // This is disambiguated based on whether B has function type or not. while (!Result.isNull() && isStartOfExpr(Tok)) { NullablePtr RHS; switch (S.expr.getJuxtapositionGreediness(Result.get())) { default: assert(0 && "Unknown juxtaposition greediness"); case SemaExpr::JG_NonGreedy: return false; case SemaExpr::JG_LocallyGreedy: if (ParseExprPrimary(RHS, "expected expression after juxtaposed operator") || RHS.isNull()) return true; break; case SemaExpr::JG_Greedy: if (ParseExprSingle(RHS, "expected expression after juxtaposed operator") || RHS.isNull()) return true; break; } llvm::PointerIntPair Op = S.expr.ActOnJuxtaposition(Result.get(), RHS.get()); assert(!Op.getInt() && "ShouldGreedilyJuxtapose guaranteed an apply"); Result = Op.getPointer(); } return false; } /// ParseExprIdentifier - Parse an identifier expression: /// /// expr-identifier: /// identifier /// identifier '::' identifier bool Parser::ParseExprIdentifier(llvm::NullablePtr &Result) { llvm::StringRef Name = Tok.getText(); SMLoc Loc = Tok.getLoc(); ConsumeToken(tok::identifier); if (Tok.isNot(tok::coloncolon)) { Result = S.expr.ActOnIdentifierExpr(Name, Loc); return false; } SMLoc ColonColonLoc = Tok.getLoc(); ConsumeToken(tok::coloncolon); SMLoc Loc2 = Tok.getLoc(); llvm::StringRef Name2; if (ParseIdentifier(Name2, "expected identifier after '" + Name + "::' expression")) return true; Result = S.expr.ActOnScopedIdentifierExpr(Name, Loc, ColonColonLoc, Name2, Loc2); return false; } /// ParseExprParen - Parse a tuple expression. /// /// expr-paren: /// '(' ')' /// '(' expr-paren-element (',' expr-paren-element)* ')' /// /// expr-paren-element: /// ('.' identifier '=')? expr /// bool Parser::ParseExprParen(llvm::NullablePtr &Result) { SMLoc LPLoc = Tok.getLoc(); ConsumeToken(tok::l_paren); llvm::SmallVector SubExprs; llvm::SmallVector SubExprNames; bool AnyErroneousSubExprs = false; if (Tok.isNot(tok::r_paren)) { do { Identifier FieldName; // Check to see if there is a field specifier. if (ConsumeIf(tok::period)) { llvm::StringRef FieldNameStr; if (ParseIdentifier(FieldNameStr, "expected field specifier name in tuple expression")|| ParseToken(tok::equal, "expected '=' in tuple expression")) return true; FieldName = S.Context.getIdentifier(FieldNameStr); } if (!SubExprNames.empty()) SubExprNames.push_back(FieldName); else if (FieldName.get()) { SubExprNames.resize(SubExprs.size()); SubExprNames.push_back(FieldName); } NullablePtr SubExpr; if (ParseExpr(SubExpr, "expected expression in parentheses")) return true; if (SubExpr.isNull()) AnyErroneousSubExprs = true; else SubExprs.push_back(SubExpr.get()); } while (ConsumeIf(tok::comma)); } SMLoc RPLoc = Tok.getLoc(); if (ParseToken(tok::r_paren, "expected ')' in parenthesis expression")) { Note(LPLoc, "to match this opening '('"); return true; } if (!AnyErroneousSubExprs) Result = S.expr.ActOnTupleExpr(LPLoc, SubExprs.data(), SubExprNames.empty()?0 : SubExprNames.data(), SubExprs.size(), RPLoc); return false; } /// ParseExprBrace - A brace enclosed expression list which may optionally end /// with a ; inside of it. For example { 1; 4+5; } or { 1; 2 }. /// /// expr-brace: /// '{' expr-brace-item* '}' /// expr-brace-item: /// expr /// decl-var /// ';' bool Parser::ParseExprBrace(NullablePtr &Result) { SMLoc LBLoc = Tok.getLoc(); ConsumeToken(tok::l_brace); // This brace expression forms a lexical scope. Scope BraceScope(S.decl); llvm::SmallVector, 16> Entries; // MissingSemiAtEnd - Keep track of whether the last expression in the block // had no semicolon. bool MissingSemiAtEnd = false; while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { MissingSemiAtEnd = false; // If this is a semi, eat it and ignore it. if (ConsumeIf(tok::semi)) continue; // Otherwise, we must have a var decl or expression. Parse it up Entries.push_back(llvm::PointerUnion()); // Parse the var or expression. If we have an error, try to do nice // recovery. bool HadError = false; if (Tok.is(tok::kw_var)) { Entries.back() = ParseDeclVar(); if (Entries.back().isNull()) HadError = true; } else { NullablePtr ResultExpr; if (ParseExpr(ResultExpr) || ResultExpr.isNull()) HadError = true; else { Entries.back() = ResultExpr.get(); MissingSemiAtEnd = true; } } if (HadError) { if (Tok.is(tok::semi)) { Entries.pop_back(); continue; // Consume the ';' and keep going. } // FIXME: QOI: Improve error recovery. if (Tok.is(tok::semi) && Tok.isNot(tok::r_brace)) SkipUntil(tok::r_brace); ConsumeIf(tok::r_brace); return true; } } SMLoc RBLoc = Tok.getLoc(); if (ParseToken(tok::r_brace, "expected '}' at end of brace expression", tok::r_brace)) { Note(LBLoc, "to match this opening '{'"); return true; } Result = S.expr.ActOnBraceExpr(LBLoc, Entries.data(), Entries.size(), MissingSemiAtEnd, RBLoc); return false; } /// getBinOp - Return the ValueDecl for the token if it is an infix binary /// operator, otherwise return null. static ValueDecl *getBinOp(const Token &Tok, Sema &S) { if (Tok.isNot(tok::identifier)) return 0; ValueDecl *VD =S.decl.LookupValueName(S.Context.getIdentifier(Tok.getText())); if (VD == 0 || VD->Attrs.InfixPrecedence == -1) return 0; return VD; } /// ParseExprBinaryRHS - Parse the right hand side of a binary expression and /// assemble it according to precedence rules. /// /// expr-binary-rhs: /// (binary-operator expr-primary)* bool Parser::ParseExprBinaryRHS(NullablePtr &Result, unsigned MinPrec) { ValueDecl *NextTokOp = getBinOp(Tok, S); int NextTokPrec = NextTokOp ? NextTokOp->Attrs.InfixPrecedence : -1; // Assignment is a hack until we get generics. Assignment gets the lowest // precedence since it "returns void". if (Tok.is(tok::equal)) NextTokPrec = 1; while (1) { // If this token has a lower precedence than we are allowed to parse (e.g. // because we are called recursively, or because the token is not a binop), // then we are done! if (NextTokPrec < (int)MinPrec) return false; // Consume the operator, saving the operator location. SMLoc OpLoc = Tok.getLoc(); ConsumeToken(); // TODO: Support ternary operators some day. // Parse another leaf here for the RHS of the operator. NullablePtr Leaf; if (ParseExprPrimary(Leaf, "expected expression after binary operator")) return true; // Remember the precedence of this operator and get the precedence of the // operator immediately to the right of the RHS. int ThisPrec = NextTokPrec; ValueDecl *ThisTokOp = NextTokOp; NextTokOp = getBinOp(Tok, S); NextTokPrec = NextTokOp ? NextTokOp->Attrs.InfixPrecedence : -1; if (Tok.is(tok::equal)) NextTokPrec = 1; // TODO: All operators are left associative at the moment. // If the next operator binds more tightly with RHS than we do, evaluate the // RHS as a complete subexpression first if (ThisPrec < NextTokPrec) { // Only parse things on the RHS that bind more tightly than the current // operator. if (ParseExprBinaryRHS(Leaf, ThisPrec + 1)) return true; NextTokOp = getBinOp(Tok, S); NextTokPrec = NextTokOp ? NextTokOp->Attrs.InfixPrecedence : -1; } assert(NextTokPrec <= ThisPrec && "Recursion didn't work!"); // Okay, we've finished the parse, form the AST node for the binop now. if (Result.isNonNull() && Leaf.isNonNull()) Result = S.expr.ActOnBinaryExpr(Result.get(), ThisTokOp, OpLoc, Leaf.get()); } return false; }