@@ -627,97 +627,79 @@ ParserResult<Expr> Parser::parseExprKeyPath() {
627
627
// / expr-keypath-objc:
628
628
// / '#keyPath' '(' unqualified-name ('.' unqualified-name) * ')'
629
629
// /
630
- ParserResult<Expr> Parser::parseExprKeyPathObjC () {
631
- SyntaxParsingContext ObjcKPCtx (SyntaxContext, SyntaxKind::ObjcKeyPathExpr);
630
+ ParsedSyntaxResult<ParsedExprSyntax> Parser::parseExprObjcKeyPathSyntax () {
631
+ ParsedObjcKeyPathExprSyntaxBuilder builder (*SyntaxContext);
632
+ ParserStatus status;
633
+
632
634
// Consume '#keyPath'.
633
- SourceLoc keywordLoc = consumeToken ( tok::pound_keyPath);
635
+ builder. useKeyPath ( consumeTokenSyntax ( tok::pound_keyPath) );
634
636
635
637
// Parse the leading '('.
636
638
if (!Tok.is (tok::l_paren)) {
637
639
diagnose (Tok, diag::expr_keypath_expected_lparen);
638
- return makeParserError ( );
640
+ return makeParsedError (builder. build () );
639
641
}
640
- SourceLoc lParenLoc = consumeToken (tok::l_paren);
641
-
642
- SmallVector<KeyPathExpr::Component, 4 > components;
643
- // / Handler for code completion.
644
- auto handleCodeCompletion = [&](SourceLoc DotLoc) -> ParserResult<Expr> {
645
- KeyPathExpr *expr = nullptr ;
646
- if (!components.empty ()) {
647
- expr = new (Context)
648
- KeyPathExpr (Context, keywordLoc, lParenLoc, components, Tok.getLoc ());
649
- }
650
-
651
- if (CodeCompletion)
652
- CodeCompletion->completeExprKeyPath (expr, DotLoc);
653
-
654
- // Eat the code completion token because we handled it.
655
- consumeToken (tok::code_complete);
656
- return makeParserCodeCompletionResult (expr);
657
- };
642
+ auto LParenLoc = Tok.getLoc ();
643
+ builder.useLeftParen (consumeTokenSyntax (tok::l_paren));
658
644
659
645
// Parse the sequence of unqualified-names.
660
- ParserStatus status;
661
- SourceLoc LastDotLoc;
662
- while (true ) {
663
- SyntaxParsingContext NamePieceCtx (SyntaxContext, SyntaxKind::ObjcNamePiece);
664
- // Handle code completion.
665
- if (Tok.is (tok::code_complete))
666
- return handleCodeCompletion (LastDotLoc);
667
-
668
- // Parse the next name.
669
- DeclNameLoc nameLoc;
670
- bool afterDot = !components.empty ();
671
- auto name = parseUnqualifiedDeclName (
672
- afterDot, nameLoc,
673
- diag::expr_keypath_expected_property_or_type);
674
- if (!name) {
675
- status.setIsParseError ();
646
+ bool isFirst = true ;
647
+ bool hasNext = true ;
648
+ do {
649
+ // Parse the next name
650
+ Optional<ParsedTokenSyntax> identTok;
651
+ Optional<ParsedDeclNameArgumentsSyntax> declNameArgs;
652
+ status |= parseUnqualifiedDeclNameSyntax (
653
+ identTok, declNameArgs, /* afterDot=*/ !isFirst,
654
+ diag::expr_keypath_expected_property_or_type);
655
+ isFirst = false ;
656
+ if (status.isError ())
676
657
break ;
677
- }
678
658
679
- // Record the name we parsed.
680
- auto component = KeyPathExpr::Component::forUnresolvedProperty (name,
681
- nameLoc.getBaseNameLoc ());
682
- components.push_back (component);
659
+ ParsedObjcNamePieceSyntaxBuilder elemBuilder (*SyntaxContext);
683
660
684
- // Handle code completion.
685
- if (Tok. is (tok::code_complete) )
686
- return handleCodeCompletion ( SourceLoc ( ));
661
+ elemBuilder. useName ( std::move (*identTok));
662
+ if (declNameArgs )
663
+ elemBuilder. useDeclNameArguments ( std::move (*declNameArgs ));
687
664
688
- // Parse the next period to continue the path.
689
- if (consumeIf (tok::period, LastDotLoc))
690
- continue ;
665
+ hasNext = Tok.is (tok::period);
666
+ if (hasNext)
667
+ elemBuilder.useDot (consumeTokenSyntax (tok::period));
668
+ builder.addNameMember (elemBuilder.build ());
669
+ } while (hasNext);
691
670
692
- break ;
671
+ if (Tok.is (tok::code_complete)) {
672
+ return makeParsedCodeCompletion (
673
+ ParsedSyntaxRecorder::makeCodeCompletionExpr (
674
+ builder.build (), None, consumeTokenSyntax (tok::code_complete),
675
+ *SyntaxContext));
693
676
}
694
677
695
- // Collect all name pieces to an objc name.
696
- SyntaxContext->collectNodesInPlace (SyntaxKind::ObjcName);
697
-
698
- // Parse the closing ')'.
699
- SourceLoc rParenLoc;
700
678
if (status.isError ()) {
701
- skipUntilDeclStmtRBrace (tok::r_paren);
702
- if (Tok.is (tok::r_paren))
703
- rParenLoc = consumeToken ();
704
- else
705
- rParenLoc = PreviousLoc;
706
- } else {
707
- parseMatchingToken (tok::r_paren, rParenLoc,
708
- diag::expr_keypath_expected_rparen, lParenLoc);
679
+ while (!Tok.isAny (tok::r_paren, tok::eof, tok::r_brace, tok::pound_endif,
680
+ tok::pound_else, tok::pound_elseif) &&
681
+ !isStartOfDecl () && !isStartOfStmt ())
682
+ ignoreSingle ();
709
683
}
710
684
711
- // If we cannot build a useful expression, just return an error
712
- // expression.
713
- if (components.empty () || status.isError ()) {
714
- return makeParserResult<Expr>(
715
- new (Context) ErrorExpr (SourceRange (keywordLoc, rParenLoc)));
716
- }
685
+ // Parse the closing ')'.
686
+ auto RParen =
687
+ parseMatchingTokenSyntax (tok::r_paren, diag::expr_keypath_expected_rparen,
688
+ LParenLoc, /* silenceDiag=*/ status.isError ());
689
+ status |= RParen.getStatus ();
690
+ if (!RParen.isNull ())
691
+ builder.useRightParen (RParen.get ());
692
+
693
+ return makeParsedResult (builder.build (), status);
694
+ }
717
695
718
- // We're done: create the key-path expression.
719
- return makeParserResult<Expr>(new (Context) KeyPathExpr (
720
- Context, keywordLoc, lParenLoc, components, rParenLoc));
696
+ ParserResult<Expr> Parser::parseExprKeyPathObjC () {
697
+ auto leadingLoc = leadingTriviaLoc ();
698
+ auto parsed = parseExprObjcKeyPathSyntax ();
699
+ SyntaxContext->addSyntax (parsed.get ());
700
+ auto syntax = SyntaxContext->topNode <ExprSyntax>();
701
+ auto expr = Generator.generate (syntax, leadingLoc);
702
+ return makeParserResult (parsed.getStatus (), expr);
721
703
}
722
704
723
705
// / parseExprSelector
0 commit comments