//===--- ParseExpr.cpp - Swift Language Parser for Expressions ------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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
//
//===----------------------------------------------------------------------===//
//
// Expression Parsing and AST Building
//
//===----------------------------------------------------------------------===//

#include "swift/Parse/Parser.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/EditorPlaceholder.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
#include "swift/Parse/ParsedSyntaxBuilders.h"
#include "swift/Parse/ParsedSyntaxRecorder.h"
#include "swift/Parse/SyntaxParsingContext.h"
#include "swift/Syntax/SyntaxKind.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/StringExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;
using namespace swift::syntax;

/// parseExpr
///
///   expr:
///     expr-sequence(basic | trailing-closure)
///
/// \param isExprBasic Whether we're only parsing an expr-basic.
ParserResult<Expr> Parser::parseExprImpl(Diag<> Message,
                                         bool isExprBasic) {
  // Start a context for creating expression syntax.
  SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr);

  // If we are parsing a refutable pattern, check to see if this is the start
  // of a let/var/is pattern.  If so, parse it to an UnresolvedPatternExpr and
  // name binding will perform final validation.
  //
  // Only do this if we're parsing a pattern, to improve QoI on malformed
  // expressions followed by (e.g.) let/var decls.
  //
  if (InVarOrLetPattern && isOnlyStartOfMatchingPattern()) {
    ParserResult<Pattern> pattern = parseMatchingPattern(/*isExprBasic*/false);
    if (pattern.hasCodeCompletion())
      return makeParserCodeCompletionResult<Expr>();
    if (pattern.isNull())
      return nullptr;
    SyntaxContext->setCreateSyntax(SyntaxKind::UnresolvedPatternExpr);
    return makeParserResult(new (Context) UnresolvedPatternExpr(pattern.get()));
  }
  
  auto expr = parseExprSequence(Message, isExprBasic,
                                /*forConditionalDirective*/false);
  if (expr.hasCodeCompletion())
    return expr;
  if (expr.isNull())
    return nullptr;
  
  return makeParserResult(expr.get());
}

/// parseExprIs
///   expr-is:
///     'is' type
ParserResult<Expr> Parser::parseExprIs() {
  SourceLoc isLoc = consumeToken(tok::kw_is);

  ParserResult<TypeRepr> type = parseType(diag::expected_type_after_is);
  if (type.hasCodeCompletion())
    return makeParserCodeCompletionResult<Expr>();
  if (type.isNull())
    return nullptr;

  return makeParserResult(new (Context) IsExpr(isLoc, type.get()));
}

/// parseExprAs
///   expr-as:
///     'as' type
///     'as?' type
///     'as!' type
ParserResult<Expr> Parser::parseExprAs() {
  // Parse the 'as'.
  SourceLoc asLoc = consumeToken(tok::kw_as);

  // Parse the postfix '?'.
  SourceLoc questionLoc;
  SourceLoc exclaimLoc;
  if (Tok.is(tok::question_postfix)) {
    questionLoc = consumeToken(tok::question_postfix);
  } else if (Tok.is(tok::exclaim_postfix)) {
    exclaimLoc = consumeToken(tok::exclaim_postfix);
  }

  ParserResult<TypeRepr> type = parseType(diag::expected_type_after_as);

  if (type.hasCodeCompletion())
    return makeParserCodeCompletionResult<Expr>();
  if (type.isNull())
    return nullptr;

  Expr *parsed;
  if (questionLoc.isValid()) {
    parsed = new (Context) ConditionalCheckedCastExpr(asLoc, questionLoc,
                                                      type.get());
  } else if (exclaimLoc.isValid()) {
    parsed = new (Context) ForcedCheckedCastExpr(asLoc, exclaimLoc, type.get());
  } else {
    parsed = new (Context) CoerceExpr(asLoc, type.get());
  }
  return makeParserResult(parsed);
}

/// parseExprArrow
///
///   expr-arrow:
///     '->'
///     'throws' '->'
ParserResult<Expr> Parser::parseExprArrow() {
  SourceLoc throwsLoc, arrowLoc;
  if (Tok.is(tok::kw_throws)) {
    throwsLoc = consumeToken(tok::kw_throws);
    if (!Tok.is(tok::arrow)) {
      diagnose(throwsLoc, diag::throws_in_wrong_position);
      return nullptr;
    }
  }
  arrowLoc = consumeToken(tok::arrow);
  if (Tok.is(tok::kw_throws)) {
    diagnose(Tok.getLoc(), diag::throws_in_wrong_position);
    throwsLoc = consumeToken(tok::kw_throws);
  }
  auto arrow = new (Context) ArrowExpr(throwsLoc, arrowLoc);
  return makeParserResult(arrow);
}

/// parseExprSequence
///
///   expr-sequence(Mode):
///     expr-sequence-element(Mode) expr-binary(Mode)*
///   expr-binary(Mode):
///     operator-binary expr-sequence-element(Mode)
///     '?' expr-sequence(Mode) ':' expr-sequence-element(Mode)
///     '=' expr-unary
///     expr-is
///     expr-as
///
/// The sequencing for binary exprs is not structural, i.e., binary operators
/// are not inherently right-associative. If present, '?' and ':' tokens must
/// match.
///
/// Similarly, the parsing of 'try' as part of expr-sequence-element
/// is not structural.  'try' is not permitted at arbitrary points in
/// a sequence; in the places it's permitted, it's hoisted out to
/// apply to everything to its right.
ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
                                             bool isExprBasic,
                                             bool isForConditionalDirective) {
  SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr);

  SmallVector<Expr*, 8> SequencedExprs;
  SourceLoc startLoc = Tok.getLoc();
  bool HasCodeCompletion = false;
  bool PendingTernary = false;

  while (true) {
    if (isForConditionalDirective && Tok.isAtStartOfLine())
      break;

    // Parse a unary expression.
    ParserResult<Expr> Primary =
      parseExprSequenceElement(Message, isExprBasic);

    if (Primary.hasCodeCompletion()) {
      HasCodeCompletion = true;
      if (CodeCompletion)
        CodeCompletion->setLeadingSequenceExprs(SequencedExprs);
    }
    if (Primary.isNull())
      return Primary;

    SequencedExprs.push_back(Primary.get());

    // We know we can make a syntax node for ternary expression.
    if (PendingTernary) {
      SyntaxContext->createNodeInPlace(SyntaxKind::TernaryExpr);
      PendingTernary = false;
    }

    if (isForConditionalDirective && Tok.isAtStartOfLine())
      break;
    
parse_operator:
    switch (Tok.getKind()) {
    case tok::oper_binary_spaced:
    case tok::oper_binary_unspaced: {
      // If this is an "&& #available()" expression (or related things that
      // show up in a stmt-condition production), then don't eat it.
      //
      // These are not general expressions, and && is an infix operator,
      // so the code is invalid.  We get better recovery if we bail out from
      // this, because then we can produce a fixit to rewrite the && into a ,
      // if we're in a stmt-condition.
      if (Tok.getText() == "&&" &&
          peekToken().isAny(tok::pound_available,
                            tok::kw_let, tok::kw_var, tok::kw_case))
        goto done;
      
      // Parse the operator.
      SyntaxParsingContext OperatorContext(SyntaxContext,
                                           SyntaxKind::BinaryOperatorExpr);
      Expr *Operator = parseExprOperator();
      SequencedExprs.push_back(Operator);

      // The message is only valid for the first subexpr.
      Message = diag::expected_expr_after_operator;
      break;
    }
    
    case tok::question_infix: {
      // Save the '?'.
      SourceLoc questionLoc = consumeToken();
      
      // Parse the middle expression of the ternary.
      ParserResult<Expr> middle =
          parseExprSequence(diag::expected_expr_after_if_question, isExprBasic);
      ParserStatus Status = middle;
      if (middle.hasCodeCompletion())
        HasCodeCompletion = true;
      if (middle.isNull())
        return nullptr;
      
      // Make sure there's a matching ':' after the middle expr.
      if (!Tok.is(tok::colon)) {
        diagnose(questionLoc, diag::expected_colon_after_if_question);

      Status.setIsParseError();
      return makeParserResult(Status, new (Context) ErrorExpr(
          {startLoc, middle.get()->getSourceRange().End}));
      }
      
      SourceLoc colonLoc = consumeToken();
      
      auto *unresolvedIf
        = new (Context) IfExpr(questionLoc,
                               middle.get(),
                               colonLoc);
      SequencedExprs.push_back(unresolvedIf);
      Message = diag::expected_expr_after_if_colon;

      // Wait for the next expression to make a syntax node for ternary
      // expression.
      PendingTernary = true;
      break;
    }
        
    case tok::equal: {
      // If we're parsing an expression as the body of a refutable var/let
      // pattern, then an assignment doesn't make sense.  In a "if let"
      // statement the equals is the start of the condition, so don't parse it
      // as a binary operator.
      if (InVarOrLetPattern)
        goto done;
      SyntaxParsingContext AssignContext(SyntaxContext,
                                         SyntaxKind::AssignmentExpr);
      SourceLoc equalsLoc = consumeToken();
      auto *assign = new (Context) AssignExpr(equalsLoc);
      SequencedExprs.push_back(assign);
      Message = diag::expected_expr_assignment;
      break;
    }
        
    case tok::kw_is: {
      SyntaxParsingContext IsContext(SyntaxContext, SyntaxKind::IsExpr);
      // Parse a type after the 'is' token instead of an expression.
      ParserResult<Expr> is = parseExprIs();
      if (is.isNull() || is.hasCodeCompletion())
        return is;
      
      // Store the expr itself as a placeholder RHS. The real RHS is the
      // type parameter stored in the node itself.
      SequencedExprs.push_back(is.get());
      SequencedExprs.push_back(is.get());
      
      // We already parsed the right operand as part of the 'is' production.
      // Jump directly to parsing another operator.
      goto parse_operator;
    }
        
    case tok::kw_as: {
      SyntaxParsingContext AsContext(SyntaxContext, SyntaxKind::AsExpr);
      ParserResult<Expr> as = parseExprAs();
      if (as.isNull() || as.hasCodeCompletion())
        return as;
        
      // Store the expr itself as a placeholder RHS. The real RHS is the
      // type parameter stored in the node itself.
      SequencedExprs.push_back(as.get());
      SequencedExprs.push_back(as.get());
      
      // We already parsed the right operand as part of the 'is' production.
      // Jump directly to parsing another operator.
      goto parse_operator;
    }

    case tok::arrow:
    case tok::kw_throws: {
      SyntaxParsingContext ArrowContext(SyntaxContext, SyntaxKind::ArrowExpr);
      ParserResult<Expr> arrow = parseExprArrow();
      if (arrow.isNull() || arrow.hasCodeCompletion())
        return arrow;
      SequencedExprs.push_back(arrow.get());
      break;
    }
        
    default:
      // If the next token is not a binary operator, we're done.
      goto done;
    }
  }
done:

  // For conditional directives, we stop parsing after a line break.
  if (isForConditionalDirective && (SequencedExprs.size() & 1) == 0) {
    diagnose(getEndOfPreviousLoc(),
             diag::incomplete_conditional_compilation_directive);
    return makeParserError();
  }

  // If we had semantic errors, just fail here.
  assert(!SequencedExprs.empty());

  // If we saw no operators, don't build a sequence.
  if (SequencedExprs.size() == 1) {
    auto Result = makeParserResult(SequencedExprs[0]);
    if (HasCodeCompletion)
      Result.setHasCodeCompletion();
    return Result;
  }

  ExprSequnceContext.createNodeInPlace(SyntaxKind::ExprList);
  ExprSequnceContext.setCreateSyntax(SyntaxKind::SequenceExpr);
  auto Result = makeParserResult(SequenceExpr::create(Context, SequencedExprs));
  if (HasCodeCompletion)
    Result.setHasCodeCompletion();
  return Result;
}

/// parseExprSequenceElement
///
///   expr-sequence-element(Mode):
///     'try' expr-unary(Mode)
///     'try' '?' expr-unary(Mode)
///     'try' '!' expr-unary(Mode)
///     expr-unary(Mode)
///
/// 'try' is not actually allowed at an arbitrary position of a
/// sequence, but this isn't enforced until sequence-folding.
ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
                                                    bool isExprBasic) {
  SyntaxParsingContext ElementContext(SyntaxContext,
                                      SyntaxContextKind::Expr);
  SourceLoc tryLoc;
  bool hadTry = consumeIf(tok::kw_try, tryLoc);
  Optional<Token> trySuffix;
  if (hadTry && Tok.isAny(tok::exclaim_postfix, tok::question_postfix)) {
    trySuffix = Tok;
    consumeToken();
  }

  // Try to parse '@' sign or 'inout' as a attributed typerepr.
  if (Tok.isAny(tok::at_sign, tok::kw_inout)) {
    bool isType = false;
    {
      BacktrackingScope backtrack(*this);
      isType = canParseType();
    }
    if (isType) {
      ParserResult<TypeRepr> ty = parseType();
      if (ty.isNonNull())
        return makeParserResult(
            new (Context) TypeExpr(TypeLoc(ty.get(), Type())));
      checkForInputIncomplete();
      return nullptr;
    }
  }

  ParserResult<Expr> sub = parseExprUnary(message, isExprBasic);

  if (hadTry && !sub.hasCodeCompletion() && !sub.isNull()) {
    ElementContext.setCreateSyntax(SyntaxKind::TryExpr);
    switch (trySuffix ? trySuffix->getKind() : tok::NUM_TOKENS) {
    case tok::exclaim_postfix:
      sub = makeParserResult(
          new (Context) ForceTryExpr(tryLoc, sub.get(), trySuffix->getLoc()));
      break;
    case tok::question_postfix:
      sub = makeParserResult(
          new (Context) OptionalTryExpr(tryLoc, sub.get(),
                                        trySuffix->getLoc()));
      break;
    default:
      // If this is a simple "try expr" situation, where the expr is a closure
      // literal, and the next token is a 'catch', then the user wrote
      // try/catch instead of do/catch.  Emit a fixit hint to rewrite to the
      // correct do/catch construct.
      if (Tok.is(tok::kw_catch) && isa<ClosureExpr>(sub.get())) {
        diagnose(tryLoc, diag::docatch_not_trycatch)
          .fixItReplace(tryLoc, "do");
        
        // Eat all of the catch clauses, so we don't trip over them in error
        // recovery.
        while (Tok.is(tok::kw_catch)) {
          ParserResult<CatchStmt> clause = parseStmtCatch();
          if (clause.hasCodeCompletion() && clause.isNull())
            break;
        }

        return makeParserResult(new (Context) ErrorExpr(tryLoc));
      }
        
      sub = makeParserResult(new (Context) TryExpr(tryLoc, sub.get()));
      break;
    }
  }

  return sub;
}

static Expr *formUnaryArgument(ASTContext &context, Expr *argument) {
  if (isa<ParenExpr>(argument))
    return argument;

  auto *arg = new (context)
      ParenExpr(argument->getStartLoc(), argument, argument->getEndLoc(),
                /*hasTrailingClosure*/ false);
  arg->setImplicit();
  return arg;
}

/// parseExprUnary
///
///   expr-unary(Mode):
///     expr-postfix(Mode)
///     operator-prefix expr-unary(Mode)
///     '&' expr-unary(Mode)
///
ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
  SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr);
  UnresolvedDeclRefExpr *Operator;
  switch (Tok.getKind()) {
  default:
    // If the next token is not an operator, just parse this as expr-postfix.
    return parseExprPostfix(Message, isExprBasic);

  case tok::amp_prefix: {
    SyntaxParsingContext AmpCtx(SyntaxContext, SyntaxKind::InOutExpr);
    SourceLoc Loc = consumeToken(tok::amp_prefix);

    ParserResult<Expr> SubExpr = parseExprUnary(Message, isExprBasic);
    if (SubExpr.hasCodeCompletion())
      return makeParserCodeCompletionResult<Expr>();
    if (SubExpr.isNull())
      return nullptr;
    return makeParserResult(
        new (Context) InOutExpr(Loc, SubExpr.get(), Type()));
  }

  case tok::backslash:
    return parseExprKeyPath();

  case tok::oper_postfix:
    // Postfix operators cannot start a subexpression, but can happen
    // syntactically because the operator may just follow whatever precedes this
    // expression (and that may not always be an expression).
    diagnose(Tok, diag::invalid_postfix_operator);
    Tok.setKind(tok::oper_prefix);
    LLVM_FALLTHROUGH;
  case tok::oper_prefix:
    Operator = parseExprOperator();
    break;
  case tok::oper_binary_spaced:
  case tok::oper_binary_unspaced: {
    // For recovery purposes, accept an oper_binary here.
    SourceLoc OperEndLoc = Tok.getLoc().getAdvancedLoc(Tok.getLength());
    Tok.setKind(tok::oper_prefix);
    Operator = parseExprOperator();

    if (OperEndLoc == Tok.getLoc())
      diagnose(PreviousLoc, diag::expected_expr_after_unary_operator);
    else
      diagnose(PreviousLoc, diag::expected_prefix_operator)
          .fixItRemoveChars(OperEndLoc, Tok.getLoc());
    break;
  }
  }

  ParserResult<Expr> SubExpr = parseExprUnary(Message, isExprBasic);
  ParserStatus Status = SubExpr;
  if (SubExpr.isNull())
    return Status;

  // We are sure we can create a prefix prefix operator expr now.
  UnaryContext.setCreateSyntax(SyntaxKind::PrefixOperatorExpr);

  // Check if we have a unary '-' with number literal sub-expression, for
  // example, "-42" or "-1.25".
  if (auto *LE = dyn_cast<NumberLiteralExpr>(SubExpr.get())) {
    if (Operator->hasName() && Operator->getName().getBaseName() == "-") {
      LE->setNegative(Operator->getLoc());
      return makeParserResult(Status, LE);
    }
  }

  return makeParserResult(
      Status, new (Context) PrefixUnaryExpr(
                  Operator, formUnaryArgument(Context, SubExpr.get())));
}

/// expr-keypath-swift:
///   \ type? . initial-key-path-component key-path-components
///
/// key-path-components:
//    key-path-component*
///   <empty>
///
/// key-path-component:
///   .identifier
///   ?
///   !
///   [ expression ]
///
/// initial-key-path-component:
///   identifier
///   ?
///   !
///   [ expression ]
ParserResult<Expr> Parser::parseExprKeyPath() {
  SyntaxParsingContext KeyPathCtx(SyntaxContext, SyntaxKind::KeyPathExpr);
  // Consume '\'.
  SourceLoc backslashLoc = consumeToken(tok::backslash);
  llvm::SaveAndRestore<bool> S(InSwiftKeyPath, true);

  // FIXME: diagnostics
  ParserResult<Expr> rootResult, pathResult;
  if (!startsWithSymbol(Tok, '.')) {
    rootResult = parseExprPostfix(diag::expr_keypath_expected_expr,
                                  /*isBasic=*/true);

    if (rootResult.isParseError())
      return rootResult;
  }

  if (startsWithSymbol(Tok, '.')) {
    SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);

    auto dotLoc = Tok.getLoc();
    // For uniformity, \.foo is parsed as if it were MAGIC.foo, so we need to
    // make sure the . is there, but parsing the ? in \.? as .? doesn't make
    // sense. This is all made more complicated by .?. being considered an
    // operator token. Since keypath allows '.!' '.?' and '.[', consume '.'
    // the token is a operator starts with '.', or the following token is '['.
    if ((Tok.isAnyOperator() && Tok.getLength() != 1) ||
        peekToken().is(tok::l_square)) {
      SyntaxParsingContext KeyPathBaseContext(SyntaxContext,
                                              SyntaxKind::KeyPathBaseExpr);
      consumeStartingCharacterOfCurrentToken(tok::period);
    }

    auto inner = makeParserResult(new (Context) KeyPathDotExpr(dotLoc));
    bool unusedHasBindOptional = false;

    // Inside a keypath's path, the period always behaves normally: the key path
    // behavior is only the separation between type and path.
    pathResult = parseExprPostfixSuffix(inner, /*isExprBasic=*/true,
                                        /*periodHasKeyPathBehavior=*/false,
                                        unusedHasBindOptional);
    if (pathResult.isParseError())
      return pathResult;
  }

  auto keypath = new (Context) KeyPathExpr(
      backslashLoc, rootResult.getPtrOrNull(), pathResult.getPtrOrNull());

  // Handle code completion.
  if ((Tok.is(tok::code_complete) && !Tok.isAtStartOfLine()) ||
      (Tok.is(tok::period) && peekToken().isAny(tok::code_complete))) {
    SourceLoc DotLoc;
    consumeIf(tok::period, DotLoc);
    if (CodeCompletion)
      CodeCompletion->completeExprKeyPath(keypath, DotLoc);
    consumeToken(tok::code_complete);
    return makeParserCodeCompletionResult(keypath);
  }

  return makeParserResult(keypath);
}

///   expr-keypath-objc:
///     '#keyPath' '(' unqualified-name ('.' unqualified-name) * ')'
///
ParserResult<Expr> Parser::parseExprKeyPathObjC() {
  SyntaxParsingContext ObjcKPCtx(SyntaxContext, SyntaxKind::ObjcKeyPathExpr);
  // Consume '#keyPath'.
  SourceLoc keywordLoc = consumeToken(tok::pound_keyPath);

  // Parse the leading '('.
  if (!Tok.is(tok::l_paren)) {
    diagnose(Tok, diag::expr_keypath_expected_lparen);
    return makeParserError();
  }
  SourceLoc lParenLoc = consumeToken(tok::l_paren);

  SmallVector<KeyPathExpr::Component, 4> components;
  /// Handler for code completion.
  auto handleCodeCompletion = [&](SourceLoc DotLoc) -> ParserResult<Expr> {
    KeyPathExpr *expr = nullptr;
    if (!components.empty()) {
      expr = new (Context)
          KeyPathExpr(Context, keywordLoc, lParenLoc, components, Tok.getLoc());
    }

    if (CodeCompletion)
      CodeCompletion->completeExprKeyPath(expr, DotLoc);

    // Eat the code completion token because we handled it.
    consumeToken(tok::code_complete);
    return makeParserCodeCompletionResult(expr);
  };

  // Parse the sequence of unqualified-names.
  ParserStatus status;
  SourceLoc LastDotLoc;
  while (true) {
    SyntaxParsingContext NamePieceCtx(SyntaxContext, SyntaxKind::ObjcNamePiece);
    // Handle code completion.
    if (Tok.is(tok::code_complete))
      return handleCodeCompletion(LastDotLoc);

    // Parse the next name.
    DeclNameLoc nameLoc;
    bool afterDot = !components.empty();
    auto name = parseUnqualifiedDeclName(
                  afterDot, nameLoc, 
                  diag::expr_keypath_expected_property_or_type);
    if (!name) {
      status.setIsParseError();
      break;
    }

    // Record the name we parsed.
    auto component = KeyPathExpr::Component::forUnresolvedProperty(name,
                                                      nameLoc.getBaseNameLoc());
    components.push_back(component);

    // Handle code completion.
    if (Tok.is(tok::code_complete))
      return handleCodeCompletion(SourceLoc());

    // Parse the next period to continue the path.
    if (consumeIf(tok::period, LastDotLoc))
      continue;

    break;
  }

  // Collect all name pieces to an objc name.
  SyntaxContext->collectNodesInPlace(SyntaxKind::ObjcName);

  // Parse the closing ')'.
  SourceLoc rParenLoc;
  if (status.isError()) {
    skipUntilDeclStmtRBrace(tok::r_paren);
    if (Tok.is(tok::r_paren))
      rParenLoc = consumeToken();
    else
      rParenLoc = PreviousLoc;
  } else {
    parseMatchingToken(tok::r_paren, rParenLoc,
                       diag::expr_keypath_expected_rparen, lParenLoc);
  }

  // If we cannot build a useful expression, just return an error
  // expression.
  if (components.empty() || status.isError()) {
    return makeParserResult<Expr>(
             new (Context) ErrorExpr(SourceRange(keywordLoc, rParenLoc)));
  }

  // We're done: create the key-path expression.
  return makeParserResult<Expr>(new (Context) KeyPathExpr(
      Context, keywordLoc, lParenLoc, components, rParenLoc));
}

/// parseExprSelector
///
///   expr-selector:
///     '#selector' '(' expr ')'
///     '#selector' '(' 'getter' ':' expr ')'
///     '#selector' '(' 'setter' ':' expr ')'
///
ParserResult<Expr> Parser::parseExprSelector() {
  SyntaxParsingContext ExprCtxt(SyntaxContext, SyntaxKind::ObjcSelectorExpr);
  // Consume '#selector'.
  SourceLoc keywordLoc = consumeToken(tok::pound_selector);

  // Parse the leading '('.
  if (!Tok.is(tok::l_paren)) {
    diagnose(Tok, diag::expr_selector_expected_lparen);
    return makeParserError();
  }
  SourceLoc lParenLoc = consumeToken(tok::l_paren);
  SourceLoc modifierLoc;

  // Parse possible 'getter:' or 'setter:' modifiers, and determine
  // the kind of selector we're working with.
  ObjCSelectorExpr::ObjCSelectorKind selectorKind;
  if (peekToken().is(tok::colon) &&
      (Tok.isContextualKeyword("getter") ||
       Tok.isContextualKeyword("setter"))) {
    // Parse the modifier.
    if (Tok.isContextualKeyword("getter"))
      selectorKind = ObjCSelectorExpr::Getter;
    else
      selectorKind = ObjCSelectorExpr::Setter;

    Tok.setKind(tok::contextual_keyword);
    modifierLoc = consumeToken();
    (void)consumeToken(tok::colon);
  } else {
    selectorKind = ObjCSelectorExpr::Method;
  }

  ObjCSelectorContext selectorContext;
  switch (selectorKind) {
  case ObjCSelectorExpr::Getter:
    selectorContext = ObjCSelectorContext::GetterSelector;
    break;
  case ObjCSelectorExpr::Setter:
    selectorContext = ObjCSelectorContext::SetterSelector;
    break;
  case ObjCSelectorExpr::Method:
    selectorContext = ObjCSelectorContext::MethodSelector;
  }

  // Parse the subexpression.
  CodeCompletionCallbacks::InObjCSelectorExprRAII
    InObjCSelectorExpr(CodeCompletion, selectorContext);
  ParserResult<Expr> subExpr =
    parseExpr(selectorKind == ObjCSelectorExpr::Method
                ? diag::expr_selector_expected_method_expr
                : diag::expr_selector_expected_property_expr);
  if (subExpr.hasCodeCompletion())
    return makeParserCodeCompletionResult<Expr>();

  // Parse the closing ')'.
  SourceLoc rParenLoc;
  if (subExpr.isParseError()) {
    skipUntilDeclStmtRBrace(tok::r_paren);
    if (Tok.is(tok::r_paren))
      rParenLoc = consumeToken();
    else
      rParenLoc = PreviousLoc;
  } else {
    parseMatchingToken(tok::r_paren, rParenLoc,
                       diag::expr_selector_expected_rparen, lParenLoc);
  }

  // If the subexpression was in error, just propagate the error.
  if (subExpr.isParseError())
    return makeParserResult<Expr>(
      new (Context) ErrorExpr(SourceRange(keywordLoc, rParenLoc)));

  return makeParserResult<Expr>(
    new (Context) ObjCSelectorExpr(selectorKind, keywordLoc, lParenLoc,
                                   modifierLoc, subExpr.get(), rParenLoc));
}

static DeclRefKind getDeclRefKindForOperator(tok kind) {
  switch (kind) {
  case tok::oper_binary_spaced:
  case tok::oper_binary_unspaced:  return DeclRefKind::BinaryOperator;
  case tok::oper_postfix: return DeclRefKind::PostfixOperator;
  case tok::oper_prefix:  return DeclRefKind::PrefixOperator;
  default: llvm_unreachable("bad operator token kind");
  }
}

/// parseExprOperator - Parse an operator reference expression.  These
/// are not "proper" expressions; they can only appear in binary/unary
/// operators.
UnresolvedDeclRefExpr *Parser::parseExprOperator() {
  assert(Tok.isAnyOperator());
  DeclRefKind refKind = getDeclRefKindForOperator(Tok.getKind());
  SourceLoc loc = Tok.getLoc();
  Identifier name = Context.getIdentifier(Tok.getText());
  consumeToken();
  // Bypass local lookup.
  return new (Context) UnresolvedDeclRefExpr(name, refKind, DeclNameLoc(loc));
}

static VarDecl *getImplicitSelfDeclForSuperContext(Parser &P,
                                                   DeclContext *DC,
                                                   SourceLoc Loc) {
  auto *methodContext = DC->getInnermostMethodContext();
  if (!methodContext) {
    P.diagnose(Loc, diag::super_not_in_class_method);
    return nullptr;
  }

  // Do an actual lookup for 'self' in case it shows up in a capture list.
  auto *methodSelf = methodContext->getImplicitSelfDecl();
  auto *lookupSelf = P.lookupInScope(P.Context.Id_self);
  if (lookupSelf && lookupSelf != methodSelf) {
    // FIXME: This is the wrong diagnostic for if someone manually declares a
    // variable named 'self' using backticks.
    P.diagnose(Loc, diag::super_in_closure_with_capture);
    P.diagnose(lookupSelf->getLoc(), diag::super_in_closure_with_capture_here);
    return nullptr;
  }

  return methodSelf;
}

/// parseExprSuper
///
///   expr-super:
///     expr-super-member
///     expr-super-init
///     expr-super-subscript
///   expr-super-member:
///     'super' '.' identifier
///   expr-super-init:
///     'super' '.' 'init'
///   expr-super-subscript:
///     'super' '[' expr ']'
ParserResult<Expr> Parser::parseExprSuper() {
  SyntaxParsingContext SuperCtxt(SyntaxContext, SyntaxContextKind::Expr);
  // Parse the 'super' reference.
  SourceLoc superLoc = consumeToken(tok::kw_super);
  SyntaxContext->createNodeInPlace(SyntaxKind::SuperRefExpr);

  // 'super.' must be followed by a member ref, explicit initializer ref, or
  // subscript call.
  if (!Tok.isAny(tok::period, tok::period_prefix, tok::code_complete) &&
      !Tok.isFollowingLSquare()) {
    if (!consumeIf(tok::unknown))
      diagnose(Tok, diag::expected_dot_or_subscript_after_super);
    return nullptr;
  }

  VarDecl *selfDecl =
      getImplicitSelfDeclForSuperContext(*this, CurDeclContext, superLoc);
  if (!selfDecl)
    return makeParserResult(new (Context) ErrorExpr(superLoc));

  return makeParserResult(new (Context) SuperRefExpr(selfDecl, superLoc,
                                                     /*Implicit=*/false));
}

StringRef Parser::copyAndStripUnderscores(StringRef orig) {
  return ASTGen::copyAndStripUnderscores(orig, Context);
}

/// Disambiguate the parse after '{' token that is in a place that might be
/// the start of a trailing closure, or start the variable accessor block.
///
/// Check to see if the '{' is followed by a 'didSet' or a 'willSet' label,
/// possibly preceded by attributes.  If so, we disambiguate the parse as the
/// start of a get-set block in a variable definition (not as a trailing
/// closure).
static bool isStartOfGetSetAccessor(Parser &P) {
  assert(P.Tok.is(tok::l_brace) && "not checking a brace?");
  
  // The only case this can happen is if the accessor label is immediately after
  // a brace (possibly preceded by attributes).  "get" is implicit, so it can't
  // be checked for.  Conveniently however, get/set properties are not allowed
  // to have initializers, so we don't have an ambiguity, we just have to check
  // for observing accessors.
  //
  // If we have a 'didSet' or a 'willSet' label, disambiguate immediately as
  // an accessor block.
  Token NextToken = P.peekToken();
  if (NextToken.isContextualKeyword("didSet") ||
      NextToken.isContextualKeyword("willSet"))
    return true;

  // If we don't have attributes, then it cannot be an accessor block.
  if (NextToken.isNot(tok::at_sign))
    return false;

  Parser::BacktrackingScope Backtrack(P);

  // Eat the "{".
  P.consumeToken(tok::l_brace);

  // Eat attributes, if present.
  while (P.consumeIf(tok::at_sign)) {
    if (!P.consumeIf(tok::identifier)) return false;
    // Eat paren after attribute name; e.g. @foo(x)
    if (P.Tok.is(tok::l_paren)) P.skipSingle();
  }

  // Check if we have 'didSet'/'willSet' after attributes.
  return P.Tok.isContextualKeyword("didSet") ||
         P.Tok.isContextualKeyword("willSet");
}

/// Recover invalid uses of trailing closures in a situation
/// where the parser requires an expr-basic (which does not allow them).  We
/// handle this by doing some lookahead in common situations. And later, Sema
/// will emit a diagnostic with a fixit to add wrapping parens.
static bool isValidTrailingClosure(bool isExprBasic, Parser &P){
  assert(P.Tok.is(tok::l_brace) && "Couldn't be a trailing closure");
  
  // If this is the start of a get/set accessor, then it isn't a trailing
  // closure.
  if (isStartOfGetSetAccessor(P))
    return false;

  // If this is a normal expression (not an expr-basic) then trailing closures
  // are allowed, so this is obviously one.
  // TODO: We could handle try to disambiguate cases like:
  //   let x = foo
  //   {...}()
  // by looking ahead for the ()'s, but this has been replaced by do{}, so this
  // probably isn't worthwhile.
  //
  if (!isExprBasic)
    return true;
  
  // If this is an expr-basic, then a trailing closure is not allowed.  However,
  // it is very common for someone to write something like:
  //
  //    for _ in numbers.filter {$0 > 4} {
  //
  // and we want to recover from this very well.   We need to perform arbitrary
  // look-ahead to disambiguate this case, so we only do this in the case where
  // the token after the { is on the same line as the {.
  if (P.peekToken().isAtStartOfLine())
    return false;
  
  
  // Determine if the {} goes with the expression by eating it, and looking
  // to see if it is immediately followed by '{', 'where', or comma.  If so,
  // we consider it to be part of the proceeding expression.
  Parser::BacktrackingScope backtrack(P);
  P.consumeToken(tok::l_brace);
  P.skipUntil(tok::r_brace);
  SourceLoc endLoc;
  if (!P.consumeIf(tok::r_brace, endLoc) ||
      P.Tok.isNot(tok::l_brace, tok::kw_where, tok::comma)) {
    return false;
  }

  // Recoverable case. Just return true here and Sema will emit a diagnostic
  // later. see: Sema/MiscDiagnostics.cpp#checkStmtConditionTrailingClosure
  return true;
}

ParserResult<Expr>
Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
                               bool periodHasKeyPathBehavior,
                               bool &hasBindOptional) {
  hasBindOptional = false;

  // Handle suffix expressions.
  while (1) {
    // FIXME: Better recovery.
    if (Result.isNull())
      return Result;

    if (Result.hasCodeCompletion() &&
        SourceMgr.getCodeCompletionLoc() == PreviousLoc) {
      // Don't parse suffixes if the expression ended with code completion
      // token. Because, for example, given:
      //   [.foo(), .bar()]
      // If user want to insert another element in between:
      //   [.foo(), <HERE> .bar()]
      // '.bar()' is probably not a part of the inserting element. Moreover,
      // having suffixes doesn't help type inference in any way.
      return Result;
    }

    // Check for a .foo suffix.
    SourceLoc TokLoc = Tok.getLoc();
    if (Tok.is(tok::period) || Tok.is(tok::period_prefix)) {
      // A key path is special, because it allows .[, unlike anywhere else. The
      // period itself should be left in the token stream. (.? and .! end up
      // being operators, and so aren't handled here.)
      if (periodHasKeyPathBehavior && peekToken().is(tok::l_square)) {
        break;
      }
      // Completion for keyPath expression is handled in parseExprKeyPath.
      if (InSwiftKeyPath && peekToken().is(tok::code_complete))
        break;

      Tok.setKind(tok::period);
      consumeToken();

      // Handle "x.42" - a tuple index.
      if (Tok.is(tok::integer_literal)) {
        DeclName name = Context.getIdentifier(Tok.getText());
        SourceLoc nameLoc = consumeToken(tok::integer_literal);
        SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);

        // Don't allow '.<integer literal>' following a numeric literal
        // expression (unless in #if env, for 1.2.3.4 version numbers)
        if (!InPoundIfEnvironment && Result.isNonNull() &&
            isa<NumberLiteralExpr>(Result.get())) {
          diagnose(nameLoc, diag::numeric_literal_numeric_member)
              .highlight(Result.get()->getSourceRange());
          continue;
        }

        Result = makeParserResult(
            Result, new (Context) UnresolvedDotExpr(Result.get(), TokLoc, name,
                                                    DeclNameLoc(nameLoc),
                                                    /*Implicit=*/false));
        continue;
      }

      // Handle "x.self" expr.
      if (Tok.is(tok::kw_self)) {
        Result = makeParserResult(
            Result,
            new (Context) DotSelfExpr(Result.get(), TokLoc, consumeToken()));
        SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
        continue;
      }

      // Handle the deprecated 'x.dynamicType' and migrate it to `type(of: x)`
      if (Tok.getText() == "dynamicType") {
        auto range = Result.get()->getSourceRange();
        auto dynamicTypeExprRange = SourceRange(TokLoc, Tok.getLoc());
        diagnose(TokLoc, diag::expr_dynamictype_deprecated)
            .highlight(dynamicTypeExprRange)
            .fixItReplace(dynamicTypeExprRange, ")")
            .fixItInsert(range.Start, "type(of: ");

        // fallthrough to an UnresolvedDotExpr.
      }

      // Handle "x.<tab>" for code completion.
      if (Tok.is(tok::code_complete)) {
        assert(!InSwiftKeyPath);
        if (CodeCompletion) {
          CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc);
        }
        // Eat the code completion token because we handled it.
        consumeToken(tok::code_complete);
        Result.setHasCodeCompletion();
        return Result;
      }

      DeclNameLoc NameLoc;
      Diag<> D = isa<SuperRefExpr>(Result.get())
                     ? diag::expected_identifier_after_super_dot_expr
                     : diag::expected_member_name;
      DeclName Name = parseUnqualifiedDeclName(/*afterDot=*/true, NameLoc, D);
      if (!Name)
        return nullptr;
      SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
      Result = makeParserResult(Result, new (Context) UnresolvedDotExpr(
                                            Result.get(), TokLoc, Name, NameLoc,
                                            /*Implicit=*/false));

      if (canParseAsGenericArgumentList()) {
        SmallVector<TypeRepr *, 8> args;
        SourceLoc LAngleLoc, RAngleLoc;
        auto argStat = parseGenericArguments(args, LAngleLoc, RAngleLoc);
        if (argStat.isError())
          diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);

        SmallVector<TypeLoc, 8> locArgs;
        for (auto ty : args)
          locArgs.push_back(ty);
        SyntaxContext->createNodeInPlace(SyntaxKind::SpecializeExpr);
        Result = makeParserResult(
            Result, UnresolvedSpecializeExpr::create(
                        Context, Result.get(), LAngleLoc, locArgs, RAngleLoc));
      }

      continue;
    }

    // If there is an expr-call-suffix, parse it and form a call.
    if (Tok.isFollowingLParen()) {
      Result = parseExprCallSuffix(Result, isExprBasic);
      SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);
      continue;
    }

    // Check for a [expr] suffix.
    // Note that this cannot be the start of a new line.
    if (Tok.isFollowingLSquare()) {
      SourceLoc lSquareLoc, rSquareLoc;
      SmallVector<Expr *, 2> indexArgs;
      SmallVector<Identifier, 2> indexArgLabels;
      SmallVector<SourceLoc, 2> indexArgLabelLocs;
      Expr *trailingClosure;

      ParserStatus status = parseExprList(
          tok::l_square, tok::r_square,
          /*isPostfix=*/true, isExprBasic, lSquareLoc, indexArgs,
          indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure,
          SyntaxKind::TupleExprElementList);
      Result = makeParserResult(
          status | Result,
          SubscriptExpr::create(Context, Result.get(), lSquareLoc, indexArgs,
                                indexArgLabels, indexArgLabelLocs, rSquareLoc,
                                trailingClosure, ConcreteDeclRef(),
                                /*implicit=*/false));
      SyntaxContext->createNodeInPlace(SyntaxKind::SubscriptExpr);
      continue;
    }

    // Check for a trailing closure, if allowed.
    if (Tok.is(tok::l_brace) && isValidTrailingClosure(isExprBasic, *this)) {
      // FIXME: if Result has a trailing closure, break out.

      // Stop after literal expressions, which may never have trailing closures.
      const auto *callee = Result.get();
      if (isa<LiteralExpr>(callee) || isa<CollectionExpr>(callee) ||
          isa<TupleExpr>(callee))
        break;

      // Add dummy blank argument list to the call expression syntax.
      SyntaxContext->addSyntax(
          ParsedSyntaxRecorder::makeBlankTupleExprElementList(
              Tok.getLoc(), *SyntaxContext));

      ParserResult<Expr> closure =
          parseTrailingClosure(callee->getSourceRange());
      if (closure.isNull())
        return nullptr;

      // Trailing closure implicitly forms a call.
      Result = makeParserResult(
          ParserStatus(closure) | ParserStatus(Result),
          CallExpr::create(Context, Result.get(), SourceLoc(), {}, {}, {},
                           SourceLoc(), closure.get(), /*implicit=*/false));
      SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);

      // We only allow a single trailing closure on a call.  This could be
      // generalized in the future, but needs further design.
      if (Tok.is(tok::l_brace))
        break;
      continue;
    }

    // Check for a ? suffix.
    if (consumeIf(tok::question_postfix)) {
      Result = makeParserResult(Result, new (Context) BindOptionalExpr(
                                            Result.get(), TokLoc, /*depth*/ 0));
      SyntaxContext->createNodeInPlace(SyntaxKind::OptionalChainingExpr);
      hasBindOptional = true;
      continue;
    }

    // Check for a ! suffix.
    if (consumeIf(tok::exclaim_postfix)) {
      Result = makeParserResult(
          Result, new (Context) ForceValueExpr(Result.get(), TokLoc));
      SyntaxContext->createNodeInPlace(SyntaxKind::ForcedValueExpr);
      continue;
    }

    // Check for a postfix-operator suffix.
    if (Tok.is(tok::oper_postfix)) {
      // KeyPaths are more restricted in what can go after a ., and so we treat
      // them specially.
      if (periodHasKeyPathBehavior && startsWithSymbol(Tok, '.'))
        break;

      Expr *oper = parseExprOperator();

      Result = makeParserResult(
          Result, new (Context) PostfixUnaryExpr(
                      oper, formUnaryArgument(Context, Result.get())));
      SyntaxContext->createNodeInPlace(SyntaxKind::PostfixUnaryExpr);
      continue;
    }

    if (Tok.is(tok::code_complete)) {
      if (InSwiftKeyPath)
        return Result;

      if (Tok.isAtStartOfLine()) {
        // Postfix expression is located on a different line than the code
        // completion token, and thus they are not related.
        return Result;
      }

      if (CodeCompletion && Result.isNonNull()) {
        bool hasSpace = Tok.getLoc() != getEndOfPreviousLoc();
        CodeCompletion->completePostfixExpr(Result.get(), hasSpace);
      }
      // Eat the code completion token because we handled it.
      consumeToken(tok::code_complete);
      Result.setHasCodeCompletion();
      return Result;
    }

    // If we end up with an unknown token on this line, return an ErrorExpr
    // covering the range of the token.
    if (!Tok.isAtStartOfLine() && consumeIf(tok::unknown)) {
      Result = makeParserResult(
          Result, new (Context) ErrorExpr(Result.get()->getSourceRange()));
      continue;
    }

    // Otherwise, we don't know what this token is, it must end the expression.
    break;
  }

  return Result;
}

/// parseExprPostfix
///
///   expr-dot:
///     expr-postfix '.' 'type'
///     expr-postfix '.' (identifier|keyword) generic-args? expr-call-suffix?
///     expr-postfix '.' integer_literal
///
///   expr-subscript:
///     expr-postfix '[' expr ']'
///
///   expr-call:
///     expr-postfix expr-paren
///
///   expr-force-value:
///     expr-postfix '!'
///
///   expr-trailing-closure:
///     expr-postfix(trailing-closure) expr-closure
///
///   expr-postfix(Mode):
///     expr-postfix(Mode) operator-postfix
///
///   expr-postfix(basic):
///     expr-primary
///     expr-dot
///     expr-metatype
///     expr-init
///     expr-subscript
///     expr-call
///     expr-force-value
///
///   expr-postfix(trailing-closure):
///     expr-postfix(basic)
///     expr-trailing-closure
///
ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
  SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
  auto Result = parseExprPrimary(ID, isExprBasic);
  // If we couldn't parse any expr, don't attempt to parse suffixes.
  if (Result.isNull())
    return Result;

  bool hasBindOptional = false;
  Result = parseExprPostfixSuffix(Result, isExprBasic,
                                  /*periodHasKeyPathBehavior=*/InSwiftKeyPath,
                                  hasBindOptional);
  if (Result.isParseError() || Result.hasCodeCompletion())
    return Result;

  // If we had a ? suffix expression, bind the entire postfix chain
  // within an OptionalEvaluationExpr.
  if (hasBindOptional) {
    Result = makeParserResult(new (Context) OptionalEvaluationExpr(Result.get()));
  }

  return Result;
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<IntegerLiteralExprSyntax>() {
  auto Token = consumeTokenSyntax(tok::integer_literal);
  return ParsedSyntaxRecorder::makeIntegerLiteralExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<FloatLiteralExprSyntax>() {
  auto Token = consumeTokenSyntax(tok::floating_literal);
  return ParsedSyntaxRecorder::makeFloatLiteralExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<NilLiteralExprSyntax>() {
  auto Token = consumeTokenSyntax(tok::kw_nil);
  return ParsedSyntaxRecorder::makeNilLiteralExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<BooleanLiteralExprSyntax>() {
  auto Token = consumeTokenSyntax();
  return ParsedSyntaxRecorder::makeBooleanLiteralExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<PoundFileExprSyntax>() {
  if (Tok.getKind() == tok::kw___FILE__) {
    StringRef fixit = "#file";
    diagnose(Tok.getLoc(), diag::snake_case_deprecated, Tok.getText(), fixit)
        .fixItReplace(Tok.getLoc(), fixit);

    auto Token = consumeTokenSyntax(tok::kw___FILE__);
    return ParsedSyntaxRecorder::makeUnknownExpr({&Token, 1}, *SyntaxContext);
  }

  auto Token = consumeTokenSyntax(tok::pound_file);
  return ParsedSyntaxRecorder::makePoundFileExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<PoundLineExprSyntax>() {
  if (Tok.getKind() == tok::kw___LINE__) {
    StringRef fixit = "#line";
    diagnose(Tok.getLoc(), diag::snake_case_deprecated, Tok.getText(), fixit)
        .fixItReplace(Tok.getLoc(), fixit);

    auto Token = consumeTokenSyntax(tok::kw___LINE__);
    return ParsedSyntaxRecorder::makeUnknownExpr({&Token, 1}, *SyntaxContext);
  }

  // FIXME: #line was renamed to #sourceLocation
  auto Token = consumeTokenSyntax(tok::pound_line);
  return ParsedSyntaxRecorder::makePoundLineExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<PoundColumnExprSyntax>() {
  if (Tok.getKind() == tok::kw___COLUMN__) {
    StringRef fixit = "#column";
    diagnose(Tok.getLoc(), diag::snake_case_deprecated, Tok.getText(), fixit)
        .fixItReplace(Tok.getLoc(), fixit);

    auto Token = consumeTokenSyntax(tok::kw___COLUMN__);
    return ParsedSyntaxRecorder::makeUnknownExpr({&Token, 1}, *SyntaxContext);
  }

  auto Token = consumeTokenSyntax(tok::pound_column);
  return ParsedSyntaxRecorder::makePoundColumnExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<PoundFunctionExprSyntax>() {
  if (Tok.getKind() == tok::kw___FUNCTION__) {
    StringRef fixit = "#function";
    diagnose(Tok.getLoc(), diag::snake_case_deprecated, Tok.getText(), fixit)
        .fixItReplace(Tok.getLoc(), fixit);

    auto Token = consumeTokenSyntax(tok::kw___FUNCTION__);
    return ParsedSyntaxRecorder::makeUnknownExpr({&Token, 1}, *SyntaxContext);
  }

  auto Token = consumeTokenSyntax(tok::pound_function);
  return ParsedSyntaxRecorder::makePoundFunctionExpr(std::move(Token), *SyntaxContext);
}

template <>
ParsedExprSyntax Parser::parseExprSyntax<PoundDsohandleExprSyntax>() {
  if (Tok.getKind() == tok::kw___DSO_HANDLE__) {
    StringRef fixit = "#dsohandle";
    diagnose(Tok.getLoc(), diag::snake_case_deprecated, Tok.getText(), fixit)
        .fixItReplace(Tok.getLoc(), fixit);

    auto Token = consumeTokenSyntax(tok::kw___DSO_HANDLE__);
    return ParsedSyntaxRecorder::makeUnknownExpr({&Token, 1}, *SyntaxContext);
  }

  auto Token = consumeTokenSyntax(tok::pound_dsohandle);
  return ParsedSyntaxRecorder::makePoundDsohandleExpr(std::move(Token), *SyntaxContext);
}

template <typename SyntaxNode>
ParserResult<Expr> Parser::parseExprAST() {
  auto Loc = leadingTriviaLoc();
  auto ParsedExpr = parseExprSyntax<SyntaxNode>();
  SyntaxContext->addSyntax(std::move(ParsedExpr));
  // todo [gsoc]: improve this somehow
  if (SyntaxContext->isTopNode<UnknownExprSyntax>()) {
    auto Expr = SyntaxContext->topNode<UnknownExprSyntax>();
    auto ExprAST = Generator.generate(Expr, Loc);
    return makeParserResult(ExprAST);
  }
  auto Expr = SyntaxContext->topNode<SyntaxNode>();
  auto ExprAST = Generator.generate(Expr, Loc);
  return makeParserResult(ExprAST);
}

/// parseExprPrimary
///
///   expr-literal:
///     integer_literal
///     floating_literal
///     string_literal
///     nil
///     true
///     false
///     #file
///     #line
///     #column
///     #function
///     #dsohandle
///
///   expr-delayed-identifier:
///     '.' identifier
///
///   expr-discard:
///     '_'
///
///   expr-primary:
///     expr-literal
///     expr-identifier expr-call-suffix?
///     expr-closure
///     expr-anon-closure-argument
///     expr-delayed-identifier
///     expr-paren
///     expr-super
///     expr-discard
///     expr-selector
///
ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
  switch (Tok.getKind()) {
  case tok::integer_literal: return parseExprAST<IntegerLiteralExprSyntax>();
  case tok::floating_literal: return parseExprAST<FloatLiteralExprSyntax>();
  case tok::kw_nil: return parseExprAST<NilLiteralExprSyntax>();
  case tok::kw_true:
  case tok::kw_false: return parseExprAST<BooleanLiteralExprSyntax>();
  case tok::kw___FILE__:
  case tok::pound_file: return parseExprAST<PoundFileExprSyntax>();
  case tok::kw___LINE__:
  case tok::pound_line: return parseExprAST<PoundLineExprSyntax>();
  case tok::kw___COLUMN__:
  case tok::pound_column: return parseExprAST<PoundColumnExprSyntax>();
  case tok::kw___FUNCTION__:
  case tok::pound_function: return parseExprAST<PoundFunctionExprSyntax>();
  case tok::kw___DSO_HANDLE__:
  case tok::pound_dsohandle: return parseExprAST<PoundDsohandleExprSyntax>();
  default: break;
  }

  SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
  switch (Tok.getKind()) {
  case tok::at_sign:
    // Objective-C programmers habitually type @"foo", so recover gracefully
    // with a fixit.  If this isn't @"foo", just handle it like an unknown
    // input.
    if (peekToken().isNot(tok::string_literal))
      goto UnknownCharacter;
    
    diagnose(Tok.getLoc(), diag::string_literal_no_atsign)
      .fixItRemove(Tok.getLoc());
    consumeToken(tok::at_sign);
    LLVM_FALLTHROUGH;
      
  case tok::string_literal:  // "foo"
    return parseExprStringLiteral();

  case tok::identifier:  // foo
  case tok::kw_self:     // self

    // If we are parsing a refutable pattern and are inside a let/var pattern,
    // the identifiers change to be value bindings instead of decl references.
    // Parse and return this as an UnresolvedPatternExpr around a binding.  This
    // will be resolved (or rejected) by sema when the overall refutable pattern
    // it transformed from an expression into a pattern.
    if ((InVarOrLetPattern == IVOLP_ImplicitlyImmutable ||
         InVarOrLetPattern == IVOLP_InVar ||
         InVarOrLetPattern == IVOLP_InLet) &&
        // If we have "case let x." or "case let x(", we parse x as a normal
        // name, not a binding, because it is the start of an enum pattern or
        // call pattern.
        peekToken().isNot(tok::period, tok::period_prefix, tok::l_paren)) {
      Identifier name;
      SourceLoc loc = consumeIdentifier(&name, /*allowDollarIdentifier=*/true);
      auto introducer = (InVarOrLetPattern != IVOLP_InVar
                         ? VarDecl::Introducer::Let
                         : VarDecl::Introducer::Var);
      auto pattern = createBindingFromPattern(loc, name, introducer);
      ParsedPatternSyntax PatternNode =
          ParsedSyntaxRecorder::makeIdentifierPattern(
                                  SyntaxContext->popToken(), *SyntaxContext);
      ParsedExprSyntax ExprNode =
          ParsedSyntaxRecorder::makeUnresolvedPatternExpr(std::move(PatternNode),
                                                          *SyntaxContext);
      SyntaxContext->addSyntax(std::move(ExprNode));
      return makeParserResult(new (Context) UnresolvedPatternExpr(pattern));
    }

    LLVM_FALLTHROUGH;
  case tok::kw_Self:     // Self
    return makeParserResult(parseExprIdentifier());

  case tok::kw_Any: { // Any
    ExprContext.setCreateSyntax(SyntaxKind::TypeExpr);
    auto TyR = parseAnyTypeAST();
    return makeParserResult(new (Context) TypeExpr(TypeLoc(TyR.get())));
  }

  case tok::dollarident: // $1
    return makeParserResult(parseExprAnonClosureArg());

  case tok::kw__: // _
    ExprContext.setCreateSyntax(SyntaxKind::DiscardAssignmentExpr);
    return makeParserResult(
      new (Context) DiscardAssignmentExpr(consumeToken(), /*Implicit=*/false));

  case tok::pound_selector: // expr-selector
    return parseExprSelector();

  case tok::pound_keyPath:
    return parseExprKeyPathObjC();

  case tok::l_brace:     // expr-closure
    return parseExprClosure();

  case tok::period:              //=.foo
  case tok::period_prefix: {     // .foo
    Tok.setKind(tok::period_prefix);
    SourceLoc DotLoc = consumeToken();
    
    // Special case ".<integer_literal>" like ".4".  This isn't valid, but the
    // developer almost certainly meant to use "0.4".  Diagnose this, and
    // recover as if they wrote that.
    if (Tok.is(tok::integer_literal) && !Tok.isAtStartOfLine()) {
      diagnose(DotLoc, diag::invalid_float_literal_missing_leading_zero,
               Tok.getText())
        .fixItInsert(DotLoc, "0")
        .highlight({DotLoc, Tok.getLoc()});
      char *Ptr = (char*)Context.Allocate(Tok.getLength()+2, 1);
      memcpy(Ptr, "0.", 2);
      memcpy(Ptr+2, Tok.getText().data(), Tok.getLength());
      auto FltText = StringRef(Ptr, Tok.getLength()+2);
      FltText = copyAndStripUnderscores(FltText);
      
      consumeToken(tok::integer_literal);
      return makeParserResult(new (Context)
                                  FloatLiteralExpr(FltText, DotLoc,
                                                   /*Implicit=*/false));
    }
    
    DeclName Name;
    DeclNameLoc NameLoc;

    if (Tok.is(tok::code_complete)) {
      auto CCE = new (Context) CodeCompletionExpr(Tok.getLoc());
      auto Result = makeParserResult(CCE);
      Result.setHasCodeCompletion();
      if (CodeCompletion) {
        CodeCompletion->completeUnresolvedMember(CCE, DotLoc);
      }
      consumeToken();
      return Result;
    }

    Name = parseUnqualifiedDeclName(/*afterDot=*/true, NameLoc,
                                    diag::expected_identifier_after_dot_expr);
    if (!Name) return nullptr;
    SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);

    // Check for a () suffix, which indicates a call when constructing
    // this member.  Note that this cannot be the start of a new line.
    if (Tok.isFollowingLParen()) {
      SourceLoc lParenLoc, rParenLoc;
      SmallVector<Expr *, 2> args;
      SmallVector<Identifier, 2> argLabels;
      SmallVector<SourceLoc, 2> argLabelLocs;
      Expr *trailingClosure;
      
      ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
                                          /*isPostfix=*/true, isExprBasic,
                                          lParenLoc, args, argLabels,
                                          argLabelLocs,
                                          rParenLoc,
                                          trailingClosure,
                                          SyntaxKind::TupleExprElementList);
      SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);
      return makeParserResult(
                 status,
                 UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
                                              lParenLoc, args, argLabels,
                                              argLabelLocs, rParenLoc,
                                              trailingClosure,
                                              /*implicit=*/false));
    }

    // Check for a trailing closure, if allowed.
    if (Tok.is(tok::l_brace) && isValidTrailingClosure(isExprBasic, *this)) {
      // Add dummy blank argument list to the call expression syntax.
      SyntaxContext->addSyntax(
          ParsedSyntaxRecorder::makeBlankTupleExprElementList(
              Tok.getLoc(), *SyntaxContext));

      ParserResult<Expr> closure =
        parseTrailingClosure(NameLoc.getSourceRange());
      if (closure.isNull()) return nullptr;

      SyntaxContext->createNodeInPlace(SyntaxKind::FunctionCallExpr);
      // Handle .foo by just making an AST node.
      return makeParserResult(
                 ParserStatus(closure),
                 UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
                                              SourceLoc(), { }, { }, { },
                                              SourceLoc(), closure.get(),
                                              /*implicit=*/false));
    }

    // Handle .foo by just making an AST node.
    return makeParserResult(
               UnresolvedMemberExpr::create(Context, DotLoc, NameLoc, Name,
                                            /*implicit=*/false));
  }
      
  case tok::kw_super: // 'super'
    return parseExprSuper();

  case tok::l_paren:
    // Build a tuple expression syntax node.
    // AST differentiates paren and tuple expression where the former allows
    // only one element without label. However, libSyntax tree doesn't have this
    // differentiation. A tuple expression node in libSyntax can have a single
    // element without label.
    ExprContext.setCreateSyntax(SyntaxKind::TupleExpr);
    return parseExprList(tok::l_paren, tok::r_paren,
                         SyntaxKind::TupleExprElementList);

  case tok::l_square:
    return parseExprCollection();

  case tok::pound_quote:
    return parseExprQuoteLiteral();

  case tok::pound_unquote:
    return parseExprUnquote();

  case tok::pound_available: {
    // For better error recovery, parse but reject #available in an expr
    // context.
    diagnose(Tok.getLoc(), diag::availability_query_outside_if_stmt_guard);
    auto res = parseStmtConditionPoundAvailable();
    if (res.hasCodeCompletion())
      return makeParserCodeCompletionStatus();
    if (res.isParseError() || res.isNull())
      return nullptr;
    return makeParserResult(new (Context)
                                ErrorExpr(res.get()->getSourceRange()));
  }

#define POUND_OBJECT_LITERAL(Name, Desc, Proto)                                \
  case tok::pound_##Name:                                                      \
    return parseExprObjectLiteral(ObjectLiteralExpr::Name, isExprBasic);
#include "swift/Syntax/TokenKinds.def"

  case tok::code_complete: {
    auto Result =
        makeParserResult(new (Context) CodeCompletionExpr(Tok.getLoc()));
    Result.setHasCodeCompletion();
    if (CodeCompletion &&
        // We cannot code complete anything after var/let.
        (!InVarOrLetPattern || InVarOrLetPattern == IVOLP_InMatchingPattern)) {
      if (InPoundIfEnvironment) {
        CodeCompletion->completePlatformCondition();
      } else {
        CodeCompletion->completePostfixExprBeginning(
            cast<CodeCompletionExpr>(Result.get()));
      }
    }
    consumeToken(tok::code_complete);
    return Result;
  }

  case tok::pound:
    if (peekToken().is(tok::identifier) && !peekToken().isEscapedIdentifier() &&
        Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
      return parseExprPoundUnknown(SourceLoc());
    }
    if (peekToken().is(tok::code_complete) &&
        Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
      return parseExprPoundCodeCompletion(/*ParentKind*/None);
    }
    goto UnknownCharacter;

  // Eat an invalid token in an expression context.  Error tokens are diagnosed
  // by the lexer, so there is no reason to emit another diagnostic.
  case tok::unknown:
    if (Tok.getText().startswith("\"\"\"")) {
      // This was due to unterminated multi-line string.
      IsInputIncomplete = true;
    }
    consumeToken(tok::unknown);
    return nullptr;

  default:
  UnknownCharacter:
    checkForInputIncomplete();
    // FIXME: offer a fixit: 'Self' -> 'self'
    diagnose(Tok, ID);
    return nullptr;
  }
}

static StringLiteralExpr *
createStringLiteralExprFromSegment(ASTContext &Ctx,
                                   const Lexer *L,
                                   Lexer::StringSegment &Segment,
                                   SourceLoc TokenLoc) {
  assert(Segment.Kind == Lexer::StringSegment::Literal);
  // FIXME: Consider lazily encoding the string when needed.
  llvm::SmallString<256> Buf;
  StringRef EncodedStr = L->getEncodedStringSegment(Segment, Buf);
  if (!Buf.empty()) {
    assert(EncodedStr.begin() == Buf.begin() &&
           "Returned string is not from buffer?");
    EncodedStr = Ctx.AllocateCopy(EncodedStr);
  }
  return new (Ctx) StringLiteralExpr(EncodedStr, TokenLoc);
}

ParserStatus Parser::
parseStringSegments(SmallVectorImpl<Lexer::StringSegment> &Segments,
                    Token EntireTok,
                    VarDecl *InterpolationVar,
                    /* remaining parameters are outputs: */
                    SmallVectorImpl<ASTNode> &Stmts,
                    unsigned &LiteralCapacity,
                    unsigned &InterpolationCount) {
  SourceLoc Loc = EntireTok.getLoc();
  ParserStatus Status;
  ParsedTrivia EmptyTrivia;
  bool First = true;

  DeclName appendLiteral(Context, Context.Id_appendLiteral, { Identifier() });
  DeclName appendInterpolation(Context.Id_appendInterpolation);

  for (auto Segment : Segments) {
    auto InterpolationVarRef =
      new (Context) DeclRefExpr(InterpolationVar,
                                DeclNameLoc(Segment.Loc), /*implicit=*/true);

    switch (Segment.Kind) {
    case Lexer::StringSegment::Literal: {

      // The end location of the entire string literal.
      SourceLoc EndLoc = EntireTok.getLoc().getAdvancedLoc(EntireTok.getLength());

      auto TokenLoc = First ? Loc : Segment.Loc;
      auto Literal = createStringLiteralExprFromSegment(Context, L, Segment,
                                                        TokenLoc);

      LiteralCapacity += Literal->getValue().size();

      auto AppendLiteralRef =
        new (Context) UnresolvedDotExpr(InterpolationVarRef,
                                        /*dotloc=*/SourceLoc(),
                                        appendLiteral,
                                        /*nameloc=*/DeclNameLoc(), 
                                        /*Implicit=*/true);
      auto AppendLiteralCall =
        CallExpr::createImplicit(Context, AppendLiteralRef, {Literal}, {});
      Stmts.push_back(AppendLiteralCall);

      // Since the string is already parsed, Tok already points to the first
      // token after the whole string, but PreviousLoc is not exactly correct.
      PreviousLoc = TokenLoc;
      SourceLoc TokEnd = Segment.IsLastSegment ? EndLoc : Segment.getEndLoc();
      unsigned CommentLength = 0;

      // First segment shall inherit the attached comments.
      if (First && EntireTok.hasComment()) {
        CommentLength = SourceMgr.getByteDistance(EntireTok.getCommentRange().
          getStart(), TokenLoc);
      }
      consumeExtraToken(Token(tok::string_literal,
                              CharSourceRange(SourceMgr, TokenLoc, TokEnd).str(),
                              CommentLength));
      SyntaxParsingContext StrSegContext(SyntaxContext,
                                         SyntaxKind::StringSegment);

      // Make an unknown token to encapsulate the entire string segment and add
      // such token to the context.
      Token content(tok::string_segment,
                    CharSourceRange(Segment.Loc, Segment.Length).str());
      SyntaxContext->addToken(content, EmptyTrivia, EmptyTrivia);
      break;
    }
        
    case Lexer::StringSegment::Expr: {
      SyntaxParsingContext ExprContext(SyntaxContext,
                                       SyntaxKind::ExpressionSegment);

      unsigned DelimiterLen = EntireTok.getCustomDelimiterLen();
      bool HasCustomDelimiter = DelimiterLen > 0;

      // Backslash is part of an expression segment.
      SourceLoc BackSlashLoc = Segment.Loc.getAdvancedLoc(-1 - DelimiterLen);
      Token BackSlash(tok::backslash, CharSourceRange(BackSlashLoc, 1).str());
      ExprContext.addToken(BackSlash, EmptyTrivia, EmptyTrivia);

      // Custom delimiter may be a part of an expression segment.
      if (HasCustomDelimiter) {
        SourceLoc DelimiterLoc = Segment.Loc.getAdvancedLoc(-DelimiterLen);
        Token Delimiter(tok::raw_string_delimiter,
                        CharSourceRange(DelimiterLoc, DelimiterLen).str());
        ExprContext.addToken(Delimiter, EmptyTrivia, EmptyTrivia);
      }

      // Create a temporary lexer that lexes from the body of the string.
      LexerState BeginState =
          L->getStateForBeginningOfTokenLoc(Segment.Loc);
      // We need to set the EOF at r_paren, to prevent the Lexer from eagerly
      // trying to lex the token beyond it. Parser::parseList() does a special
      // check for a tok::EOF that is spelled with a ')'.
      // FIXME: This seems like a hack, there must be a better way..
      LexerState EndState = BeginState.advance(Segment.Length-1);
      Lexer LocalLex(*L, BeginState, EndState);

      // Temporarily swap out the parser's current lexer with our new one.
      llvm::SaveAndRestore<Lexer *> T(L, &LocalLex);

      // Prime the new lexer with a '(' as the first token.
      // We might be at tok::eof now, so ensure that consumeToken() does not
      // assert about lexing past eof.
      Tok.setKind(tok::unknown);
      consumeTokenWithoutFeedingReceiver();
      assert(Tok.is(tok::l_paren));
      TokReceiver->registerTokenKindChange(Tok.getLoc(),
                                           tok::string_interpolation_anchor);

      auto callee = new (Context)
          UnresolvedDotExpr(InterpolationVarRef,
                            /*dotloc=*/BackSlashLoc, appendInterpolation,
                            /*nameloc=*/DeclNameLoc(Segment.Loc),
                            /*Implicit=*/true);
      auto S = parseExprCallSuffix(makeParserResult(callee), true);

      // If we stopped parsing the expression before the expression segment is
      // over, eat the remaining tokens into a token list
      if (Segment.getEndLoc() !=
          L->getLocForEndOfToken(SourceMgr, Tok.getLoc())) {
        SyntaxParsingContext RemainingTokens(SyntaxContext,
                                             SyntaxKind::NonEmptyTokenList);
        do {
          consumeToken();
        } while (Segment.getEndLoc() !=
                 L->getLocForEndOfToken(SourceMgr, Tok.getLoc()));
      }

      Expr *call = S.getPtrOrNull();
      if (!call)
        call = new (Context) ErrorExpr(SourceRange(Segment.Loc,
                                                   Segment.getEndLoc()));

      InterpolationCount += 1;
      Stmts.push_back(call);
      Status |= S;

      if (!Tok.is(tok::eof)) {
        diagnose(Tok, diag::string_interpolation_extra);
      } else if (Tok.getText() == ")") {
        Tok.setKind(tok::string_interpolation_anchor);
        // We don't allow trailing trivia for this anchor, because the
        // trivia is a part of the next string segment.
        TrailingTrivia.clear();
        consumeToken();
      }
      break;
    }
    }
    First = false;
  }
  return Status;
}

///   expr-literal:
///     string_literal
ParserResult<Expr> Parser::parseExprStringLiteral() {
  SyntaxParsingContext LocalContext(SyntaxContext,
                                    SyntaxKind::StringLiteralExpr);

  SmallVector<Lexer::StringSegment, 1> Segments;
  L->getStringLiteralSegments(Tok, Segments);

  Token EntireTok = Tok;

  // The start location of the entire string literal.
  SourceLoc Loc = Tok.getLoc();

  StringRef OpenDelimiterStr, OpenQuoteStr, CloseQuoteStr, CloseDelimiterStr;
  unsigned DelimiterLength = Tok.getCustomDelimiterLen();
  bool HasCustomDelimiter = DelimiterLength > 0;
  unsigned QuoteLength;
  tok QuoteKind;
  std::tie(QuoteLength, QuoteKind) =
    Tok.isMultilineString() ? std::make_tuple(3, tok::multiline_string_quote)
                            : std::make_tuple(1, Tok.getText().startswith("\'") ?
                                          tok::single_quote: tok::string_quote);
  unsigned CloseQuoteBegin = Tok.getLength() - DelimiterLength - QuoteLength;

  OpenDelimiterStr = Tok.getRawText().take_front(DelimiterLength);
  OpenQuoteStr = Tok.getRawText().substr(DelimiterLength, QuoteLength);
  CloseQuoteStr = Tok.getRawText().substr(CloseQuoteBegin, QuoteLength);
  CloseDelimiterStr = Tok.getRawText().take_back(DelimiterLength);

  // Make unknown tokens to represent the open and close quote.
  Token OpenQuote(QuoteKind, OpenQuoteStr);
  Token CloseQuote(QuoteKind, CloseQuoteStr);
  ParsedTrivia EmptyTrivia;
  ParsedTrivia EntireTrailingTrivia = TrailingTrivia;

  if (HasCustomDelimiter) {
    Token OpenDelimiter(tok::raw_string_delimiter, OpenDelimiterStr);
    // When a custom delimiter is present, it owns the leading trivia.
    SyntaxContext->addToken(OpenDelimiter, LeadingTrivia, EmptyTrivia);

    SyntaxContext->addToken(OpenQuote, EmptyTrivia, EmptyTrivia);
  } else {
    // Without custom delimiter the quote owns trailing trivia.
    SyntaxContext->addToken(OpenQuote, LeadingTrivia, EmptyTrivia);
  }

  // The simple case: just a single literal segment.
  if (Segments.size() == 1 &&
      Segments.front().Kind == Lexer::StringSegment::Literal) {
    {
      consumeExtraToken(Tok);
      consumeTokenWithoutFeedingReceiver();

      SyntaxParsingContext SegmentsCtx(SyntaxContext,
                                       SyntaxKind::StringLiteralSegments);

      SyntaxParsingContext StrSegContext(SyntaxContext,
                                         SyntaxKind::StringSegment);

      // Make an unknown token to encapsulate the entire string segment and add
      // such token to the context.
      auto Segment = Segments.front();
      Token content(tok::string_segment,
                    CharSourceRange(Segment.Loc, Segment.Length).str());
      SyntaxContext->addToken(content, EmptyTrivia, EmptyTrivia);
    }

    if (HasCustomDelimiter) {
      SyntaxContext->addToken(CloseQuote, EmptyTrivia, EmptyTrivia);

      Token CloseDelimiter(tok::raw_string_delimiter, CloseDelimiterStr);
      // When a custom delimiter is present it owns the trailing trivia.
      SyntaxContext->addToken(CloseDelimiter, EmptyTrivia, EntireTrailingTrivia);
    } else {
      // Without custom delimiter the quote owns trailing trivia.
      SyntaxContext->addToken(CloseQuote, EmptyTrivia, EntireTrailingTrivia);
    }

    return makeParserResult(
        createStringLiteralExprFromSegment(Context, L, Segments.front(), Loc));
  }

  // We don't expose the entire interpolated string as one token. Instead, we
  // should expose the tokens in each segment.
  consumeTokenWithoutFeedingReceiver();
  // We are going to mess with Tok to do reparsing for interpolated literals,
  // don't lose our 'next' token.
  llvm::SaveAndRestore<Token> SavedTok(Tok);
  llvm::SaveAndRestore<ParsedTrivia> SavedLeadingTrivia(LeadingTrivia);
  llvm::SaveAndRestore<ParsedTrivia> SavedTrailingTrivia(TrailingTrivia);
  // For errors, we need the real PreviousLoc, i.e. the start of the
  // whole InterpolatedStringLiteral.
  llvm::SaveAndRestore<SourceLoc> SavedPreviousLoc(PreviousLoc);

  // We're not in a place where an interpolation would be valid.
  if (!CurLocalContext) {
    // Return an error, but include an empty InterpolatedStringLiteralExpr
    // so that parseDeclPoundDiagnostic() can figure out why this string
    // literal was bad.
    return makeParserErrorResult(new (Context) InterpolatedStringLiteralExpr(
        Loc, Loc.getAdvancedLoc(CloseQuoteBegin), 0, 0, nullptr));
  }

  unsigned LiteralCapacity = 0;
  unsigned InterpolationCount = 0;
  TapExpr * AppendingExpr;

  ParserStatus Status;
  {
    Scope S(this, ScopeKind::Brace);
    SmallVector<ASTNode, 4> Stmts;

    // Make the variable which will contain our temporary value.
    auto InterpolationVar =
      new (Context) VarDecl(/*IsStatic=*/false, VarDecl::Introducer::Var,
                            /*IsCaptureList=*/false, /*NameLoc=*/SourceLoc(),
                            Context.Id_dollarInterpolation, CurDeclContext);
    InterpolationVar->setImplicit(true);
    InterpolationVar->setHasNonPatternBindingInit(true);
    InterpolationVar->setUserAccessible(false);
    addToScope(InterpolationVar);
    setLocalDiscriminator(InterpolationVar);
    
    Stmts.push_back(InterpolationVar);

    // Collect all string segments.
    SyntaxParsingContext SegmentsCtx(SyntaxContext,
                                     SyntaxKind::StringLiteralSegments);
    Status = parseStringSegments(Segments, EntireTok, InterpolationVar, 
                                 Stmts, LiteralCapacity, InterpolationCount);

    auto Body = BraceStmt::create(Context, Loc, Stmts, /*endLoc=*/Loc,
                                  /*implicit=*/true);
    AppendingExpr = new (Context) TapExpr(nullptr, Body);
  }

  if (HasCustomDelimiter) {
    SyntaxContext->addToken(CloseQuote, EmptyTrivia, EmptyTrivia);

    Token CloseDelimiter(tok::raw_string_delimiter, CloseDelimiterStr);
    // When a custom delimiter is present it owns the trailing trivia.
    SyntaxContext->addToken(CloseDelimiter, EmptyTrivia, EntireTrailingTrivia);
  } else {
    // Without custom delimiter the quote owns trailing trivia.
    SyntaxContext->addToken(CloseQuote, EmptyTrivia, EntireTrailingTrivia);
  }

  if (AppendingExpr->getBody()->getNumElements() == 1) {
    Status.setIsParseError();
    return makeParserResult(Status, new (Context) ErrorExpr(Loc));
  }

  return makeParserResult(Status, new (Context) InterpolatedStringLiteralExpr(
                                      Loc, Loc.getAdvancedLoc(CloseQuoteBegin),
                                      LiteralCapacity, InterpolationCount,
                                      AppendingExpr));
}

/// Parse an optional argument label and ':'. Returns \c true if it's parsed.
/// Returns \c false it it's not found.
bool Parser::parseOptionalArgumentLabelSyntax(
    Optional<ParsedTokenSyntax> &name, Optional<ParsedTokenSyntax> &colon) {
  if (!Tok.canBeArgumentLabel() || !peekToken().is(tok::colon))
    return false;

  // If this was an escaped identifier that need not have been escaped, say
  // so. Only _ needs escaping, because we take foo(_: 3) to be equivalent
  // to foo(3), to be more uniform with _ in function declaration as well as
  // the syntax for referring to the function pointer (foo(_:)),
  auto text = Tok.getText();
  auto escaped = Tok.isEscapedIdentifier();
  auto underscore = Tok.is(tok::kw__) || (escaped && text == "_");
  if (escaped && !underscore && canBeArgumentLabel(text)) {
    SourceLoc start = Tok.getLoc();
    SourceLoc end = start.getAdvancedLoc(Tok.getLength());
    diagnose(Tok, diag::escaped_parameter_name, text)
        .fixItRemoveChars(start, start.getAdvancedLoc(1))
        .fixItRemoveChars(end.getAdvancedLoc(-1), end);
  }
  name = consumeArgumentLabelSyntax();
  colon = consumeTokenSyntax(tok::colon);
  return true;
}

void Parser::parseOptionalArgumentLabel(Identifier &name, SourceLoc &loc) {
  // Check to see if there is an argument label.
  if (Tok.canBeArgumentLabel() && peekToken().is(tok::colon)) {
    auto text = Tok.getText();

    // If this was an escaped identifier that need not have been escaped, say
    // so. Only _ needs escaping, because we take foo(_: 3) to be equivalent
    // to foo(3), to be more uniform with _ in function declaration as well as
    // the syntax for referring to the function pointer (foo(_:)),
    auto escaped = Tok.isEscapedIdentifier();
    auto underscore = Tok.is(tok::kw__) || (escaped && text == "_");
    if (escaped && !underscore && canBeArgumentLabel(text)) {
      SourceLoc start = Tok.getLoc();
      SourceLoc end = start.getAdvancedLoc(Tok.getLength());
      diagnose(Tok, diag::escaped_parameter_name, text)
          .fixItRemoveChars(start, start.getAdvancedLoc(1))
          .fixItRemoveChars(end.getAdvancedLoc(-1), end);
    }

    loc = consumeArgumentLabel(name);
    consumeToken(tok::colon);
  }
}

/// Parse unqualified decl name.
///
///   decl-name:
///     identifier decl-name-arguments?
///   decl-name-arguments:
///     '(' decl-name-argument* ')'
///   decl-name-argument:
///     (identifier | '_') ':'
ParserStatus Parser::parseUnqualifiedDeclNameSyntax(
    Optional<ParsedTokenSyntax> &identTok,
    Optional<ParsedDeclNameArgumentsSyntax> &declNameArg, bool afterDot,
    const Diagnostic &diag, bool allowOperators, bool allowZeroArgCompoundNames,
    bool allowDeinitAndSubscript) {

  if (Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_self)) {
    identTok = consumeTokenSyntax();
  } else if (allowOperators && Tok.isAnyOperator()) {
    identTok = consumeTokenSyntax();
  } else if (afterDot && Tok.isKeyword()) {
    if (Tok.is(tok::kw_init) ||
        (allowDeinitAndSubscript &&
         Tok.isAny(tok::kw_deinit, tok::kw_subscript))) {
      // Parse 'init', 'deinit' and 'subscript' as a keyword.
    } else {
      Tok.setKind(tok::identifier);
    }
    identTok = consumeTokenSyntax();
  } else {
    checkForInputIncomplete();
    diagnose(Tok, diag);
    return makeParserError();
  }

  // If the next token isn't a following '(', we don't have a compound name.
  if (!Tok.isFollowingLParen())
    return makeParserSuccess();

  // If the next token is a ')' then we have a 0-arg compound name. This is
  // explicitly differentiated from "simple" (non-compound) name in DeclName.
  // Unfortunately only some places in the grammar are ok with accepting this
  // kind of name; in other places it's ambiguous with trailing calls.
  if (allowZeroArgCompoundNames && peekToken().is(tok::r_paren)) {
    ParsedDeclNameArgumentsSyntaxBuilder builder(*SyntaxContext);
    builder.useLeftParen(consumeTokenSyntax(tok::l_paren));
    builder.useRightParen(consumeTokenSyntax(tok::r_paren));
    declNameArg = builder.build();
    return makeParserSuccess();
  }

  // If the token after that isn't an argument label or ':', we don't have a
  // compound name.
  if ((!peekToken().canBeArgumentLabel() && !peekToken().is(tok::colon)) ||
      Identifier::isEditorPlaceholder(peekToken().getText()))
    return makeParserSuccess();

  ParsedDeclNameArgumentsSyntaxBuilder builder(*SyntaxContext);

  // Try to parse a compound name.
  BacktrackingScope backtrack(*this);

  // Parse '('.
  builder.useLeftParen(consumeTokenSyntax(tok::l_paren));
  while (Tok.isNot(tok::r_paren)) {
    ParsedDeclNameArgumentSyntaxBuilder argBuilder(*SyntaxContext);

    // If we see a ':', the user forgot the '_';
    if (Tok.is(tok::colon)) {
      diagnose(Tok, diag::empty_arg_label_underscore)
          .fixItInsert(Tok.getLoc(), "_");
      argBuilder.useColon(consumeTokenSyntax(tok::colon));
      builder.addArgumentsMember(argBuilder.build());
      continue;
    }

    Optional<ParsedTokenSyntax> name;
    Optional<ParsedTokenSyntax> colon;
    if (parseOptionalArgumentLabelSyntax(name, colon)) {
      argBuilder.useName(std::move(*name));
      argBuilder.useColon(std::move(*colon));
      builder.addArgumentsMember(argBuilder.build());
      continue;
    }

    // This is not a compound name.
    // FIXME: Could recover better if we "know" it's a compound name.
    return makeParserSuccess();
  }

  // We have a compound name. Cancel backtracking and build that name.
  backtrack.cancelBacktrack();

  // Parse ')'.
  builder.useRightParen(consumeTokenSyntax(tok::r_paren));
  declNameArg = builder.build();

  return makeParserSuccess();
}

DeclName Parser::parseUnqualifiedDeclName(bool afterDot, DeclNameLoc &loc,
                                          const Diagnostic &diag,
                                          bool allowOperators,
                                          bool allowZeroArgCompoundNames,
                                          bool allowDeinitAndSubscript) {
  auto leadingLoc = leadingTriviaLoc();
  Optional<ParsedTokenSyntax> parsedIdentTok;
  Optional<ParsedDeclNameArgumentsSyntax> parsedDeclNameArgs;
  auto status = parseUnqualifiedDeclNameSyntax(
      parsedIdentTok, parsedDeclNameArgs, afterDot, diag, allowOperators,
      allowZeroArgCompoundNames, allowDeinitAndSubscript);
  if (status.isError())
    return DeclName();

  SyntaxContext->addSyntax(std::move(*parsedIdentTok));
  auto identTok = SyntaxContext->topNode<TokenSyntax>();

  Optional<DeclNameArgumentsSyntax> declNameArgs;
  if (parsedDeclNameArgs) {
    SyntaxContext->addSyntax(std::move(*parsedDeclNameArgs));
    declNameArgs.emplace(SyntaxContext->topNode<DeclNameArgumentsSyntax>());
  }

  DeclName name;
  std::tie(name, loc) =
      Generator.generateUnqualifiedDeclName(identTok, declNameArgs, leadingLoc);
  return name;
}

///   expr-identifier:
///     unqualified-decl-name generic-argument-clause?
ParsedSyntaxResult<ParsedExprSyntax> Parser::parseExprIdentifierSyntax() {
  assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));

  if (swift::isEditorPlaceholder(Tok.getRawText())) {
    return makeParsedResult(ParsedSyntaxRecorder::makeEditorPlaceholderExpr(
        consumeTokenSyntax(), *SyntaxContext));
  }

  Optional<ParsedTokenSyntax> idTok;
  Optional<ParsedDeclNameArgumentsSyntax> declNameArgs;
  auto status = parseUnqualifiedDeclNameSyntax(idTok, declNameArgs,
                                               /*afterDot=*/false,
                                               diag::expected_expr);
  assert(status.isSuccess() && idTok.hasValue());
  (void)status;

  ParsedIdentifierExprSyntaxBuilder builder(*SyntaxContext);
  builder.useIdentifier(std::move(*idTok));
  if (declNameArgs)
    builder.useDeclNameArguments(std::move(*declNameArgs));

  if (canParseAsGenericArgumentList())
    return parseExprSpecializeSyntax(builder.build());

  return makeParsedResult(builder.build());
}

/// Parse generic argument suffix for the base expression.
///
///   expr-specialize:
///     expr generic-argument-clause
ParsedSyntaxResult<ParsedExprSyntax>
Parser::parseExprSpecializeSyntax(ParsedExprSyntax &&base) {
  assert(startsWithLess(Tok));

  auto LAngleLoc = Tok.getLoc();
  auto genericArgs = parseGenericArgumentClauseSyntax();
  auto status = genericArgs.getStatus();

  if (status.isError())
    diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);
  assert(!genericArgs.isNull());

  auto specializeExpr = ParsedSyntaxRecorder::makeSpecializeExpr(
      std::move(base), genericArgs.get(), *SyntaxContext);
  return makeParsedResult(std::move(specializeExpr), status);
}

Expr *Parser::parseExprIdentifier() {
  auto leadingLoc = leadingTriviaLoc();
  auto parsed = parseExprIdentifierSyntax();
  assert(!parsed.isNull());
  SyntaxContext->addSyntax(parsed.get());

  auto syntax = SyntaxContext->topNode<ExprSyntax>();
  return Generator.generate(syntax, leadingLoc);
}

Expr *Parser::parseExprEditorPlaceholder(SourceLoc loc, StringRef text) {
  auto parseTypeForPlaceholder = [&](TypeLoc &TyLoc, TypeRepr *&ExpansionTyR) {
    Optional<EditorPlaceholderData> DataOpt =
        swift::parseEditorPlaceholder(text);
    if (!DataOpt)
      return;
    StringRef TypeStr = DataOpt->Type;
    if (TypeStr.empty())
      return;

    // Ensure that we restore the parser state at exit.
    ParserPositionRAII PPR(*this);

    auto parseTypeString = [&](StringRef TyStr) -> TypeRepr* {
      unsigned Offset = TyStr.data() - text.data();
      SourceLoc TypeStartLoc = loc.getAdvancedLoc(Offset);
      SourceLoc TypeEndLoc = TypeStartLoc.getAdvancedLoc(TyStr.size());

      LexerState StartState = L->getStateForBeginningOfTokenLoc(TypeStartLoc);
      LexerState EndState = L->getStateForBeginningOfTokenLoc(TypeEndLoc);

      // Create a lexer for the type sub-string.
      Lexer LocalLex(*L, StartState, EndState);

      // Temporarily swap out the parser's current lexer with our new one.
      llvm::SaveAndRestore<Lexer *> T(L, &LocalLex);

      // Don't feed to syntax token recorder.
      ConsumeTokenReceiver DisabledRec;
      llvm::SaveAndRestore<ConsumeTokenReceiver *> R(TokReceiver, &DisabledRec);
      SyntaxParsingContext SContext(SyntaxContext);
      SContext.setDiscard();

      Tok.setKind(tok::unknown); // we might be at tok::eof now.
      consumeTokenWithoutFeedingReceiver();
      return parseType().getPtrOrNull();
    };

    TypeRepr *TyR = parseTypeString(TypeStr);
    TyLoc = TyR;
    if (DataOpt->TypeForExpansion == TypeStr) {
      ExpansionTyR = TyR;
    } else {
      ExpansionTyR = parseTypeString(DataOpt->TypeForExpansion);
    }
  };

  TypeLoc TyLoc;
  TypeRepr *ExpansionTyR = nullptr;
  parseTypeForPlaceholder(TyLoc, ExpansionTyR);
  return new (Context) EditorPlaceholderExpr(Context.getIdentifier(text),
                                             loc, TyLoc, ExpansionTyR);
}

// Extract names of the tuple elements and preserve the structure
// of the tuple (with any nested tuples inside) to be able to use
// it in the fix-it without any type information provided by user.
static void printTupleNames(const TypeRepr *typeRepr, llvm::raw_ostream &OS) {
  if (!typeRepr)
    return;
  
  auto tupleRepr = dyn_cast<TupleTypeRepr>(typeRepr);
  if (!tupleRepr)
    return;
  
  OS << "(";
  unsigned elementIndex = 0;
  llvm::SmallVector<TypeRepr *, 10> elementTypes;
  tupleRepr->getElementTypes(elementTypes);
  interleave(elementTypes,
             [&](const TypeRepr *element) {
               if (isa<TupleTypeRepr>(element)) {
                 printTupleNames(element, OS);
               } else {
                 auto name = tupleRepr->getElementName(elementIndex);
                 // If there is no label from the element
                 // it means that it's malformed and we can
                 // use the type instead.
                 if (name.empty())
                   element->print(OS);
                 else
                   OS << name;
               }
               
               ++elementIndex;
             },
             [&] { OS << ", "; });
  OS << ")";
}

bool Parser::
parseClosureSignatureIfPresent(SmallVectorImpl<CaptureListEntry> &captureList,
                               ParameterList *&params, SourceLoc &throwsLoc,
                               SourceLoc &arrowLoc,
                               TypeRepr *&explicitResultType, SourceLoc &inLoc){
  // Clear out result parameters.
  params = nullptr;
  throwsLoc = SourceLoc();
  arrowLoc = SourceLoc();
  explicitResultType = nullptr;
  inLoc = SourceLoc();

  // If we have a leading token that may be part of the closure signature, do a
  // speculative parse to validate it and look for 'in'.
  if (Tok.isAny(tok::l_paren, tok::l_square, tok::identifier, tok::kw__)) {
    BacktrackingScope backtrack(*this);

    // Skip by a closure capture list if present.
    if (consumeIf(tok::l_square)) {
      skipUntil(tok::r_square);
      if (!consumeIf(tok::r_square))
        return false;
    }

    // Parse pattern-tuple func-signature-result? 'in'.
    if (consumeIf(tok::l_paren)) {      // Consume the ')'.

      // While we don't have '->' or ')', eat balanced tokens.
      while (!Tok.is(tok::r_paren) && !Tok.is(tok::eof))
        skipSingle();

      // Consume the ')', if it's there.
      if (consumeIf(tok::r_paren)) {
        consumeIf(tok::kw_throws) || consumeIf(tok::kw_rethrows);
        // Parse the func-signature-result, if present.
        if (consumeIf(tok::arrow)) {
          if (!canParseType())
            return false;
        }
      }

      // Okay, we have a closure signature.
    } else if (Tok.isIdentifierOrUnderscore()) {
      // Parse identifier (',' identifier)*
      consumeToken();
      while (consumeIf(tok::comma)) {
        if (Tok.isIdentifierOrUnderscore()) {
          consumeToken();
          continue;
        }

        return false;
      }
      
      consumeIf(tok::kw_throws) || consumeIf(tok::kw_rethrows);

      // Parse the func-signature-result, if present.
      if (consumeIf(tok::arrow)) {
        if (!canParseType())
          return false;
      }
    }
    
    // Parse the 'in' at the end.
    if (Tok.isNot(tok::kw_in))
      return false;

    // Okay, we have a closure signature.
  } else {
    // No closure signature.
    return false;
  }
  SyntaxParsingContext ClosureSigCtx(SyntaxContext, SyntaxKind::ClosureSignature);
  if (Tok.is(tok::l_square) && peekToken().is(tok::r_square)) {
    SyntaxParsingContext CaptureCtx(SyntaxContext,
                                    SyntaxKind::ClosureCaptureSignature);
    consumeToken(tok::l_square);
    consumeToken(tok::r_square);
  } else if (Tok.is(tok::l_square) && !peekToken().is(tok::r_square)) {
    SyntaxParsingContext CaptureCtx(SyntaxContext,
                                    SyntaxKind::ClosureCaptureSignature);
    consumeToken(tok::l_square);
    // At this point, we know we have a closure signature. Parse the capture list
    // and parameters.
    bool HasNext;
    do {
      SyntaxParsingContext CapturedItemCtx(SyntaxContext,
                                           SyntaxKind::ClosureCaptureItem);
      SWIFT_DEFER { HasNext = consumeIf(tok::comma); };
      // Check for the strength specifier: "weak", "unowned", or
      // "unowned(safe/unsafe)".
      SourceLoc ownershipLocStart, ownershipLocEnd;
      auto ownershipKind = ReferenceOwnership::Strong;
      if (Tok.isContextualKeyword("weak")){
        ownershipLocStart = ownershipLocEnd = consumeToken(tok::identifier);
        ownershipKind = ReferenceOwnership::Weak;
      } else if (Tok.isContextualKeyword("unowned")) {
        ownershipLocStart = ownershipLocEnd = consumeToken(tok::identifier);
        ownershipKind = ReferenceOwnership::Unowned;

        // Skip over "safe" and "unsafe" if present.
        if (consumeIf(tok::l_paren)) {
          if (Tok.getText() == "safe")
            ownershipKind =
                ReferenceOwnership::Unowned; // FIXME: No "safe" variant.
          else if (Tok.getText() == "unsafe")
            ownershipKind = ReferenceOwnership::Unmanaged;
          else
            diagnose(Tok, diag::attr_unowned_invalid_specifier);
          consumeIf(tok::identifier, ownershipLocEnd);
          if (!consumeIf(tok::r_paren, ownershipLocEnd))
            diagnose(Tok, diag::attr_unowned_expected_rparen);
        }
      } else if (Tok.isAny(tok::identifier, tok::kw_self) &&
                 peekToken().isAny(tok::equal, tok::comma, tok::r_square)) {
        // "x = 42", "x," and "x]" are all strong captures of x.
      } else {
        diagnose(Tok, diag::expected_capture_specifier);
        skipUntil(tok::comma, tok::r_square);
        continue;
      }

      if (Tok.isNot(tok::identifier, tok::kw_self)) {
        diagnose(Tok, diag::expected_capture_specifier_name);
        skipUntil(tok::comma, tok::r_square);
        continue;
      }

      // Squash all tokens, if any, as the specifier of the captured item.
      CapturedItemCtx.collectNodesInPlace(SyntaxKind::TokenList);

      // The thing being capture specified is an identifier, or as an identifier
      // followed by an expression.
      Expr *initializer;
      Identifier name;
      SourceLoc nameLoc = Tok.getLoc();
      SourceLoc equalLoc;
      if (peekToken().isNot(tok::equal)) {
        // If this is the simple case, then the identifier is both the name and
        // the expression to capture.
        name = Context.getIdentifier(Tok.getText());
        initializer = parseExprIdentifier();

        // It is a common error to try to capture a nested field instead of just
        // a local name, reject it with a specific error message.
        if (Tok.isAny(tok::period, tok::exclaim_postfix,tok::question_postfix)){
          diagnose(Tok, diag::cannot_capture_fields);
          skipUntil(tok::comma, tok::r_square);
          continue;
        }

      } else {
        // Otherwise, the name is a new declaration.
        consumeIdentifier(&name);
        equalLoc = consumeToken(tok::equal);

        auto ExprResult = parseExpr(diag::expected_init_capture_specifier);
        if (ExprResult.isNull())
          continue;
        initializer = ExprResult.get();
      }

      // Create the VarDecl and the PatternBindingDecl for the captured
      // expression.  This uses the parent declcontext (not the closure) since
      // the initializer expression is evaluated before the closure is formed.
      auto introducer = (ownershipKind != ReferenceOwnership::Weak
                         ? VarDecl::Introducer::Let
                         : VarDecl::Introducer::Var);
      auto *VD = new (Context) VarDecl(/*isStatic*/false, introducer,
                                       /*isCaptureList*/true,
                                       nameLoc, name, CurDeclContext);

      // Attributes.
      if (ownershipKind != ReferenceOwnership::Strong)
        VD->getAttrs().add(new (Context) ReferenceOwnershipAttr(
          SourceRange(ownershipLocStart, ownershipLocEnd), ownershipKind));

      auto pattern = new (Context) NamedPattern(VD, /*implicit*/true);

      auto *PBD = PatternBindingDecl::create(
          Context, /*StaticLoc*/ SourceLoc(), StaticSpellingKind::None,
          /*VarLoc*/ nameLoc, pattern, /*EqualLoc*/ equalLoc, initializer,
          CurDeclContext);

      captureList.push_back(CaptureListEntry(VD, PBD));
    } while (HasNext);

    SyntaxContext->collectNodesInPlace(SyntaxKind::ClosureCaptureItemList);
    // The capture list needs to be closed off with a ']'.
    if (!consumeIf(tok::r_square)) {
      diagnose(Tok, diag::expected_capture_list_end_rsquare);
      skipUntil(tok::r_square);
      if (Tok.is(tok::r_square))
        consumeToken(tok::r_square);
    }
  }
  
  bool invalid = false;
  if (Tok.isNot(tok::kw_in)) {
    if (Tok.is(tok::l_paren)) {
      // Parse the closure arguments.
      auto pattern = parseSingleParameterClause(ParameterContextKind::Closure);
      if (pattern.isNonNull())
        params = pattern.get();
      else
        invalid = true;
    } else {
      SyntaxParsingContext ClParamListCtx(SyntaxContext,
                                          SyntaxKind::ClosureParamList);
      // Parse identifier (',' identifier)*
      SmallVector<ParamDecl*, 4> elements;
      bool HasNext;
      do {
        SyntaxParsingContext ClParamCtx(SyntaxContext, SyntaxKind::ClosureParam);
        if (Tok.isNot(tok::identifier, tok::kw__)) {
          diagnose(Tok, diag::expected_closure_parameter_name);
          invalid = true;
          break;
        }

        Identifier name;
        SourceLoc nameLoc;
        if (Tok.is(tok::identifier)) {
          nameLoc = consumeIdentifier(&name);
        } else {
          nameLoc = consumeToken(tok::kw__);
        }
        auto var = new (Context)
            ParamDecl(ParamDecl::Specifier::Default, SourceLoc(), SourceLoc(),
                      Identifier(), nameLoc, name, nullptr);
        elements.push_back(var);

        // Consume a comma to continue.
        HasNext = consumeIf(tok::comma);
      } while (HasNext);

      params = ParameterList::create(Context, elements);
    }
    
    if (Tok.is(tok::kw_throws)) {
      throwsLoc = consumeToken();
    } else if (Tok.is(tok::kw_rethrows)) {
      throwsLoc = consumeToken();
      diagnose(throwsLoc, diag::rethrowing_function_type)
        .fixItReplace(throwsLoc, "throws");
    }

    // Parse the optional explicit return type.
    if (Tok.is(tok::arrow)) {
      SyntaxParsingContext ReturnCtx(SyntaxContext, SyntaxKind::ReturnClause);
      // Consume the '->'.
      arrowLoc = consumeToken();

      // Parse the type.
      explicitResultType =
          parseType(diag::expected_closure_result_type).getPtrOrNull();
      if (!explicitResultType) {
        // If we couldn't parse the result type, clear out the arrow location.
        arrowLoc = SourceLoc();
        invalid = true;
      }
    }
  }

  // Parse the 'in'.
  if (Tok.is(tok::kw_in)) {
    inLoc = consumeToken();
  } else {
    // Scan forward to see if we can find the 'in'. This re-synchronizes the
    // parser so we can at least parse the body correctly.
    SourceLoc startLoc = Tok.getLoc();
    ParserPosition pos = getParserPosition();
    while (Tok.isNot(tok::eof) && !Tok.is(tok::kw_in) &&
           Tok.isNot(tok::r_brace)) {
      skipSingle();
    }

    if (Tok.is(tok::kw_in)) {
      // We found the 'in'. If this is the first error, complain about the
      // junk tokens in-between but re-sync at the 'in'.
      if (!invalid) {
        diagnose(startLoc, diag::unexpected_tokens_before_closure_in);
      }
      inLoc = consumeToken();
    } else {
      // We didn't find an 'in', backtrack to where we started. If this is the
      // first error, complain about the missing 'in'.
      backtrackToPosition(pos);
      if (!invalid) {
        diagnose(Tok, diag::expected_closure_in)
          .fixItInsert(Tok.getLoc(), "in ");
      }
      inLoc = Tok.getLoc();
    }
  }

  if (!params)
    return invalid;

  // If this was a closure declaration (maybe even trailing)
  // tuple parameter destructuring is one of the common
  // problems, and is misleading to users, so it's imperative
  // to detect any tuple splat or destructuring as early as
  // possible and give a proper fix-it. See SE-0110 for more details.
  auto isTupleDestructuring = [](ParamDecl *param) -> bool {
    if (!param->isInvalid())
      return false;
    auto &typeLoc = param->getTypeLoc();
    if (auto typeRepr = typeLoc.getTypeRepr())
      return !param->hasName() && isa<TupleTypeRepr>(typeRepr);
    return false;
  };

  for (unsigned i = 0, e = params->size(); i != e; ++i) {
    auto *param = params->get(i);
    if (!isTupleDestructuring(param))
      continue;

    auto argName = "arg" + std::to_string(i);
    auto typeLoc = param->getTypeLoc();

    SmallString<64> fixIt;
    llvm::raw_svector_ostream OS(fixIt);
    auto isMultiLine = Tok.isAtStartOfLine();
    StringRef indent = Lexer::getIndentationForLine(SourceMgr, Tok.getLoc());
    if (isMultiLine)
      OS << '\n' << indent;

    OS << "let ";
    printTupleNames(typeLoc.getTypeRepr(), OS);
    OS << " = " << argName << (isMultiLine ? "\n" + indent : "; ");

    diagnose(param->getStartLoc(), diag::anon_closure_tuple_param_destructuring)
        .fixItReplace(param->getSourceRange(), argName)
        .fixItInsert(Tok.getLoc(), OS.str());

    invalid = true;
  }

  return invalid;
}

ParserResult<Expr> Parser::parseExprClosure() {
  assert(Tok.is(tok::l_brace) && "Not at a left brace?");
  SyntaxParsingContext ClosureContext(SyntaxContext, SyntaxKind::ClosureExpr);
  // We may be parsing this closure expr in a matching pattern context.  If so,
  // reset our state to not be in a pattern for any recursive pattern parses.
  llvm::SaveAndRestore<decltype(InVarOrLetPattern)>
  T(InVarOrLetPattern, IVOLP_NotInVarOrLet);
  
  // Parse the opening left brace.
  SourceLoc leftBrace = consumeToken();

  // Parse the closure-signature, if present.
  ParameterList *params = nullptr;
  SourceLoc throwsLoc;
  SourceLoc arrowLoc;
  TypeRepr *explicitResultType;
  SourceLoc inLoc;
  SmallVector<CaptureListEntry, 2> captureList;
  parseClosureSignatureIfPresent(captureList, params, throwsLoc, arrowLoc,
                                 explicitResultType, inLoc);

  // If the closure was created in the context of an array type signature's
  // size expression, there will not be a local context. A parse error will
  // be reported at the signature's declaration site.
  if (!CurLocalContext) {
    skipUntil(tok::r_brace);
    if (Tok.is(tok::r_brace))
      consumeToken();
    return makeParserError();
  }
  
  unsigned discriminator = CurLocalContext->claimNextClosureDiscriminator();

  // Create the closure expression and enter its context.
  auto *closure = new (Context) ClosureExpr(params, throwsLoc, arrowLoc, inLoc,
                                            explicitResultType,
                                            discriminator, CurDeclContext);
  // The arguments to the func are defined in their own scope.
  Scope S(this, ScopeKind::ClosureParams);
  ParseFunctionBody cc(*this, closure);

  // Handle parameters.
  if (params) {
    // Add the parameters into scope.
    addParametersToScope(params);
    setLocalDiscriminatorToParamList(params);
  } else {
    // There are no parameters; allow anonymous closure variables.
    // FIXME: We could do this all the time, and then provide Fix-Its
    // to map $i -> the appropriately-named argument. This might help
    // users who are refactoring code by adding names.
    AnonClosureVars.push_back({ leftBrace, {}});
  }
  
  // Add capture list variables to scope.
  for (auto c : captureList)
    addToScope(c.Var);

  // Parse the body.
  SmallVector<ASTNode, 4> bodyElements;
  ParserStatus Status;
  Status |= parseBraceItems(bodyElements, BraceItemListKind::Brace);

  // Parse the closing '}'.
  SourceLoc rightBrace;
  parseMatchingToken(tok::r_brace, rightBrace, diag::expected_closure_rbrace,
                     leftBrace);

  // If we didn't have any parameters, create a parameter list from the
  // anonymous closure arguments.
  if (!params) {
    // Create a parameter pattern containing the anonymous variables.
    auto &anonVars = AnonClosureVars.back().second;
    SmallVector<ParamDecl*, 4> elements;
    for (auto anonVar : anonVars)
      elements.push_back(anonVar);
    
    params = ParameterList::create(Context, leftBrace, elements, leftBrace);

    // Pop out of the anonymous closure variables scope.
    AnonClosureVars.pop_back();

    // Attach the parameters to the closure.
    closure->setParameterList(params);
    closure->setHasAnonymousClosureVars();
  }

  // If the body consists of a single expression, turn it into a return
  // statement.
  //
  // But don't do this transformation during code completion, as the source
  // may be incomplete and the type mismatch in return statement will just
  // confuse the type checker.
  bool hasSingleExpressionBody = false;
  if (!Status.hasCodeCompletion() && bodyElements.size() == 1) {
    // If the closure's only body element is a single return statement,
    // use that instead of creating a new wrapping return expression.
    Expr *returnExpr = nullptr;
    
    if (bodyElements[0].is<Stmt *>()) {
      if (auto returnStmt =
                  dyn_cast<ReturnStmt>(bodyElements[0].get<Stmt*>())) {
        
        if (!returnStmt->hasResult()) {
          
          returnExpr = TupleExpr::createEmpty(Context,
                                              SourceLoc(),
                                              SourceLoc(),
                                              /*implicit*/true);
          
          returnStmt->setResult(returnExpr);
        }
        
        hasSingleExpressionBody = true;
      }
    }
    
    // Otherwise, create the wrapping return.
    if (bodyElements[0].is<Expr *>()) {
      hasSingleExpressionBody = true;
      returnExpr = bodyElements[0].get<Expr*>();
      bodyElements[0] = new (Context) ReturnStmt(SourceLoc(),
                                                 returnExpr);
    }
  }

  // Set the body of the closure.
  closure->setBody(BraceStmt::create(Context, leftBrace, bodyElements,
                                     rightBrace),
                   hasSingleExpressionBody);

  // If the closure includes a capture list, create an AST node for it as well.
  Expr *result = closure;
  if (!captureList.empty())
    result = CaptureListExpr::create(Context, captureList, closure);

  return makeParserResult(Status, result);
}

///   expr-anon-closure-argument:
///     dollarident
Expr *Parser::parseExprAnonClosureArg() {
  SyntaxParsingContext ExprContext(SyntaxContext, SyntaxKind::IdentifierExpr);
  StringRef Name = Tok.getText();
  SourceLoc Loc = consumeToken(tok::dollarident);
  assert(Name[0] == '$' && "Not a dollarident");

  // We know from the lexer that this is all-numeric.

  unsigned ArgNo = 0;
  if (Name.substr(1).getAsInteger(10, ArgNo)) {
    diagnose(Loc.getAdvancedLoc(1), diag::dollar_numeric_too_large);
    return new (Context) ErrorExpr(Loc);
  }

  // If this is a closure expression that did not have any named parameters,
  // generate the anonymous variables we need.
  auto closure = dyn_cast_or_null<ClosureExpr>(
      dyn_cast<AbstractClosureExpr>(CurDeclContext));
  if (!closure) {
    if (Context.LangOpts.DebuggerSupport) {
      auto refKind = DeclRefKind::Ordinary;
      auto identifier = Context.getIdentifier(Name);
      return new (Context) UnresolvedDeclRefExpr(DeclName(identifier), refKind,
                                                 DeclNameLoc(Loc));
    }
    diagnose(Loc, diag::anon_closure_arg_not_in_closure);
    return new (Context) ErrorExpr(Loc);
  }
  // When the closure already has explicit parameters, offer their names as
  // replacements.
  if (auto *params = closure->getParameters()) {
    if (ArgNo < params->size() && params->get(ArgNo)->hasName()) {
      auto paramName = params->get(ArgNo)->getNameStr();
      diagnose(Loc, diag::anon_closure_arg_in_closure_with_args_typo, paramName)
        .fixItReplace(Loc, paramName);
      return new (Context) DeclRefExpr(params->get(ArgNo), DeclNameLoc(Loc),
                                       /*Implicit=*/false);
    } else {
      diagnose(Loc, diag::anon_closure_arg_in_closure_with_args);
      return new (Context) ErrorExpr(Loc);
    }
  }

  auto leftBraceLoc = AnonClosureVars.back().first;
  auto &decls = AnonClosureVars.back().second;
  while (ArgNo >= decls.size()) {
    unsigned nextIdx = decls.size();
    SmallVector<char, 4> StrBuf;
    StringRef varName = ("$" + Twine(nextIdx)).toStringRef(StrBuf);
    Identifier ident = Context.getIdentifier(varName);
    SourceLoc varLoc = leftBraceLoc;
    auto *var = new (Context)
        ParamDecl(ParamDecl::Specifier::Default, SourceLoc(), SourceLoc(),
                  Identifier(), varLoc, ident, closure);
    var->setImplicit();
    decls.push_back(var);
  }

  return new (Context) DeclRefExpr(decls[ArgNo], DeclNameLoc(Loc),
                                   /*Implicit=*/false);
}


/// parseExprList - Parse a list of expressions.
///
///   expr-paren:
///     lparen-any ')'
///     lparen-any binary-op ')'
///     lparen-any expr-paren-element (',' expr-paren-element)* ')'
///
///   expr-paren-element:
///     (identifier ':')? expr
///
ParserResult<Expr>
Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
  SmallVector<Expr*, 8> subExprs;
  SmallVector<Identifier, 8> subExprNames;
  SmallVector<SourceLoc, 8> subExprNameLocs;
  Expr *trailingClosure = nullptr;

  SourceLoc leftLoc, rightLoc;
  ParserStatus status = parseExprList(leftTok, rightTok, /*isPostfix=*/false,
                                      /*isExprBasic=*/true,
                                      leftLoc,
                                      subExprs,
                                      subExprNames,
                                      subExprNameLocs,
                                      rightLoc,
                                      trailingClosure,
                                      Kind);

  // A tuple with a single, unlabeled element is just parentheses.
  if (subExprs.size() == 1 &&
      (subExprNames.empty() || subExprNames[0].empty())) {
    return makeParserResult(
        status, new (Context) ParenExpr(leftLoc, subExprs[0], rightLoc,
                                        /*hasTrailingClosure=*/false));
  }

  return makeParserResult(
      status,
      TupleExpr::create(Context, leftLoc, subExprs, subExprNames,
                        subExprNameLocs, rightLoc, /*HasTrailingClosure=*/false,
                        /*Implicit=*/false));
}

/// parseExprList - Parse a list of expressions.
///
///   expr-paren:
///     lparen-any ')'
///     lparen-any binary-op ')'
///     lparen-any expr-paren-element (',' expr-paren-element)* ')'
///
///   expr-paren-element:
///     (identifier ':')? expr
///
ParserStatus Parser::parseExprList(tok leftTok, tok rightTok,
                                   bool isPostfix,
                                   bool isExprBasic,
                                   SourceLoc &leftLoc,
                                   SmallVectorImpl<Expr *> &exprs,
                                   SmallVectorImpl<Identifier> &exprLabels,
                                   SmallVectorImpl<SourceLoc> &exprLabelLocs,
                                   SourceLoc &rightLoc,
                                   Expr *&trailingClosure,
                                   SyntaxKind Kind) {
  trailingClosure = nullptr;

  StructureMarkerRAII ParsingExprList(*this, Tok);
  
  if (ParsingExprList.isFailed()) {
    return makeParserError();
  }

  leftLoc = consumeToken(leftTok);
  ParserStatus status = parseList(rightTok, leftLoc, rightLoc,
                                  /*AllowSepAfterLast=*/false,
                                  rightTok == tok::r_paren
                                    ? diag::expected_rparen_expr_list
                                    : diag::expected_rsquare_expr_list,
                                  Kind,
                                  [&] () -> ParserStatus {
    Identifier FieldName;
    SourceLoc FieldNameLoc;
    if (Kind != SyntaxKind::YieldStmt)
      parseOptionalArgumentLabel(FieldName, FieldNameLoc);

    // See if we have an operator decl ref '(<op>)'. The operator token in
    // this case lexes as a binary operator because it neither leads nor
    // follows a proper subexpression.
    ParserStatus Status;
    Expr *SubExpr = nullptr;
    if (Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma)) {
      SyntaxParsingContext operatorContext(SyntaxContext,
                                           SyntaxKind::IdentifierExpr);
      SourceLoc Loc;
      Identifier OperName;
      if (parseAnyIdentifier(OperName, Loc, diag::expected_operator_ref)) {
        return makeParserError();
      }
      // Bypass local lookup. Use an 'Ordinary' reference kind so that the
      // reference may resolve to any unary or binary operator based on
      // context.
      SubExpr = new(Context) UnresolvedDeclRefExpr(OperName,
                                                   DeclRefKind::Ordinary,
                                                   DeclNameLoc(Loc));
    } else if (isPostfix && Tok.is(tok::code_complete)) {
      // Handle call arguments specially because it may need argument labels.
      auto CCExpr = new (Context) CodeCompletionExpr(Tok.getLoc());
      if (CodeCompletion)
        CodeCompletion->completeCallArg(CCExpr, PreviousLoc == leftLoc);
      consumeIf(tok::code_complete);
      SubExpr = CCExpr;
      Status.setHasCodeCompletion();
    } else {
      auto ParsedSubExpr = parseExpr(diag::expected_expr_in_expr_list);
      SubExpr = ParsedSubExpr.getPtrOrNull();
      Status = ParsedSubExpr;
    }

    // If we got a subexpression, add it.
    if (SubExpr) {
      // Update names and locations.
      if (!exprLabels.empty()) {
        exprLabels.push_back(FieldName);
        exprLabelLocs.push_back(FieldNameLoc);
      } else if (FieldNameLoc.isValid()) {
        exprLabels.resize(exprs.size());
        exprLabels.push_back(FieldName);

        exprLabelLocs.resize(exprs.size());
        exprLabelLocs.push_back(FieldNameLoc);
      }

      // Add the subexpression.
      exprs.push_back(SubExpr);
    }

    return Status;
  });

  // If we aren't interested in trailing closures, or there isn't a valid one,
  // we're done.
  if (!isPostfix || Tok.isNot(tok::l_brace) ||
      !isValidTrailingClosure(isExprBasic, *this))
    return status;

  // Parse the closure.
  ParserResult<Expr> closure =
    parseTrailingClosure(SourceRange(leftLoc, rightLoc));
  status |= closure;
  if (closure.isNull())
    return status;

  // Record the trailing closure.
  trailingClosure = closure.get();

  return status;
}

ParserResult<Expr> Parser::parseTrailingClosure(SourceRange calleeRange) {
  SourceLoc braceLoc = Tok.getLoc();

  // Record the line numbers for the diagnostics below.
  // Note that *do not* move this to after 'parseExprClosure()' it slows down
  // 'getLineNumber()' call because of cache in SourceMgr.
  auto origLine = SourceMgr.getLineNumber(calleeRange.End);
  auto braceLine = SourceMgr.getLineNumber(braceLoc);

  // Parse the closure.
  ParserResult<Expr> closure = parseExprClosure();
  if (closure.isNull())
    return makeParserError();

  // Warn if the trailing closure is separated from its callee by more than
  // one line. A single-line separation is acceptable for a trailing closure
  // call, and will be diagnosed later only if the call fails to typecheck.
  if (braceLine > origLine + 1) {
    diagnose(braceLoc, diag::trailing_closure_after_newlines);
    diagnose(calleeRange.Start, diag::trailing_closure_callee_here);
    
    auto *CE = dyn_cast<ClosureExpr>(closure.get());
    if (CE && CE->hasAnonymousClosureVars() &&
        CE->getParameters()->size() == 0) {
      diagnose(braceLoc, diag::brace_stmt_suggest_do)
        .fixItInsert(braceLoc, "do ");
    }
  }

  return closure;
}
 
/// Parse an object literal expression.
///
/// expr-literal:
///   '#' identifier expr-paren
ParserResult<Expr>
Parser::parseExprObjectLiteral(ObjectLiteralExpr::LiteralKind LitKind,
                               bool isExprBasic) {
  SyntaxParsingContext ObjectLiteralContext(SyntaxContext,
                                            SyntaxKind::ObjectLiteralExpr);
  SourceLoc PoundLoc = consumeToken();
  // Parse a tuple of args
  if (!Tok.is(tok::l_paren)) {
    diagnose(Tok, diag::expected_arg_list_in_object_literal);
    return makeParserError();
  }

  // Parse the argument list.
  SourceLoc lParenLoc, rParenLoc;
  SmallVector<Expr *, 2> args;
  SmallVector<Identifier, 2> argLabels;
  SmallVector<SourceLoc, 2> argLabelLocs;
  Expr *trailingClosure;

  ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
                                      /*isPostfix=*/true, isExprBasic,
                                      lParenLoc, args, argLabels,
                                      argLabelLocs,
                                      rParenLoc,
                                      trailingClosure,
                                      SyntaxKind::TupleExprElementList);
  if (status.hasCodeCompletion())
    return makeParserCodeCompletionResult<Expr>();
  if (status.isError())
    return makeParserError();

  return makeParserResult(
    ObjectLiteralExpr::create(Context, PoundLoc, LitKind, lParenLoc, args,
                              argLabels, argLabelLocs, rParenLoc,
                              trailingClosure, /*implicit=*/false));
}

/// Parse a quote literal expression.
///
/// quote-expr:
///   '#quote' '(' expr ')'
///   '#quote' '{' expr '}'
ParserResult<Expr> Parser::parseExprQuoteLiteral() {
  SyntaxParsingContext RADEContext(SyntaxContext, SyntaxKind::QuoteLiteralExpr);
  auto poundQuoteLoc = consumeToken();
  SourceLoc openLoc;
  SourceLoc closeLoc;

  auto errorAndSkipToEnd = [&]() -> ParserResult<Expr> {
    skipUntilDeclStmtRBrace(tok::r_paren);
    closeLoc = Tok.is(tok::r_paren) ? consumeToken() : PreviousLoc;
    return makeParserResult<Expr>(
        new (Context) ErrorExpr(SourceRange(poundQuoteLoc, closeLoc)));
  };

  ParserResult<Expr> subExprResult;
  if (Tok.is(tok::l_paren)) {
    openLoc = consumeToken();
    subExprResult = parseExpr(diag::expr_quote_expected_expr);
    if (subExprResult.hasCodeCompletion()) {
      return makeParserCodeCompletionResult<Expr>();
    }
    if (subExprResult.isParseError()) {
      return errorAndSkipToEnd();
    }
    if (parseToken(tok::r_paren, closeLoc, diag::expr_quote_expected_rparen)) {
      return makeParserResult<Expr>(
          new (Context) ErrorExpr(SourceRange(poundQuoteLoc, PreviousLoc)));
    }
  } else if (Tok.is(tok::l_brace)) {
    openLoc = Tok.getLoc();
    subExprResult = parseExprClosure();
    if (subExprResult.hasCodeCompletion()) {
      return makeParserCodeCompletionResult<Expr>();
    }
    if (subExprResult.isParseError()) {
      diagnose(openLoc, diag::expr_quote_expected_closure);
      return errorAndSkipToEnd();
    }
  } else {
    diagnose(Tok, diag::expr_quote_expected_lparen_or_lbrace);
    return errorAndSkipToEnd();
  }

  if (Context.LangOpts.EnableExperimentalQuasiquotes) {
    return makeParserResult<Expr>(
        QuoteLiteralExpr::create(Context, poundQuoteLoc, subExprResult.get()));
  } else {
    diagnose(openLoc, diag::expr_quote_enable_experimental_quasiquotes);
    return makeParserResult<Expr>(
        new (Context) ErrorExpr(SourceRange(poundQuoteLoc, PreviousLoc)));
  }
}

/// Parse an unquote expression.
///
/// unquote-expr:
///   '#unquote' '(' expr ')'
ParserResult<Expr> Parser::parseExprUnquote() {
  SyntaxParsingContext RADEContext(SyntaxContext, SyntaxKind::UnquoteExpr);
  auto poundUnquoteLoc = consumeToken();
  SourceLoc openLoc;
  SourceLoc closeLoc;

  auto errorAndSkipToEnd = [&]() -> ParserResult<Expr> {
    skipUntilDeclStmtRBrace(tok::r_paren);
    closeLoc = Tok.is(tok::r_paren) ? consumeToken() : PreviousLoc;
    return makeParserResult<Expr>(
        new (Context) ErrorExpr(SourceRange(poundUnquoteLoc, closeLoc)));
  };

  if (parseToken(tok::l_paren, openLoc, diag::expr_unquote_expected_lparen)) {
    return errorAndSkipToEnd();
  }
  auto subExprResult = parseExpr(diag::expr_unquote_expected_expr);
  if (subExprResult.hasCodeCompletion()) {
    return makeParserCodeCompletionResult<Expr>();
  }
  if (subExprResult.isParseError()) {
    return errorAndSkipToEnd();
  }
  if (parseToken(tok::r_paren, closeLoc, diag::expr_unquote_expected_rparen)) {
    return makeParserResult<Expr>(
        new (Context) ErrorExpr(SourceRange(poundUnquoteLoc, PreviousLoc)));
  }

  if (Context.LangOpts.EnableExperimentalQuasiquotes) {
    return makeParserResult<Expr>(
        UnquoteExpr::create(Context, poundUnquoteLoc, subExprResult.get()));
  } else {
    diagnose(openLoc, diag::expr_unquote_enable_experimental_quasiquotes);
    return makeParserResult<Expr>(
        new (Context) ErrorExpr(SourceRange(poundUnquoteLoc, PreviousLoc)));
  }
}

/// Parse and diagnose unknown pound expression
///
/// If it look like a legacy (Swift 2) object literal expression, suggest fix-it
/// to use new object literal syntax.
///
/// expr-unknown-pound:
///   '#' identifier expr-paren?
///   '[' '#' identifier expr-paren? '#' ']' ; Legacy object literal
ParserResult<Expr> Parser::parseExprPoundUnknown(SourceLoc LSquareLoc) {
  SourceLoc PoundLoc = consumeToken(tok::pound);

  assert(Tok.is(tok::identifier) && !Tok.isEscapedIdentifier() &&
         PoundLoc.getAdvancedLoc(1) == Tok.getLoc());

  Identifier Name;
  SourceLoc NameLoc = consumeIdentifier(&Name);

  // Parse arguments if exist.
  SourceLoc LParenLoc, RParenLoc;
  SmallVector<SourceLoc, 2> argLabelLocs;
  SmallVector<Expr *, 2> args;
  SmallVector<Identifier, 2> argLabels;
  Expr *trailingClosure;
  if (Tok.isFollowingLParen()) {
    // Parse arguments.
    ParserStatus status =
        parseExprList(tok::l_paren, tok::r_paren,
                      /*isPostfix=*/true, /*isExprBasic*/ true, LParenLoc,
                      args, argLabels, argLabelLocs, RParenLoc, trailingClosure,
                      SyntaxKind::TupleExprElementList);
    if (status.hasCodeCompletion())
      return makeParserCodeCompletionResult<Expr>();
    if (status.isError())
      return makeParserError();
  }

  std::pair<StringRef, StringRef> NewNameArgPair =
      llvm::StringSwitch<std::pair<StringRef, StringRef>>(Name.str())
          .Case("Color", {"colorLiteral", "red"})
          .Case("Image", {"imageLiteral", "resourceName"})
          .Case("FileReference", {"fileLiteral", "resourceName"})
          .Default({});

  // If it's not legacy object literal, we don't know how to handle this.
  if (NewNameArgPair.first.empty()) {
    diagnose(PoundLoc, diag::unknown_pound_expr, Name.str());
    return makeParserError();
  }

  // Diagnose legacy object literal.

  // Didn't have arguments.
  if (LParenLoc.isInvalid()) {
    diagnose(Tok.getLoc(), diag::expected_arg_list_in_object_literal);
    return makeParserError();
  }

  // If it's started with '[', try to parse closing '#]'.
  SourceLoc RPoundLoc, RSquareLoc;
  if (LSquareLoc.isValid() && consumeIf(tok::pound, RPoundLoc))
    consumeIf(tok::r_square, RSquareLoc);

  auto diag = diagnose(LSquareLoc.isValid() ? LSquareLoc : PoundLoc,
                       diag::legacy_object_literal, LSquareLoc.isValid(),
                       Name.str(), NewNameArgPair.first);

  // Remove '[' if exist.
  if (LSquareLoc.isValid())
    diag.fixItRemove(LSquareLoc);
  // Replace the literal name.
  diag.fixItReplace(NameLoc, NewNameArgPair.first);
  // Replace the first argument.
  if (!argLabelLocs.empty() && argLabelLocs[0].isValid())
    diag.fixItReplace(argLabelLocs[0], NewNameArgPair.second);
  // Remove '#]' if exist.
  if (RPoundLoc.isValid())
    diag.fixItRemove(
        {RPoundLoc, RSquareLoc.isValid() ? RSquareLoc : RPoundLoc});

  return makeParserError();
}

/// Handle code completion after pound in expression position.
///
/// In case it's in a stmt condition position, specify \p ParentKind to
/// decide the position accepts #available(...) condtion.
///
/// expr-pound-codecompletion:
///   '#' code-completion-token
ParserResult<Expr>
Parser::parseExprPoundCodeCompletion(Optional<StmtKind> ParentKind) {
  assert(Tok.is(tok::pound) && peekToken().is(tok::code_complete) &&
         Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc());
  consumeToken(); // '#' token.
  auto CodeCompletionPos = consumeToken();
  auto Expr = new (Context) CodeCompletionExpr(CodeCompletionPos);
  if (CodeCompletion)
    CodeCompletion->completeAfterPoundExpr(Expr, ParentKind);
  return makeParserCodeCompletionResult(Expr);
}

/// Parse an expression call suffix.
///
/// expr-call-suffix:
///   expr-paren
///   expr-closure (except in expr-basic)
ParserResult<Expr>
Parser::parseExprCallSuffix(ParserResult<Expr> fn, bool isExprBasic) {
  assert(Tok.isFollowingLParen() && "Not a call suffix?");

  // Parse the first argument.

  // If there is a code completion token right after the '(', do a special case
  // callback.
  if (peekToken().is(tok::code_complete) && CodeCompletion) {
    consumeToken(tok::l_paren);
    auto CCE = new (Context) CodeCompletionExpr(Tok.getLoc());
    auto Result = makeParserResult(fn,
      CallExpr::create(Context, fn.get(), SourceLoc(),
                       { CCE },
                       { Identifier() },
                       { },
                       SourceLoc(),
                       /*trailingClosure=*/nullptr,
                       /*implicit=*/false));
    CodeCompletion->completePostfixExprParen(fn.get(), CCE);
    // Eat the code completion token because we handled it.
    consumeToken(tok::code_complete);
    Result.setHasCodeCompletion();
    return Result;
  }

  // Parse the argument list.
  SourceLoc lParenLoc, rParenLoc;
  SmallVector<Expr *, 2> args;
  SmallVector<Identifier, 2> argLabels;
  SmallVector<SourceLoc, 2> argLabelLocs;
  Expr *trailingClosure;

  ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
                                      /*isPostfix=*/true, isExprBasic,
                                      lParenLoc, args, argLabels,
                                      argLabelLocs,
                                      rParenLoc,
                                      trailingClosure,
                                      SyntaxKind::TupleExprElementList);

  // Form the call.
  return makeParserResult(
      status | fn, CallExpr::create(Context, fn.get(), lParenLoc, args,
                                    argLabels, argLabelLocs, rParenLoc,
                                    trailingClosure, /*implicit=*/false));
}

/// parseExprCollection - Parse a collection literal expression.
///
///   expr-collection:
///     expr-array
///     expr-dictionary
///   expr-array:
///     '[' expr (',' expr)* ','? ']'
///     '[' ']'
///   expr-dictionary:
///     '[' expr ':' expr (',' expr ':' expr)* ','? ']'
///     '[' ':' ']'
ParserResult<Expr> Parser::parseExprCollection() {
  SyntaxParsingContext ArrayOrDictContext(SyntaxContext,
                                          SyntaxContextKind::Expr);
  SourceLoc LSquareLoc = consumeToken(tok::l_square);
  SourceLoc RSquareLoc;

  Parser::StructureMarkerRAII ParsingCollection(
                                *this, LSquareLoc,
                                StructureMarkerKind::OpenSquare);

  // [] is always an array.
  if (Tok.is(tok::r_square)) {
    SyntaxContext->addSyntax(
        ParsedSyntaxRecorder::makeBlankArrayElementList(
                              Tok.getLoc(), *SyntaxContext));
    RSquareLoc = consumeToken(tok::r_square);
    ArrayOrDictContext.setCreateSyntax(SyntaxKind::ArrayExpr);
    return makeParserResult(
                    ArrayExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
  }

  // [:] is always an empty dictionary.
  if (Tok.is(tok::colon) && peekToken().is(tok::r_square)) {
    consumeToken(tok::colon);
    RSquareLoc = consumeToken(tok::r_square);
    ArrayOrDictContext.setCreateSyntax(SyntaxKind::DictionaryExpr);
    return makeParserResult(
               DictionaryExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
  }

  // [#identifier is likely to be a legacy object literal.
  if (Tok.is(tok::pound) && peekToken().is(tok::identifier) &&
      !peekToken().isEscapedIdentifier() &&
      LSquareLoc.getAdvancedLoc(1) == Tok.getLoc() &&
      Tok.getLoc().getAdvancedLoc(1) == peekToken().getLoc()) {
    ArrayOrDictContext.setCoerceKind(SyntaxContextKind::Expr);
    return parseExprPoundUnknown(LSquareLoc);
  }

  ParserStatus Status;
  Optional<bool> isDictionary;
  SmallVector<Expr *, 8> ElementExprs;
  SmallVector<SourceLoc, 8> CommaLocs;

  {
    SyntaxParsingContext ListCtx(SyntaxContext, SyntaxContextKind::Expr);

    while (true) {
      SyntaxParsingContext ElementCtx(SyntaxContext);

      auto Element = parseExprCollectionElement(isDictionary);
      Status |= Element;
      ElementCtx.setCreateSyntax(*isDictionary ? SyntaxKind::DictionaryElement
                                               : SyntaxKind::ArrayElement);
      if (Element.isNonNull())
        ElementExprs.push_back(Element.get());

      // Skip to ']' or ',' in case of error.
      // NOTE: This checks 'Status' instead of 'Element' to silence excessive
      // diagnostics.
      if (Status.isError()) {
        skipUntilDeclRBrace(tok::r_square, tok::comma);
        if (Tok.isNot(tok::comma))
          break;
      }

      // Parse the ',' if exists.
      if (Tok.is(tok::comma)) {
        CommaLocs.push_back(consumeToken());
        if (!Tok.is(tok::r_square))
          continue;
      }

      // Close square.
      if (Tok.is(tok::r_square))
        break;

      // If we found EOF or such, bailout.
      if (Tok.is(tok::eof)) {
        IsInputIncomplete = true;
        break;
      }

      // If The next token is at the beginning of a new line and can never start
      // an element, break.
      if (Tok.isAtStartOfLine() && (Tok.isAny(tok::r_brace, tok::pound_endif) ||
                                    isStartOfDecl() || isStartOfStmt()))
        break;

      diagnose(Tok, diag::expected_separator, ",")
          .fixItInsertAfter(PreviousLoc, ",");
      Status.setIsParseError();
    }

    ListCtx.setCreateSyntax(*isDictionary ? SyntaxKind::DictionaryElementList
                                          : SyntaxKind::ArrayElementList);
  }
  ArrayOrDictContext.setCreateSyntax(*isDictionary ? SyntaxKind::DictionaryExpr
                                                   : SyntaxKind::ArrayExpr);

  if (Status.isError()) {
    // If we've already got errors, don't emit missing RightK diagnostics.
    RSquareLoc = Tok.is(tok::r_square) ? consumeToken()
                                       : getLocForMissingMatchingToken();
  } else if (parseMatchingToken(tok::r_square, RSquareLoc,
                                diag::expected_rsquare_array_expr,
                                LSquareLoc)) {
    Status.setIsParseError();
  }

  // Don't bother to create expression if any expressions aren't parsed.
  if (ElementExprs.empty())
    return Status;

  Expr *expr;
  if (*isDictionary)
    expr = DictionaryExpr::create(Context, LSquareLoc, ElementExprs, CommaLocs,
                                  RSquareLoc);
  else
    expr = ArrayExpr::create(Context, LSquareLoc, ElementExprs, CommaLocs,
                             RSquareLoc);

  return makeParserResult(Status, expr);
}

/// parseExprCollectionElement - Parse an element for collection expr.
///
/// If \p isDictionary is \c None, it's set to \c true if the element is for
/// dictionary literal, or \c false otherwise.
ParserResult<Expr>
Parser::parseExprCollectionElement(Optional<bool> &isDictionary) {
  auto Element = parseExpr(isDictionary.hasValue() && *isDictionary
                               ? diag::expected_key_in_dictionary_literal
                               : diag::expected_expr_in_collection_literal);

  if (!isDictionary.hasValue())
    isDictionary = Tok.is(tok::colon);

  if (!*isDictionary) {
    validateCollectionElement(Element);
    return Element;
  }

  if (Element.isNull())
    return Element;

  // Parse the ':'.
  if (!consumeIf(tok::colon)) {
    diagnose(Tok, diag::expected_colon_in_dictionary_literal);
    return ParserStatus(Element) | makeParserError();
  }

  // Parse the value.
  auto Value = parseExpr(diag::expected_value_in_dictionary_literal);

  if (Value.isNull())
    Value = makeParserResult(Value, new (Context) ErrorExpr(PreviousLoc));

  // Make a tuple of Key Value pair.
  return makeParserResult(
      ParserStatus(Element) | ParserStatus(Value),
      TupleExpr::createImplicit(Context, {Element.get(), Value.get()}, {}));
}

/// validateCollectionElement - Check if a given collection element is valid.
///
/// At the moment, this checks whether a given collection element is a subscript
/// expression and whether we're subscripting into an array. If we are, then it
/// we emit a diagnostic in case it was not something that the user was
/// expecting.
///
/// For example: `let array [ [0, 1] [42] ]`
void Parser::validateCollectionElement(ParserResult<Expr> element) {
  if (element.isNull())
    return;

  auto elementExpr = element.get();
  if (!isa<SubscriptExpr>(elementExpr))
    return;

  auto subscriptExpr = cast<SubscriptExpr>(elementExpr);
  if (!isa<ArrayExpr>(subscriptExpr->getBase()))
    return;

  auto arrayExpr = cast<ArrayExpr>(subscriptExpr->getBase());

  auto startLocOfSubscript = subscriptExpr->getIndex()->getStartLoc();
  auto endLocOfArray = arrayExpr->getEndLoc();
  auto locForEndOfTokenArray = L->getLocForEndOfToken(SourceMgr, endLocOfArray);

  if (locForEndOfTokenArray != startLocOfSubscript) {
    auto subscriptLoc = subscriptExpr->getLoc();
    diagnose(subscriptLoc, diag::subscript_array_element)
        .highlight(subscriptExpr->getSourceRange());
    diagnose(subscriptLoc, diag::subscript_array_element_fix_it_add_comma)
        .fixItInsertAfter(endLocOfArray, ",");
    diagnose(subscriptLoc, diag::subscript_array_element_fix_it_remove_space)
        .fixItRemoveChars(locForEndOfTokenArray, startLocOfSubscript);
  }
}

void Parser::addPatternVariablesToScope(ArrayRef<Pattern *> Patterns) {
  for (Pattern *Pat : Patterns) {
    Pat->forEachVariable([&](VarDecl *VD) {
      if (VD->hasName()) {
        // Add any variable declarations to the current scope.
        addToScope(VD);
      }
    });
  }
}

void Parser::addParametersToScope(ParameterList *PL) {
  for (auto param : *PL)
    if (param->hasName())
      addToScope(param);
}



/// Parse availability query specification.
///
///  availability-spec:
///     '*'
///     language-version-constraint-spec
///     package-description-constraint-spec
///     platform-version-constraint-spec
ParserResult<AvailabilitySpec> Parser::parseAvailabilitySpec() {
  if (Tok.isBinaryOperator() && Tok.getText() == "*") {
    SourceLoc StarLoc = Tok.getLoc();
    consumeToken();

    return makeParserResult(new (Context) OtherPlatformAvailabilitySpec(StarLoc));
  }
  if (Tok.isIdentifierOrUnderscore() &&
       (Tok.getText() == "swift" || Tok.getText() == "_PackageDescription"))
      return parsePlatformAgnosticVersionConstraintSpec();

  return parsePlatformVersionConstraintSpec();
}

/// Parse platform-agnostic version constraint specification.
///
///  language-version-constraint-spec:
///     "swift" version-tuple
///  package-description-version-constraint-spec:
///     "_PackageDescription" version-tuple
ParserResult<PlatformAgnosticVersionConstraintAvailabilitySpec>
Parser::parsePlatformAgnosticVersionConstraintSpec() {
  SyntaxParsingContext VersionRestrictionContext(
      SyntaxContext, SyntaxKind::AvailabilityVersionRestriction);
  SourceLoc PlatformAgnosticNameLoc;
  llvm::VersionTuple Version;
  Optional<AvailabilitySpecKind> Kind;
  SourceRange VersionRange;

  if (Tok.isIdentifierOrUnderscore()) {
    if (Tok.getText() == "swift")
      Kind = AvailabilitySpecKind::LanguageVersionConstraint;
    else if (Tok.getText() == "_PackageDescription")
      Kind = AvailabilitySpecKind::PackageDescriptionVersionConstraint;
  }

  if (!Kind.hasValue())
    return nullptr;

  PlatformAgnosticNameLoc = Tok.getLoc();
  consumeToken();
  if (parseVersionTuple(Version, VersionRange,
                        diag::avail_query_expected_version_number)) {
    return nullptr;
  }
  return makeParserResult(new (Context)
                          PlatformAgnosticVersionConstraintAvailabilitySpec(
                            Kind.getValue(), PlatformAgnosticNameLoc, Version, VersionRange));
}

/// Parse platform-version constraint specification.
///
///  platform-version-constraint-spec:
///     identifier version-comparison version-tuple
ParserResult<PlatformVersionConstraintAvailabilitySpec>
Parser::parsePlatformVersionConstraintSpec() {
  SyntaxParsingContext VersionRestrictionContext(
      SyntaxContext, SyntaxKind::AvailabilityVersionRestriction);

  Identifier PlatformIdentifier;
  SourceLoc PlatformLoc;
  if (Tok.is(tok::code_complete)) {
    consumeToken();
    if (CodeCompletion) {
      CodeCompletion->completePoundAvailablePlatform();
    }
    return makeParserCodeCompletionStatus();
  }

  if (parseIdentifier(PlatformIdentifier, PlatformLoc,
                      diag::avail_query_expected_platform_name)) {
    return nullptr;
  }

  if (Tok.isBinaryOperator() && Tok.getText() == ">=") {
    diagnose(Tok, diag::avail_query_version_comparison_not_needed)
        .fixItRemove(Tok.getLoc());
    consumeToken();
  }

  llvm::VersionTuple Version;
  SourceRange VersionRange;

  if (parseVersionTuple(Version, VersionRange,
                        diag::avail_query_expected_version_number)) {
    return nullptr;
  }

  Optional<PlatformKind> Platform =
      platformFromString(PlatformIdentifier.str());

  if (!Platform.hasValue() || Platform.getValue() == PlatformKind::none) {
    diagnose(Tok, diag::avail_query_unrecognized_platform_name,
             PlatformIdentifier);
    Platform = PlatformKind::none;
  }

  // Register the platform name as a keyword token.
  TokReceiver->registerTokenKindChange(PlatformLoc, tok::contextual_keyword);

  return makeParserResult(new (Context) PlatformVersionConstraintAvailabilitySpec(
      Platform.getValue(), PlatformLoc, Version, VersionRange));
}
