//===--- 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/ASTWalker.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/EditorPlaceholder.h"
#include "swift/Parse/CodeCompletionCallbacks.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 as an UnresolvedPatternExpr and
  // let pattern type checking determine its final form.
  //
  // 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()));
  }
  
  return parseExprSequence(Message, isExprBasic,
                                /*forConditionalDirective*/false);
}

/// 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(IsExpr::create(Context, 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 = ConditionalCheckedCastExpr::create(Context, asLoc, questionLoc,
                                                type.get());
  } else if (exclaimLoc.isValid()) {
    parsed = ForcedCheckedCastExpr::create(Context, asLoc, exclaimLoc,
                                           type.get());
  } else {
    parsed = CoerceExpr::create(Context, asLoc, type.get());
  }
  return makeParserResult(parsed);
}

/// parseExprArrow
///
///   expr-arrow:
///     'async'? 'throws'? '->'
ParserResult<Expr> Parser::parseExprArrow() {
  SourceLoc asyncLoc, throwsLoc, arrowLoc;
  ParserStatus status;

  status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc,
                                   /*rethrows=*/nullptr);
  if (status.hasCodeCompletion() && !CodeCompletion) {
    // Trigger delayed parsing, no need to continue.
    return status;
  }

  if (Tok.isNot(tok::arrow)) {
    assert(throwsLoc.isValid() || asyncLoc.isValid());
    diagnose(throwsLoc.isValid() ? throwsLoc : asyncLoc,
             diag::async_or_throws_in_wrong_position,
             throwsLoc.isValid() ? "throws" : "async");
    return nullptr;
  }

  arrowLoc = consumeToken(tok::arrow);

  parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc, /*rethrows=*/nullptr);

  auto arrow = new (Context) ArrowExpr(asyncLoc, 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();
  ParserStatus SequenceStatus;
  bool PendingTernary = false;

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

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

    if (SequenceStatus.hasCodeCompletion() && CodeCompletion)
        CodeCompletion->setLeadingSequenceExprs(SequencedExprs);

    if (Primary.isNull()) {
      if (SequenceStatus.hasCodeCompletion()) {
        SequencedExprs.push_back(new (Context) CodeCompletionExpr(PreviousLoc));
        break;
      }
      return nullptr;
    }
    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 (SequenceStatus.isError() && !SequenceStatus.hasCodeCompletion())
      break;

    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);
      SequenceStatus |= middle;
      ParserStatus Status = middle;
      if (middle.isNull())
        return nullptr;

      // Make sure there's a matching ':' after the middle expr.
      if (!Tok.is(tok::colon)) {
        if (middle.hasCodeCompletion()) {
          SequencedExprs.push_back(new (Context) IfExpr(questionLoc,
                                                        middle.get(),
                                                        PreviousLoc));
          SequencedExprs.push_back(new (Context) CodeCompletionExpr(PreviousLoc));
          goto done;
        }
        
        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.
      SequenceStatus |= is;
      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.
      SequenceStatus |= as;
      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::identifier: {
      // 'async' followed by 'throws' or '->' implies that we have an arrow
      // expression.
      if (!(shouldParseExperimentalConcurrency() &&
            Tok.isContextualKeyword("async") &&
            peekToken().isAny(tok::arrow, tok::kw_throws)))
        goto done;

      LLVM_FALLTHROUGH;
    }

    case tok::arrow:
    case tok::kw_throws: {
      SyntaxParsingContext ArrowContext(SyntaxContext, SyntaxKind::ArrowExpr);
      ParserResult<Expr> arrow = parseExprArrow();
      if (arrow.isNull() || arrow.hasCodeCompletion())
        return arrow;
      SequenceStatus |= 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)
    return makeParserResult(SequenceStatus, SequencedExprs[0]);

  ExprSequnceContext.createNodeInPlace(SyntaxKind::ExprList);
  ExprSequnceContext.setCreateSyntax(SyntaxKind::SequenceExpr);
  return makeParserResult(SequenceStatus,
                          SequenceExpr::create(Context, SequencedExprs));
}

/// parseExprSequenceElement
///
///   expr-sequence-element(Mode):
///     'await' expr-sequence-element(Mode)
///     'try' expr-sequence-element(Mode)
///     'try' '?' expr-sequence-element(Mode)
///     'try' '!' expr-sequence-element(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);

  if (Tok.isContextualKeyword("await")) {
    if (shouldParseExperimentalConcurrency()) {
      SourceLoc awaitLoc = consumeToken();
      ParserResult<Expr> sub =
        parseExprSequenceElement(diag::expected_expr_after_await, isExprBasic);
      if (!sub.hasCodeCompletion() && !sub.isNull()) {
        ElementContext.setCreateSyntax(SyntaxKind::AwaitExpr);
        sub = makeParserResult(new (Context) AwaitExpr(awaitLoc, sub.get()));
      }

      return sub;
    } else {
      // warn that future versions of Swift will parse this token differently.
      diagnose(Tok.getLoc(), diag::warn_await_keyword)
        .fixItReplace(Tok.getLoc(), "`await`");
    }
  }

  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) {
      SyntaxParsingContext TyExprCtx(SyntaxContext, SyntaxKind::TypeExpr);
      ParserResult<TypeRepr> ty = parseType();
      if (ty.isNonNull())
        return makeParserResult(
            new (Context) TypeExpr(ty.get()));
      checkForInputIncomplete();
      return nullptr;
    }
  }

  ParserResult<Expr> sub = hadTry
      ? parseExprSequenceElement(message, isExprBasic)
      : parseExprUnary(message, isExprBasic);

  if (hadTry && !sub.hasCodeCompletion() && !sub.isNull()) {
    // "await" must precede "try".
    if (auto await = dyn_cast<AwaitExpr>(sub.get())) {
      diagnose(await->getLoc(), diag::try_before_await)
        .fixItRemove(await->getLoc())
        .fixItInsert(tryLoc, "await ");
    }

    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<CaseStmt> 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;
  ParserStatus parseStatus;

  if (!startsWithSymbol(Tok, '.')) {
    rootResult = parseExprPostfix(diag::expr_keypath_expected_expr,
                                  /*isBasic=*/true);
    parseStatus = rootResult;

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

  bool hasLeadingDot = startsWithSymbol(Tok, '.');
  if (hasLeadingDot) {
    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);
    parseStatus |= pathResult;
  }

  if (rootResult.isNull() && pathResult.isNull())
    return nullptr;

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

  // 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(parseStatus, 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;
  DeclNameOptions flags = DeclNameFlag::AllowCompoundNames;
  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;
    DeclNameRef name = parseDeclNameRef(nameLoc,
        diag::expr_keypath_expected_property_or_type, flags);
    if (!name) {
      status.setIsParseError();
      break;
    }

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

    // After the first component, we can start parsing keywords.
    flags |= DeclNameFlag::AllowKeywords;

    // 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.isErrorOrHasCompletion()) {
    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.isErrorOrHasCompletion()) {
    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);

  // Parse the closing ')'.
  SourceLoc rParenLoc;
  if (subExpr.isParseErrorOrHasCompletion()) {
    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.isParseErrorOrHasCompletion() && !subExpr.hasCodeCompletion())
    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();
  DeclNameRef name(Context.getIdentifier(Tok.getText()));
  consumeToken();
  // Bypass local lookup.
  return new (Context) UnresolvedDeclRefExpr(name, refKind, DeclNameLoc(loc));
}

/// 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;
  }

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

/// Copy a numeric literal value into AST-owned memory, stripping underscores
/// so the semantic part of the value can be parsed by APInt/APFloat parsers.
StringRef Parser::copyAndStripUnderscores(StringRef orig) {
  char *start = static_cast<char*>(Context.Allocate(orig.size(), 1));
  char *p = start;

  if (p) {
    for (char c : orig) {
      if (c != '_') {
        *p++ = c;
      }
    }
  }
  
  return StringRef(start, p - start);
}

/// 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 a token which indicates we should
  // consider it part of the preceding expression
  Parser::BacktrackingScope backtrack(P);
  P.consumeToken(tok::l_brace);
  P.skipUntil(tok::r_brace);
  SourceLoc endLoc;
  if (!P.consumeIf(tok::r_brace, endLoc))
    return false;

  switch (P.Tok.getKind()) {
  case tok::l_brace:
  case tok::kw_where:
  case tok::comma:
    return true;
  case tok::l_square:
  case tok::l_paren:
  case tok::period:
  case tok::period_prefix:
  case tok::kw_is:
  case tok::kw_as:
  case tok::question_postfix:
  case tok::question_infix:
  case tok::exclaim_postfix:
  case tok::colon:
  case tok::equal:
  case tok::oper_postfix:
  case tok::oper_binary_spaced:
  case tok::oper_binary_unspaced:
    return !P.Tok.isAtStartOfLine();
  default:
    return false;
  }
}



/// Map magic literal tokens such as #file to their
/// MagicIdentifierLiteralExpr kind.
static MagicIdentifierLiteralExpr::Kind
getMagicIdentifierLiteralKind(tok Kind, const LangOptions &Opts) {
  switch (Kind) {
  case tok::pound_file:
    // TODO: Enable by default at the next source break. (SR-13199)
    return Opts.EnableConcisePoundFile
         ? MagicIdentifierLiteralExpr::FileIDSpelledAsFile
         : MagicIdentifierLiteralExpr::FilePathSpelledAsFile;
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \
  case tok::TOKEN: \
    return MagicIdentifierLiteralExpr::Kind::NAME;
#include "swift/AST/MagicIdentifierKinds.def"
  default:
    llvm_unreachable("not a magic literal");
  }
}

/// Map magic literal kinds such as #file to their SyntaxKind.
static SyntaxKind
getMagicIdentifierSyntaxKind(MagicIdentifierLiteralExpr::Kind LiteralKind) {
  switch (LiteralKind) {
#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
  case MagicIdentifierLiteralExpr::NAME: \
    return SyntaxKind::SYNTAX_KIND;
#include "swift/AST/MagicIdentifierKinds.def"
  }
  llvm_unreachable("not a magic literal kind");
}

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)) {
        DeclNameRef 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);
        auto CCExpr = new (Context) CodeCompletionExpr(Result.get(),
                                                       Tok.getLoc());
        if (CodeCompletion) {
          CodeCompletion->completeDotExpr(CCExpr, /*DotLoc=*/TokLoc);
        }
        consumeToken(tok::code_complete);
        return makeParserCodeCompletionResult(CCExpr);
      }

      DeclNameLoc NameLoc;
      Diag<> D = isa<SuperRefExpr>(Result.get())
                     ? diag::expected_identifier_after_super_dot_expr
                     : diag::expected_member_name;
      auto Name = parseDeclNameRef(NameLoc, D,
          DeclNameFlag::AllowKeywords | DeclNameFlag::AllowCompoundNames);
      if (!Name) {
        SourceRange ErrorRange = Result.get()->getSourceRange();
        ErrorRange.widen(TokLoc);
        return makeParserErrorResult(new (Context) ErrorExpr(ErrorRange, Type(), Result.get()));
      }
      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.isErrorOrHasCompletion())
          diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);

        SyntaxContext->createNodeInPlace(SyntaxKind::SpecializeExpr);
        Result = makeParserResult(
            Result, UnresolvedSpecializeExpr::create(
                        Context, Result.get(), LAngleLoc, args, 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;
      SmallVector<TrailingClosure, 2> trailingClosures;

      ParserStatus status = parseExprList(
          tok::l_square, tok::r_square,
          /*isPostfix=*/true, isExprBasic, lSquareLoc, indexArgs,
          indexArgLabels, indexArgLabelLocs, rSquareLoc,
          trailingClosures, SyntaxKind::TupleExprElementList);
      Result = makeParserResult(
          status | Result,
          SubscriptExpr::create(Context, Result.get(), lSquareLoc, indexArgs,
                                indexArgLabels, indexArgLabelLocs, rSquareLoc,
                                trailingClosures, 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;

      if (SyntaxContext->isEnabled()) {
        // Add dummy blank argument list to the call expression syntax.
        SyntaxContext->addSyntax(
            ParsedSyntaxRecorder::makeBlankTupleExprElementList(
                leadingTriviaLoc(), *SyntaxContext));
      }

      SmallVector<TrailingClosure, 2> trailingClosures;
      auto trailingResult =
          parseTrailingClosures(isExprBasic, callee->getSourceRange(),
                                trailingClosures);
      if (trailingClosures.empty())
        return nullptr;

      // Trailing closure implicitly forms a call.
      Result = makeParserResult(
          ParserStatus(Result) | trailingResult,
          CallExpr::create(Context, Result.get(), SourceLoc(), {}, {}, {},
                           SourceLoc(), trailingClosures,
                           /*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.setHasCodeCompletionAndIsError();
      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() && Tok.is(tok::unknown)) {
      SourceLoc UnknownLoc = consumeToken();
      SourceRange ErrorRange = Result.get()->getSourceRange();
      ErrorRange.widen(UnknownLoc);
      Result = makeParserResult(Result, new (Context) ErrorExpr(ErrorRange,
                                                                Type(),
                                                                Result.get()));
      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.isParseErrorOrHasCompletion() || 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;
}

/// 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) {
  SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
  switch (Tok.getKind()) {
  case tok::integer_literal: {
    StringRef Text = copyAndStripUnderscores(Tok.getText());
    SourceLoc Loc = consumeToken(tok::integer_literal);
    ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
    return makeParserResult(new (Context)
                                IntegerLiteralExpr(Text, Loc,
                                                   /*Implicit=*/false));
  }
  case tok::floating_literal: {
    StringRef Text = copyAndStripUnderscores(Tok.getText());
    SourceLoc Loc = consumeToken(tok::floating_literal);
    ExprContext.setCreateSyntax(SyntaxKind::FloatLiteralExpr);
    return makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
                                                           /*Implicit=*/false));
  }
  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::kw_nil:
    ExprContext.setCreateSyntax(SyntaxKind::NilLiteralExpr);
    return makeParserResult(new (Context)
                                NilLiteralExpr(consumeToken(tok::kw_nil)));

  case tok::kw_true:
  case tok::kw_false: {
    ExprContext.setCreateSyntax(SyntaxKind::BooleanLiteralExpr);
    bool isTrue = Tok.is(tok::kw_true);
    return makeParserResult(new (Context)
                                BooleanLiteralExpr(isTrue, consumeToken()));
  }

  // Cases for deprecated magic identifier tokens
#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN) case tok::TOKEN:
#include "swift/AST/MagicIdentifierKinds.def"
  {
    auto Kind = getMagicIdentifierLiteralKind(Tok.getKind(), Context.LangOpts);
    auto replacement = MagicIdentifierLiteralExpr::getKindString(Kind);

    diagnose(Tok.getLoc(), diag::snake_case_deprecated,
             Tok.getText(), replacement)
      .fixItReplace(Tok.getLoc(), replacement);
    LLVM_FALLTHROUGH;
  }

  // Cases for non-deprecated magic identifier tokens
  case tok::pound_file:
#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN)
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) case tok::TOKEN:
#include "swift/AST/MagicIdentifierKinds.def"
  {
    auto Kind = getMagicIdentifierLiteralKind(Tok.getKind(), Context.LangOpts);
    SyntaxKind SKind = getMagicIdentifierSyntaxKind(Kind);

    ExprContext.setCreateSyntax(SKind);
    SourceLoc Loc = consumeToken();

    return makeParserResult(new (Context) MagicIdentifierLiteralExpr(
        Kind, Loc, /*implicit=*/false));
  }
      
  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)) {
      DeferringContextRAII Deferring(*SyntaxContext);
      Identifier name;
      SourceLoc loc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/false);
      auto introducer = (InVarOrLetPattern != IVOLP_InVar
                         ? VarDecl::Introducer::Let
                         : VarDecl::Introducer::Var);
      auto pattern = createBindingFromPattern(loc, name, introducer);
      if (SyntaxContext->isEnabled()) {
        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 = parseAnyType();
    return makeParserResult(new (Context) TypeExpr(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));
    }
    
    DeclNameRef Name;
    DeclNameLoc NameLoc;

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

    Name = parseDeclNameRef(NameLoc, diag::expected_identifier_after_dot_expr,
        DeclNameFlag::AllowKeywords | DeclNameFlag::AllowCompoundNames);
    if (!Name)
      return makeParserErrorResult(new (Context) ErrorExpr(DotLoc));
    SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);

    return makeParserResult(new (Context) UnresolvedMemberExpr(
        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_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.isParseErrorOrHasCompletion() || 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.setHasCodeCompletionAndIsError();
    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;

  DeclNameRef appendLiteral(
      { Context, Context.Id_appendLiteral, { Identifier() } });
  DeclNameRef 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;
  {
    SmallVector<ASTNode, 4> Stmts;

    // Make the variable which will contain our temporary value.
    auto InterpolationVar =
      new (Context) VarDecl(/*IsStatic=*/false, VarDecl::Introducer::Var,
                            /*NameLoc=*/SourceLoc(),
                            Context.Id_dollarInterpolation, CurDeclContext);
    InterpolationVar->setImplicit(true);
    InterpolationVar->setUserAccessible(false);
    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));
}

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);
  }
}

static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
                                 SourceLoc &lparenLoc,
                                 SmallVectorImpl<Identifier> &argumentLabels,
                                 SmallVectorImpl<SourceLoc> &argumentLabelLocs,
                                 SourceLoc &rparenLoc) {
  if (!flags.contains(Parser::DeclNameFlag::AllowCompoundNames))
    return false;

  // Is the current token a left paren?
  if (!P.Tok.isFollowingLParen())
    return false;

  // Okay, let's look ahead and see if the next token is something that could
  // be in an arg label list...
  const Token &next = P.peekToken();

  // A close parenthesis, if empty lists are allowed.
  bool nextIsRParen =
      flags.contains(Parser::DeclNameFlag::AllowZeroArgCompoundNames) &&
      next.is(tok::r_paren);
  // An argument label.
  bool nextIsArgLabel = next.canBeArgumentLabel() || next.is(tok::colon);
  // An editor placeholder.
  bool nextIsPlaceholder = Identifier::isEditorPlaceholder(next.getText());

  if (!(nextIsRParen || nextIsArgLabel || nextIsPlaceholder))
    return false;

  // Try to parse a compound name.
  SyntaxParsingContext ArgsCtxt(P.SyntaxContext, SyntaxKind::DeclNameArguments);
  Parser::BacktrackingScope backtrack(P);

  lparenLoc = P.consumeToken(tok::l_paren);
  while (P.Tok.isNot(tok::r_paren)) {
    SyntaxParsingContext ArgCtxt(P.SyntaxContext, SyntaxKind::DeclNameArgument);

    // If we see a ':', the user forgot the '_';
    if (P.Tok.is(tok::colon)) {
      P.diagnose(P.Tok, diag::empty_arg_label_underscore)
          .fixItInsert(P.Tok.getLoc(), "_");
      argumentLabels.push_back(Identifier());
      argumentLabelLocs.push_back(P.consumeToken(tok::colon));
    }

    Identifier argName;
    SourceLoc argLoc;
    P.parseOptionalArgumentLabel(argName, argLoc);
    if (argLoc.isValid()) {
      argumentLabels.push_back(argName);
      argumentLabelLocs.push_back(argLoc);
      continue;
    }

    // This is not a compound name.
    // FIXME: Could recover better if we "know" it's a compound name.
    ArgCtxt.setBackTracking();
    ArgsCtxt.setBackTracking();

    return false;
  }

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

  if (argumentLabels.empty() && P.SyntaxContext->isEnabled())
    P.SyntaxContext->addSyntax(
        ParsedSyntaxRecorder::makeBlankDeclNameArgumentList(
            P.leadingTriviaLoc(), *P.SyntaxContext));
  else
    ArgsCtxt.collectNodesInPlace(SyntaxKind::DeclNameArgumentList);

  rparenLoc = P.consumeToken(tok::r_paren);

  assert(argumentLabels.size() == argumentLabelLocs.size());

  return true;
}

DeclNameRef Parser::parseDeclNameRef(DeclNameLoc &loc,
                                     const Diagnostic &diag,
                                     DeclNameOptions flags) {
  // Consume the base name.
  DeclBaseName baseName;
  SourceLoc baseNameLoc;
  if (Tok.isAny(tok::identifier, tok::kw_Self, tok::kw_self)) {
    Identifier baseNameId;
    baseNameLoc = consumeIdentifier(baseNameId, /*diagnoseDollarPrefix=*/false);
    baseName = baseNameId;
  } else if (flags.contains(DeclNameFlag::AllowOperators) &&
             Tok.isAnyOperator()) {
    baseName = Context.getIdentifier(Tok.getText());
    baseNameLoc = consumeToken();
  } else if (flags.contains(DeclNameFlag::AllowKeywords) && Tok.isKeyword()) {
    bool specialDeinitAndSubscript =
        flags.contains(DeclNameFlag::AllowKeywordsUsingSpecialNames);

    // Syntax highlighting should treat this token as an identifier and
    // not as a keyword.
    if (Tok.is(tok::kw_init))
      baseName = DeclBaseName::createConstructor();
    else if (specialDeinitAndSubscript && Tok.is(tok::kw_deinit))
      baseName = DeclBaseName::createDestructor();
    else if (specialDeinitAndSubscript && Tok.is(tok::kw_subscript))
      baseName = DeclBaseName::createSubscript();
    else
      baseName = Context.getIdentifier(Tok.getText());
    Tok.setKind(tok::identifier);
    baseNameLoc = consumeToken();
  } else {
    baseName = Context.getIdentifier(Tok.getText());
    checkForInputIncomplete();
    diagnose(Tok, diag);
    return DeclNameRef();
  }

  // Parse an argument list, if the flags allow it and it's present.
  SmallVector<Identifier, 2> argumentLabels;
  SmallVector<SourceLoc, 2> argumentLabelLocs;
  SourceLoc lparenLoc;
  SourceLoc rparenLoc;

  bool hadArgList = tryParseArgLabelList(*this, flags, lparenLoc,
                                         argumentLabels, argumentLabelLocs,
                                         rparenLoc);

  if (argumentLabelLocs.empty() || !hadArgList)
    loc = DeclNameLoc(baseNameLoc);
  else
    loc = DeclNameLoc(Context, baseNameLoc, lparenLoc, argumentLabelLocs,
                      rparenLoc);

  if (!hadArgList)
    return DeclNameRef(baseName);

  return DeclNameRef({ Context, baseName, argumentLabels });
}

///   expr-identifier:
///     unqualified-decl-name generic-args?
Expr *Parser::parseExprIdentifier() {
  assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));
  SyntaxParsingContext IDSyntaxContext(SyntaxContext,
                                       SyntaxKind::IdentifierExpr);
  Token IdentTok = Tok;

  // Parse the unqualified-decl-name.
  DeclNameLoc loc;
  DeclNameRef name = parseDeclNameRef(loc, diag::expected_expr,
                                      DeclNameFlag::AllowCompoundNames);

  SmallVector<TypeRepr*, 8> args;
  SourceLoc LAngleLoc, RAngleLoc;
  bool hasGenericArgumentList = false;
  
  ///   The generic-args case is ambiguous with an expression involving '<'
  ///   and '>' operators. The operator expression is favored unless a generic
  ///   argument list can be successfully parsed, and the closing bracket is
  ///   followed by one of these tokens:
  ///     lparen_following rparen lsquare_following rsquare lbrace rbrace
  ///     period_following comma semicolon
  ///
  if (canParseAsGenericArgumentList()) {
    SyntaxContext->createNodeInPlace(SyntaxKind::IdentifierExpr);
    SyntaxContext->setCreateSyntax(SyntaxKind::SpecializeExpr);
    auto argStat = parseGenericArguments(args, LAngleLoc, RAngleLoc);
    if (argStat.isErrorOrHasCompletion())
      diagnose(LAngleLoc, diag::while_parsing_as_left_angle_bracket);
    
    // The result can be empty in error cases.
    hasGenericArgumentList = !args.empty();
  }
  
  if (name.getBaseName().isEditorPlaceholder()) {
    IDSyntaxContext.setCreateSyntax(SyntaxKind::EditorPlaceholderExpr);
    return parseExprEditorPlaceholder(IdentTok, name.getBaseIdentifier());
  }

  auto refKind = DeclRefKind::Ordinary;
  Expr *E = new (Context) UnresolvedDeclRefExpr(name, refKind, loc);
  
  if (hasGenericArgumentList) {
    E = UnresolvedSpecializeExpr::create(Context, E, LAngleLoc, args,
                                         RAngleLoc);
  }
  return E;
}

Expr *Parser::parseExprEditorPlaceholder(Token PlaceholderTok,
                                         Identifier PlaceholderId) {
  assert(PlaceholderTok.is(tok::identifier));
  assert(PlaceholderId.isEditorPlaceholder());

  auto parseTypeForPlaceholder = [&]() -> std::pair<TypeRepr *, TypeRepr *> {
    Optional<EditorPlaceholderData> DataOpt =
      swift::parseEditorPlaceholder(PlaceholderTok.getText());
    if (!DataOpt)
      return {nullptr, nullptr};
    StringRef TypeStr = DataOpt->Type;
    if (TypeStr.empty())
      return {nullptr, nullptr};

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

    auto parseTypeString = [&](StringRef TyStr) -> TypeRepr* {
      unsigned Offset = TyStr.data() - PlaceholderTok.getText().data();
      SourceLoc TypeStartLoc = PlaceholderTok.getLoc().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.disable();

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

    TypeRepr *PlaceholderTyR = parseTypeString(TypeStr);
    TypeRepr *ExpansionTyR = nullptr;
    if (DataOpt->TypeForExpansion == TypeStr) {
      ExpansionTyR = PlaceholderTyR;
    } else {
      ExpansionTyR = parseTypeString(DataOpt->TypeForExpansion);
    }
    return {PlaceholderTyR, ExpansionTyR};
  };

  TypeRepr *PlaceholderTyR = nullptr;
  TypeRepr *ExpansionTyR = nullptr;
  std::tie(PlaceholderTyR, ExpansionTyR) = parseTypeForPlaceholder();
  return new (Context) EditorPlaceholderExpr(
      PlaceholderId, PlaceholderTok.getLoc(), PlaceholderTyR, 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 << ")";
}

ParserStatus Parser::parseClosureSignatureIfPresent(
    SourceRange &bracketRange,
    SmallVectorImpl<CaptureListEntry> &captureList,
    VarDecl *&capturedSelfDecl,
    ParameterList *&params,
    SourceLoc &asyncLoc, SourceLoc &throwsLoc,
    SourceLoc &arrowLoc,
    TypeExpr *&explicitResultType, SourceLoc &inLoc) {
  // Clear out result parameters.
  bracketRange = SourceRange();
  capturedSelfDecl = nullptr;
  params = nullptr;
  throwsLoc = SourceLoc();
  arrowLoc = SourceLoc();
  explicitResultType = nullptr;
  inLoc = SourceLoc();

  // Consume 'async', 'throws', and 'rethrows', but in any order.
  auto consumeEffectsSpecifiers = [&] {
    while (isEffectsSpecifier(Tok) ||
           (Tok.is(tok::code_complete) && !Tok.isAtStartOfLine()))
      consumeToken();
  };

  // 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 makeParserSuccess();
    }

    // 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)) {
        consumeEffectsSpecifiers();

        // Parse the func-signature-result, if present.
        if (consumeIf(tok::arrow)) {
          if (!canParseType())
            return makeParserSuccess();

          consumeEffectsSpecifiers();
        }
      }

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

        return makeParserSuccess();
      }

      consumeEffectsSpecifiers();

      // Parse the func-signature-result, if present.
      if (consumeIf(tok::arrow)) {
        if (!canParseType())
          return makeParserSuccess();

        consumeEffectsSpecifiers();
      }
    }
    
    // Parse the 'in' at the end.
    if (Tok.isNot(tok::kw_in))
      return makeParserSuccess();

    // Okay, we have a closure signature.
  } else {
    // No closure signature.
    return makeParserSuccess();
  }
  ParserStatus status;
  SyntaxParsingContext ClosureSigCtx(SyntaxContext, SyntaxKind::ClosureSignature);
  if (Tok.is(tok::l_square) && peekToken().is(tok::r_square)) {
    
    SyntaxParsingContext CaptureCtx(SyntaxContext,
                                    SyntaxKind::ClosureCaptureSignature);
    SourceLoc lBracketLoc = consumeToken(tok::l_square);
    SourceLoc rBracketLoc = consumeToken(tok::r_square);
    bracketRange = SourceRange(lBracketLoc, rBracketLoc);
  } else if (Tok.is(tok::l_square) && !peekToken().is(tok::r_square)) {
    SyntaxParsingContext CaptureCtx(SyntaxContext,
                                    SyntaxKind::ClosureCaptureSignature);
    SourceLoc lBracketLoc = 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, /*diagnoseDollarPrefix=*/true);
        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,
                                       nameLoc, name, CurDeclContext);
        
      // If we captured something under the name "self", remember that.
      if (name == Context.Id_self)
        capturedSelfDecl = VD;

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

      auto pattern = NamedPattern::createImplicit(Context, VD);

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

      auto CLE = CaptureListEntry(VD, PBD);
      if (CLE.isSimpleSelfCapture())
        VD->setIsSelfParamCapture();

      captureList.push_back(CLE);
    } while (HasNext);

    SyntaxContext->collectNodesInPlace(SyntaxKind::ClosureCaptureItemList);
    // The capture list needs to be closed off with a ']'.
    SourceLoc rBracketLoc = Tok.getLoc();
    if (!consumeIf(tok::r_square)) {
      diagnose(Tok, diag::expected_capture_list_end_rsquare);
      skipUntil(tok::r_square);
      if (Tok.is(tok::r_square))
        rBracketLoc = consumeToken(tok::r_square);
    }
    bracketRange = SourceRange(lBracketLoc, rBracketLoc);
  }
  
  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
        status.setIsParseError();
    } 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);
          status.setIsParseError();
          break;
        }

        Identifier name;
        SourceLoc nameLoc;
        if (Tok.is(tok::identifier)) {
          nameLoc = consumeIdentifier(name, /*diagnoseDollarPrefix=*/true);
        } else {
          nameLoc = consumeToken(tok::kw__);
        }
        auto var = new (Context)
            ParamDecl(SourceLoc(), SourceLoc(),
                      Identifier(), nameLoc, name, nullptr);
        var->setSpecifier(ParamSpecifier::Default);
        elements.push_back(var);

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

      params = ParameterList::create(Context, elements);
    }

    status |= parseEffectsSpecifiers(SourceLoc(), asyncLoc, throwsLoc,
                                     /*rethrows*/nullptr);

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

      // Parse the type.
      auto *explicitResultTypeRepr =
          parseType(diag::expected_closure_result_type).getPtrOrNull();
      if (!explicitResultTypeRepr) {
        // If we couldn't parse the result type, clear out the arrow location.
        arrowLoc = SourceLoc();
        status.setIsParseError();
      } else {
        explicitResultType = new (Context) TypeExpr(explicitResultTypeRepr);

        // Check for 'throws' and 'rethrows' after the type and correct it.
        parseEffectsSpecifiers(arrowLoc, asyncLoc, throwsLoc,
                               /*rethrows*/nullptr);
      }
    }
  }

  // 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 status;

  // 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 {
    auto *typeRepr = param->getTypeRepr();
    if (!(typeRepr && param->isDestructured()))
      return false;
    return !param->hasName() && isa<TupleTypeRepr>(typeRepr);
  };

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

    auto argName = "arg" + std::to_string(i);

    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(param->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());

    status.setIsParseError();
  }

  return status;
}

ParserResult<Expr> Parser::parseExprClosure() {
  assert(Tok.is(tok::l_brace) && "Not at a left brace?");
  ParserStatus Status;
  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.
  SourceRange bracketRange;
  SmallVector<CaptureListEntry, 2> captureList;
  VarDecl *capturedSelfDecl;
  ParameterList *params = nullptr;
  SourceLoc asyncLoc;
  SourceLoc throwsLoc;
  SourceLoc arrowLoc;
  TypeExpr *explicitResultType;
  SourceLoc inLoc;
  Status |= parseClosureSignatureIfPresent(
      bracketRange, captureList, capturedSelfDecl, params, asyncLoc, 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(
      bracketRange, capturedSelfDecl, params, asyncLoc, throwsLoc, arrowLoc,
      inLoc, explicitResultType, discriminator, CurDeclContext);
  ParseFunctionBody cc(*this, closure);

  // Handle parameters.
  if (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});
  }

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

  if (SourceMgr.rangeContainsCodeCompletionLoc({leftBrace, PreviousLoc})) {
    // Ignore 'CodeCompletionDelayedDeclState' inside closures.
    // Completions inside functions body inside closures at top level should
    // be considered top-level completions.
    if (State->hasCodeCompletionDelayedDeclState())
      (void)State->takeCodeCompletionDelayedDeclState();
    Status.setHasCodeCompletionAndIsError();
  }

  // Parse the closing '}'.
  SourceLoc rightBrace;
  bool missingRBrace = parseMatchingToken(tok::r_brace, rightBrace,
                                          diag::expected_closure_rbrace,
                                          leftBrace);
  if (missingRBrace) {
    Status.setIsParseError();
  } else {
    // We recovered so don't propagate any error status (but still preserve
    // HasCodeCompletion).
    Status.clearIsError();
  }

  // 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().Item;
    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.
  bool hasSingleExpressionBody = false;
  if (!missingRBrace &&
      Parser::shouldReturnSingleExpressionElement(bodyElements)) {
    auto Element = bodyElements.back();
    
    if (Element.is<Stmt *>()) {
      if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
        hasSingleExpressionBody = true;
        if (!returnStmt->hasResult()) {
          auto returnExpr = TupleExpr::createEmpty(Context,
                                                   SourceLoc(),
                                                   SourceLoc(),
                                                   /*implicit*/true);
          returnStmt->setResult(returnExpr);
        }
      }
    } else if (Element.is<Expr *>()) {
      // Create the wrapping return.
      hasSingleExpressionBody = true;
      auto returnExpr = Element.get<Expr*>();
      bodyElements.back() = 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(DeclNameRef(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().Loc;
  auto &decls = AnonClosureVars.back().Item;
  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(SourceLoc(), SourceLoc(),
                  Identifier(), varLoc, ident, closure);
    var->setSpecifier(ParamSpecifier::Default);
    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;
  SmallVector<TrailingClosure, 2> trailingClosures;

  SourceLoc leftLoc, rightLoc;
  ParserStatus status = parseExprList(leftTok, rightTok, /*isPostfix=*/false,
                                      /*isExprBasic=*/true,
                                      leftLoc,
                                      subExprs,
                                      subExprNames,
                                      subExprNameLocs,
                                      rightLoc,
                                      trailingClosures,
                                      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,
                                   SmallVectorImpl<TrailingClosure> &trailingClosures,
                                   SyntaxKind Kind) {
  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);
      DeclNameLoc Loc;
      auto OperName = parseDeclNameRef(Loc, diag::expected_operator_ref,
                                       DeclNameFlag::AllowOperators);
      if (!OperName) {
        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, 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.setHasCodeCompletionAndIsError();
    } 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.
  status |=
      parseTrailingClosures(isExprBasic, SourceRange(leftLoc, rightLoc),
                            trailingClosures);
  return status;
}

static bool isStartOfLabelledTrailingClosure(Parser &P) {
  // Fast path: the next two tokens must be a label and a colon.
  // But 'default:' is ambiguous with switch cases and we disallow it
  // (unless escaped) even outside of switches.
  if (!P.Tok.canBeArgumentLabel() ||
      P.Tok.is(tok::kw_default) ||
      !P.peekToken().is(tok::colon))
    return false;

  // Do some tentative parsing to distinguish `label: { ... }` and
  // `label: switch x { ... }`.
  Parser::BacktrackingScope backtrack(P);
  P.consumeToken();
  if (P.peekToken().is(tok::l_brace))
    return true;
  // Parse editor placeholder as trailing closure so SourceKit can expand it to
  // closure literal.
  if (P.peekToken().is(tok::identifier) &&
      Identifier::isEditorPlaceholder(P.peekToken().getText()))
    return true;
  // Consider `label: <complete>` that the user is trying to write a closure.
  if (P.peekToken().is(tok::code_complete) && !P.peekToken().isAtStartOfLine())
    return true;
  return false;
}

ParserStatus
Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange,
                              SmallVectorImpl<TrailingClosure> &closures) {
  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.getLineAndColumnInBuffer(calleeRange.End).first;
  auto braceLine = SourceMgr.getLineAndColumnInBuffer(braceLoc).first;

  ParserStatus result;

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

  result |= closure;

  closures.push_back({closure.get()});

  // 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>(closures[0].ClosureExpr);
    if (CE && CE->hasAnonymousClosureVars() &&
        CE->getParameters()->size() == 0) {
      diagnose(braceLoc, diag::brace_stmt_suggest_do)
        .fixItInsert(braceLoc, "do ");
    }
  }

  // Parse labeled trailing closures.
  while (true) {
    if (!isStartOfLabelledTrailingClosure(*this)) {
      if (!Tok.is(tok::code_complete))
        break;

      // FIXME: Additional trailing closure completion on newline positions.
      //   let foo = SomeThing {
      //     ...
      //   }
      //   <HERE>
      // This was previously enabled, but it failed to suggest 'foo' because
      // the token was considered a part of the initializer.
      if (Tok.isAtStartOfLine())
        break;

      // If the current completion mode doesn't support trailing closure
      // completion, leave the token here and let "postfix completion" to
      // handle it.
      if (CodeCompletion &&
          !CodeCompletion->canPerformCompleteLabeledTrailingClosure())
        break;

      // foo() {} <token>
      auto CCExpr = new (Context) CodeCompletionExpr(Tok.getLoc());
      if (CodeCompletion)
        CodeCompletion->completeLabeledTrailingClosure(CCExpr, Tok.isAtStartOfLine());
      consumeToken(tok::code_complete);
      result.setHasCodeCompletionAndIsError();
      closures.push_back({Identifier(), SourceLoc(), CCExpr});
      continue;
    }

    SyntaxParsingContext ClosureCtx(SyntaxContext,
                                    SyntaxKind::MultipleTrailingClosureElement);
    Identifier label;
    auto labelLoc = consumeArgumentLabel(label);
    consumeToken(tok::colon);
    ParserResult<Expr> closure;
    if (Tok.is(tok::l_brace)) {
      closure = parseExprClosure();
    } else if (Tok.is(tok::identifier)) {
      // Parse editor placeholder as a closure literal.
      assert(Identifier::isEditorPlaceholder(Tok.getText()));
      SyntaxParsingContext IdCtx(SyntaxContext,
                                 SyntaxKind::EditorPlaceholderExpr);
      Identifier name = Context.getIdentifier(Tok.getText());
      closure = makeParserResult(parseExprEditorPlaceholder(Tok, name));
      consumeToken(tok::identifier);
    } else if (Tok.is(tok::code_complete)) {
      assert(!Tok.isAtStartOfLine() &&
             "isStartOfLabelledTrailingClosure() should return false");
      // Swallow code completion token after the label.
      // FIXME: Closure literal completion.
      consumeToken(tok::code_complete);
      return makeParserCodeCompletionStatus();
    }
    if (closure.isNull())
      return makeParserError();

    result |= closure;
    closures.push_back({label, labelLoc, closure.get()});

    // Don't diagnose whitespace gaps before labelled closures.
  }
  SyntaxContext->collectNodesInPlace(
      SyntaxKind::MultipleTrailingClosureElementList);

  return result;
}

/// 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;
  SmallVector<TrailingClosure, 2> trailingClosures;

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

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

/// 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, /*diagnoseDollarPrefix=*/false);

  // Parse arguments if exist.
  SourceLoc LParenLoc, RParenLoc;
  SmallVector<SourceLoc, 2> argLabelLocs;
  SmallVector<Expr *, 2> args;
  SmallVector<Identifier, 2> argLabels;
  SmallVector<TrailingClosure, 2> trailingClosures;
  if (Tok.isFollowingLParen()) {
    // Parse arguments.
    ParserStatus status =
        parseExprList(tok::l_paren, tok::r_paren,
                      /*isPostfix=*/true, /*isExprBasic*/ true, LParenLoc,
                      args, argLabels, argLabelLocs, RParenLoc,
                      trailingClosures, SyntaxKind::TupleExprElementList);
    if (status.hasCodeCompletion())
      return makeParserCodeCompletionResult<Expr>();
    if (status.isErrorOrHasCompletion())
      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?");

  SourceLoc lParenLoc, rParenLoc;
  SmallVector<Expr *, 2> args;
  SmallVector<Identifier, 2> argLabels;
  SmallVector<SourceLoc, 2> argLabelLocs;
  SmallVector<TrailingClosure, 2> trailingClosures;

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

  // Parse the argument list.
  ParserStatus status = parseExprList(tok::l_paren, tok::r_paren,
                                      /*isPostfix=*/true, isExprBasic,
                                      lParenLoc, args, argLabels,
                                      argLabelLocs,
                                      rParenLoc,
                                      trailingClosures,
                                      SyntaxKind::TupleExprElementList);

  // Form the call.
  return makeParserResult(status | fn,
                          CallExpr::create(Context, fn.get(), lParenLoc, args,
                                           argLabels, argLabelLocs, rParenLoc,
                                           trailingClosures,
                                           /*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)) {
    if (SyntaxContext->isEnabled())
      SyntaxContext->addSyntax(ParsedSyntaxRecorder::makeBlankArrayElementList(
          leadingTriviaLoc(), *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.isErrorOrHasCompletion()) {
        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) ||
                                    isStartOfSwiftDecl() || 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.isErrorOrHasCompletion()) {
    // 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 ':'.
  ParserResult<Expr> Value;
  if (consumeIf(tok::colon)) {
    // Parse the value.
    Value = parseExpr(diag::expected_value_in_dictionary_literal);
    if (Value.isNull()) {
      if (!Element.hasCodeCompletion()) {
        Value = makeParserResult(Value, new (Context) ErrorExpr(PreviousLoc));
      } else {
        Value = makeParserResult(Value,
                                 new (Context) CodeCompletionExpr(PreviousLoc));
      }
    }
  } else {
    diagnose(Tok, diag::expected_colon_in_dictionary_literal);
    Value = makeParserResult(makeParserError(),
                             new (Context) ErrorExpr(SourceRange()));
  }

  // 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);
  }
}



/// 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,
                      /*diagnoseDollarPrefix=*/false,
                      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);

  // Keep the original version around for run-time checks to support
  // macOS Big Sur betas that report 10.16 at
  // run time.
  llvm::VersionTuple RuntimeVersion = Version;
  Version = canonicalizePlatformVersion(*Platform, Version);
  return makeParserResult(new (Context) PlatformVersionConstraintAvailabilitySpec(
      Platform.getValue(), PlatformLoc, Version, RuntimeVersion, VersionRange));
}
