@@ -383,7 +383,9 @@ extension Parser {
383
383
384
384
default :
385
385
// If the next token is not an operator, just parse this as expr-postfix.
386
- return self . parsePostfixExpression ( flavor, forDirective: forDirective, inVarOrLet: inVarOrLet)
386
+ return self . parsePostfixExpression (
387
+ flavor, forDirective: forDirective, inVarOrLet: inVarOrLet,
388
+ periodHasKeyPathBehavior: false )
387
389
}
388
390
}
389
391
@@ -405,26 +407,21 @@ extension Parser {
405
407
public mutating func parsePostfixExpression(
406
408
_ flavor: ExprFlavor ,
407
409
forDirective: Bool ,
408
- inVarOrLet: Bool
410
+ inVarOrLet: Bool ,
411
+ periodHasKeyPathBehavior: Bool
409
412
) -> RawExprSyntax {
410
413
let head = self . parsePrimaryExpression ( inVarOrLet: inVarOrLet)
411
414
guard !head. is ( RawMissingExprSyntax . self) else {
412
415
return head
413
416
}
414
- return self . parsePostfixExpressionSuffix ( head, flavor, forDirective: forDirective)
417
+ return self . parsePostfixExpressionSuffix (
418
+ head, flavor, forDirective: forDirective,
419
+ periodHasKeyPathBehavior: periodHasKeyPathBehavior)
415
420
}
416
421
417
422
@_spi ( RawSyntax)
418
423
public mutating func parseDottedExpressionSuffix( _ start: RawExprSyntax ? ) -> RawExprSyntax {
419
424
assert ( self . at ( any: [ . period, . prefixPeriod] ) )
420
-
421
- // A key path is special, because it allows .[, unlike anywhere else. The
422
- // period itself should be left in the token stream. (.? and .! end up
423
- // being operators, and so aren't handled here.)
424
- // if (periodHasKeyPathBehavior && peekToken().is(tok::l_square)) {
425
- // break
426
- // }
427
-
428
425
let period = self . consumeAnyToken ( remapping: . period)
429
426
// Handle "x.42" - a tuple index.
430
427
if let name = self . consume ( if: . integerLiteral) {
@@ -478,7 +475,9 @@ extension Parser {
478
475
// TODO: diagnose and skip.
479
476
return nil
480
477
}
481
- let result = parser. parsePostfixExpressionSuffix ( head, flavor, forDirective: forDirective)
478
+ let result = parser. parsePostfixExpressionSuffix (
479
+ head, flavor, forDirective: forDirective,
480
+ periodHasKeyPathBehavior: false )
482
481
483
482
// TODO: diagnose and skip the remaining token in the current clause.
484
483
return result
@@ -513,7 +512,8 @@ extension Parser {
513
512
public mutating func parsePostfixExpressionSuffix(
514
513
_ start: RawExprSyntax ,
515
514
_ flavor: ExprFlavor ,
516
- forDirective: Bool
515
+ forDirective: Bool ,
516
+ periodHasKeyPathBehavior: Bool
517
517
) -> RawExprSyntax {
518
518
// Handle suffix expressions.
519
519
var leadingExpr = start
@@ -525,6 +525,13 @@ extension Parser {
525
525
526
526
// Check for a .foo suffix.
527
527
if self . at ( any: [ . period, . prefixPeriod] ) {
528
+ // A key path is special, because it allows .[, unlike anywhere else. The
529
+ // period itself should be left in the token stream. (.? and .! end up
530
+ // being operators, and so aren't handled here.)
531
+ if periodHasKeyPathBehavior && self . peek ( ) . tokenKind == . leftSquareBracket {
532
+ break
533
+ }
534
+
528
535
leadingExpr = self . parseDottedExpressionSuffix ( leadingExpr)
529
536
continue
530
537
}
@@ -700,7 +707,9 @@ extension Parser {
700
707
// the token is a operator starts with '.', or the following token is '['.
701
708
let root : RawExprSyntax ?
702
709
if !self . currentToken. starts ( with: " . " ) {
703
- root = self . parsePostfixExpression ( . basic, forDirective: forDirective, inVarOrLet: inVarOrLet)
710
+ root = self . parsePostfixExpression (
711
+ . basic, forDirective: forDirective, inVarOrLet: inVarOrLet,
712
+ periodHasKeyPathBehavior: true )
704
713
} else {
705
714
root = nil
706
715
}
@@ -714,12 +723,16 @@ extension Parser {
714
723
dot = self . consumeAnyToken ( )
715
724
}
716
725
let base = RawExprSyntax ( RawKeyPathBaseExprSyntax ( period: dot, arena: self . arena) )
717
- expression = self . parsePostfixExpressionSuffix ( base, . basic, forDirective: forDirective)
726
+ expression = self . parsePostfixExpressionSuffix (
727
+ base, . basic, forDirective: forDirective,
728
+ periodHasKeyPathBehavior: false )
718
729
} else if self . at ( any: [ . period, . prefixPeriod] ) {
719
730
// Inside a keypath's path, the period always behaves normally: the key path
720
731
// behavior is only the separation between type and path.
721
732
let base = self . parseDottedExpressionSuffix ( nil )
722
- expression = self . parsePostfixExpressionSuffix ( base, . basic, forDirective: forDirective)
733
+ expression = self . parsePostfixExpressionSuffix (
734
+ base, . basic, forDirective: forDirective,
735
+ periodHasKeyPathBehavior: false )
723
736
} else {
724
737
expression = RawExprSyntax ( RawMissingExprSyntax ( arena: self . arena) )
725
738
}
0 commit comments