Skip to content

Commit 892b73b

Browse files
authored
Merge pull request #793 from CodaFi/a-touch-of-gray
A Grab Bag of Miscellaneous Parser Fixes
2 parents ef80186 + 10825a7 commit 892b73b

File tree

20 files changed

+576
-184
lines changed

20 files changed

+576
-184
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ extension Parser {
5353
return RawSyntax(self.parseDynamicReplacementAttribute())
5454
case ._spi:
5555
return RawSyntax(self.parseSPIAttribute())
56+
case ._implements:
57+
return RawSyntax(self.parseImplementsAttribute())
58+
case ._semantics:
59+
return RawSyntax(self.parseSemanticsAttribute())
5660
default:
5761
break
5862
}
@@ -682,6 +686,43 @@ extension Parser {
682686
}
683687
}
684688

689+
extension Parser {
690+
mutating func parseImplementsAttribute() -> RawAttributeSyntax {
691+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
692+
let (unexpectedBeforeSpiToken, spiToken) = self.expectContextualKeyword("_implements")
693+
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
694+
let label = self.parseImplementsAttributeArguments()
695+
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
696+
return RawAttributeSyntax(
697+
unexpectedBeforeAtSign,
698+
atSignToken: atSign,
699+
unexpectedBeforeSpiToken,
700+
attributeName: spiToken,
701+
unexpectedBeforeLeftParen,
702+
leftParen: leftParen,
703+
argument: RawSyntax(label),
704+
unexpectedBeforeRightParen,
705+
rightParen: rightParen,
706+
tokenList: nil,
707+
arena: self.arena)
708+
}
709+
710+
mutating func parseImplementsAttributeArguments() -> RawImplementsAttributeArgumentsSyntax {
711+
let type = self.parseTypeIdentifier()
712+
let (unexpectedBeforeComma, comma) = self.expect(.comma)
713+
let (name, args) = self.parseDeclNameRef([
714+
.zeroArgCompoundNames,
715+
.operators,
716+
])
717+
return RawImplementsAttributeArgumentsSyntax(
718+
type: type,
719+
unexpectedBeforeComma, comma: comma,
720+
declBaseName: name,
721+
declNameArguments: args,
722+
arena: self.arena)
723+
}
724+
}
725+
685726
extension Parser {
686727
mutating func parseOpaqueReturnTypeOfAttributeArguments() -> RawOpaqueReturnTypeOfAttributeArgumentsSyntax {
687728
let (unexpectedBeforeString, mangledName) = self.expect(.stringLiteral)
@@ -698,6 +739,28 @@ extension Parser {
698739
}
699740
}
700741

742+
extension Parser {
743+
mutating func parseSemanticsAttribute() -> RawAttributeSyntax {
744+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
745+
let (unexpectedBeforeSemanticsToken, semanticsToken) = self.expectContextualKeyword("_semantics")
746+
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
747+
let label = self.parseStringLiteral()
748+
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
749+
return RawAttributeSyntax(
750+
unexpectedBeforeAtSign,
751+
atSignToken: atSign,
752+
unexpectedBeforeSemanticsToken,
753+
attributeName: semanticsToken,
754+
unexpectedBeforeLeftParen,
755+
leftParen: leftParen,
756+
argument: RawSyntax(label),
757+
unexpectedBeforeRightParen,
758+
rightParen: rightParen,
759+
tokenList: nil,
760+
arena: self.arena)
761+
}
762+
}
763+
701764
// MARK: Lookahead
702765

703766
extension Parser.Lookahead {

Sources/SwiftParser/Declarations.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,17 @@ extension Parser {
12481248
attrs = self.parseAttributeList()
12491249
}
12501250

1251+
let unexpectedBeforeIsolated: RawUnexpectedNodesSyntax?
1252+
let isolated: RawTokenSyntax?
1253+
if self.currentToken.isContextualKeyword("isolated") &&
1254+
!self.lookahead().startsParameterName(subject.isClosure) {
1255+
(unexpectedBeforeIsolated, isolated) = self.expectContextualKeyword("isolated")
1256+
} else {
1257+
unexpectedBeforeIsolated = nil
1258+
isolated = nil
1259+
}
1260+
let const = self.consumeIfContextualKeyword("_const")
1261+
12511262
let firstName: RawTokenSyntax?
12521263
let secondName: RawTokenSyntax?
12531264
let unexpectedBeforeColon: RawUnexpectedNodesSyntax?
@@ -1307,6 +1318,9 @@ extension Parser {
13071318
keepGoing = trailingComma != nil
13081319
elements.append(RawFunctionParameterSyntax(
13091320
attributes: attrs,
1321+
unexpectedBeforeIsolated,
1322+
isolated: isolated,
1323+
const: const,
13101324
firstName: firstName,
13111325
secondName: secondName,
13121326
unexpectedBeforeColon,
@@ -1414,7 +1428,14 @@ extension Parser {
14141428
public mutating func parseFunctionSignature() -> RawFunctionSignatureSyntax {
14151429
let input = self.parseParameterClause(for: .functionParameters)
14161430

1417-
let async = self.consumeIfContextualKeyword("async")
1431+
let async: RawTokenSyntax?
1432+
if let asyncTok = self.consumeIfContextualKeyword("async") {
1433+
async = asyncTok
1434+
} else if let reasync = self.consumeIfContextualKeyword("reasync") {
1435+
async = reasync
1436+
} else {
1437+
async = nil
1438+
}
14181439

14191440
var throwsKeyword = self.consume(ifAny: [.throwsKeyword, .rethrowsKeyword])
14201441

Sources/SwiftParser/Expressions.swift

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,11 @@ extension Parser {
317317
}
318318
}
319319

320-
switch self.at(anyIn: AwaitTry.self) {
320+
switch self.at(anyIn: AwaitTryMove.self) {
321321
case (.awaitContextualKeyword, let handle)?:
322322
let awaitTok = self.eat(handle)
323-
let sub = self.parseSequenceExpressionElement(flavor, inVarOrLet: inVarOrLet)
323+
let sub = self.parseSequenceExpressionElement(
324+
flavor, forDirective: forDirective, inVarOrLet: inVarOrLet)
324325
return RawExprSyntax(RawAwaitExprSyntax(
325326
awaitKeyword: awaitTok,
326327
expression: sub,
@@ -330,13 +331,22 @@ extension Parser {
330331
let tryKeyword = self.eat(handle)
331332
let mark = self.consume(ifAny: [.exclamationMark, .postfixQuestionMark])
332333

333-
let expression = self.parseSequenceExpressionElement(flavor, inVarOrLet: inVarOrLet)
334+
let expression = self.parseSequenceExpressionElement(
335+
flavor, forDirective: forDirective, inVarOrLet: inVarOrLet)
334336
return RawExprSyntax(RawTryExprSyntax(
335337
tryKeyword: tryKeyword,
336338
questionOrExclamationMark: mark,
337339
expression: expression,
338340
arena: self.arena
339341
))
342+
case (._moveContextualKeyword, let handle)?:
343+
let moveTok = self.eat(handle)
344+
let sub = self.parseSequenceExpressionElement(
345+
flavor, forDirective: forDirective, inVarOrLet: inVarOrLet)
346+
return RawExprSyntax(RawMoveExprSyntax(
347+
moveKeyword: moveTok,
348+
expression: sub,
349+
arena: self.arena))
340350
case nil:
341351
return self.parseUnaryExpression(flavor, forDirective: forDirective, inVarOrLet: inVarOrLet)
342352
}
@@ -383,7 +393,9 @@ extension Parser {
383393

384394
default:
385395
// If the next token is not an operator, just parse this as expr-postfix.
386-
return self.parsePostfixExpression(flavor, forDirective: forDirective, inVarOrLet: inVarOrLet)
396+
return self.parsePostfixExpression(
397+
flavor, forDirective: forDirective, inVarOrLet: inVarOrLet,
398+
periodHasKeyPathBehavior: false)
387399
}
388400
}
389401

@@ -405,26 +417,21 @@ extension Parser {
405417
public mutating func parsePostfixExpression(
406418
_ flavor: ExprFlavor,
407419
forDirective: Bool,
408-
inVarOrLet: Bool
420+
inVarOrLet: Bool,
421+
periodHasKeyPathBehavior: Bool
409422
) -> RawExprSyntax {
410423
let head = self.parsePrimaryExpression(inVarOrLet: inVarOrLet)
411424
guard !head.is(RawMissingExprSyntax.self) else {
412425
return head
413426
}
414-
return self.parsePostfixExpressionSuffix(head, flavor, forDirective: forDirective)
427+
return self.parsePostfixExpressionSuffix(
428+
head, flavor, forDirective: forDirective,
429+
periodHasKeyPathBehavior: periodHasKeyPathBehavior)
415430
}
416431

417432
@_spi(RawSyntax)
418433
public mutating func parseDottedExpressionSuffix(_ start: RawExprSyntax?) -> RawExprSyntax {
419434
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-
428435
let period = self.consumeAnyToken(remapping: .period)
429436
// Handle "x.42" - a tuple index.
430437
if let name = self.consume(if: .integerLiteral) {
@@ -478,7 +485,9 @@ extension Parser {
478485
// TODO: diagnose and skip.
479486
return nil
480487
}
481-
let result = parser.parsePostfixExpressionSuffix(head, flavor, forDirective: forDirective)
488+
let result = parser.parsePostfixExpressionSuffix(
489+
head, flavor, forDirective: forDirective,
490+
periodHasKeyPathBehavior: false)
482491

483492
// TODO: diagnose and skip the remaining token in the current clause.
484493
return result
@@ -513,7 +522,8 @@ extension Parser {
513522
public mutating func parsePostfixExpressionSuffix(
514523
_ start: RawExprSyntax,
515524
_ flavor: ExprFlavor,
516-
forDirective: Bool
525+
forDirective: Bool,
526+
periodHasKeyPathBehavior: Bool
517527
) -> RawExprSyntax {
518528
// Handle suffix expressions.
519529
var leadingExpr = start
@@ -525,6 +535,13 @@ extension Parser {
525535

526536
// Check for a .foo suffix.
527537
if self.at(any: [.period, .prefixPeriod]) {
538+
// A key path is special, because it allows .[, unlike anywhere else. The
539+
// period itself should be left in the token stream. (.? and .! end up
540+
// being operators, and so aren't handled here.)
541+
if periodHasKeyPathBehavior && self.peek().tokenKind == .leftSquareBracket {
542+
break
543+
}
544+
528545
leadingExpr = self.parseDottedExpressionSuffix(leadingExpr)
529546
continue
530547
}
@@ -700,7 +717,9 @@ extension Parser {
700717
// the token is a operator starts with '.', or the following token is '['.
701718
let root: RawExprSyntax?
702719
if !self.currentToken.starts(with: ".") {
703-
root = self.parsePostfixExpression(.basic, forDirective: forDirective, inVarOrLet: inVarOrLet)
720+
root = self.parsePostfixExpression(
721+
.basic, forDirective: forDirective, inVarOrLet: inVarOrLet,
722+
periodHasKeyPathBehavior: true)
704723
} else {
705724
root = nil
706725
}
@@ -714,12 +733,16 @@ extension Parser {
714733
dot = self.consumeAnyToken()
715734
}
716735
let base = RawExprSyntax(RawKeyPathBaseExprSyntax(period: dot, arena: self.arena))
717-
expression = self.parsePostfixExpressionSuffix(base, .basic, forDirective: forDirective)
736+
expression = self.parsePostfixExpressionSuffix(
737+
base, .basic, forDirective: forDirective,
738+
periodHasKeyPathBehavior: false)
718739
} else if self.at(any: [.period, .prefixPeriod]) {
719740
// Inside a keypath's path, the period always behaves normally: the key path
720741
// behavior is only the separation between type and path.
721742
let base = self.parseDottedExpressionSuffix(nil)
722-
expression = self.parsePostfixExpressionSuffix(base, .basic, forDirective: forDirective)
743+
expression = self.parsePostfixExpressionSuffix(
744+
base, .basic, forDirective: forDirective,
745+
periodHasKeyPathBehavior: false)
723746
} else {
724747
expression = RawExprSyntax(RawMissingExprSyntax(arena: self.arena))
725748
}
@@ -870,7 +893,7 @@ extension Parser {
870893
// 'any' followed by another identifier is an existential type.
871894
if self.atContextualKeyword("any"),
872895
self.peek().tokenKind == .identifier,
873-
self.peek().isAtStartOfLine
896+
!self.peek().isAtStartOfLine
874897
{
875898
let ty = self.parseType()
876899
return RawExprSyntax(RawTypeExprSyntax(type: ty, arena: self.arena))

Sources/SwiftParser/Modifiers.swift

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ extension Parser {
2424
(.internalKeyword, _)?,
2525
(.publicKeyword, _)?:
2626
elements.append(parseAccessLevelModifier())
27+
case (.open, _)?:
28+
elements.append(parseOpenAccessLevelModifier())
2729
case (.staticKeyword, let handle)?:
2830
let staticKeyword = self.eat(handle)
2931
elements.append(RawDeclModifierSyntax(
@@ -64,7 +66,6 @@ extension Parser {
6466
(.nonmutating, _)?,
6567
(.convenience, _)?,
6668
(.override, _)?,
67-
(.open, _)?,
6869
(.weak, _)?,
6970
(.indirect, _)?,
7071
(.isolated, _)?,
@@ -130,43 +131,54 @@ extension Parser {
130131
)
131132
}
132133

134+
mutating func parseOpenAccessLevelModifier() -> RawDeclModifierSyntax {
135+
let (unexpectedBeforeName, name) = self.expectContextualKeyword("open")
136+
let details = self.parseAccessModifierDetails()
137+
return RawDeclModifierSyntax(
138+
unexpectedBeforeName,
139+
name: name,
140+
detail: details,
141+
arena: self.arena)
142+
}
143+
133144
mutating func parseAccessLevelModifier() -> RawDeclModifierSyntax {
134145
let (unexpectedBeforeName, name) = expectAny(
135146
[.privateKeyword, .fileprivateKeyword, .internalKeyword, .publicKeyword],
136147
default: .internalKeyword
137148
)
138-
let details: RawDeclModifierDetailSyntax?
139-
if let leftParen = consume(if: .leftParen) {
140-
let unexpectedBeforeDetail: RawUnexpectedNodesSyntax?
141-
let detail: RawTokenSyntax
142-
if let setHandle = canRecoverToContextualKeyword("set", precedence: .weakBracketClose) {
143-
(unexpectedBeforeDetail, detail) = eat(setHandle)
144-
} else {
145-
unexpectedBeforeDetail = nil
146-
detail = RawTokenSyntax(
147-
missing: .contextualKeyword,
148-
text: "set",
149-
arena: arena
150-
)
151-
}
152-
let (unexpectedBeforeRightParen, rightParen) = expect(.rightParen)
153-
154-
details = RawDeclModifierDetailSyntax(
155-
leftParen: leftParen,
156-
unexpectedBeforeDetail,
157-
detail: detail,
158-
unexpectedBeforeRightParen,
159-
rightParen: rightParen,
160-
arena: arena
161-
)
162-
} else {
163-
details = nil
164-
}
149+
let details = self.parseAccessModifierDetails()
165150
return RawDeclModifierSyntax(
166151
unexpectedBeforeName,
167152
name: name,
168153
detail: details,
169-
arena: arena
170-
)
154+
arena: self.arena)
155+
}
156+
157+
mutating func parseAccessModifierDetails() -> RawDeclModifierDetailSyntax? {
158+
guard let leftParen = consume(if: .leftParen) else {
159+
return nil
160+
}
161+
162+
let unexpectedBeforeDetail: RawUnexpectedNodesSyntax?
163+
let detail: RawTokenSyntax
164+
if let setHandle = canRecoverToContextualKeyword("set", precedence: .weakBracketClose) {
165+
(unexpectedBeforeDetail, detail) = eat(setHandle)
166+
} else {
167+
unexpectedBeforeDetail = nil
168+
detail = RawTokenSyntax(
169+
missing: .contextualKeyword,
170+
text: "set",
171+
arena: arena
172+
)
173+
}
174+
let (unexpectedBeforeRightParen, rightParen) = expect(.rightParen)
175+
176+
return RawDeclModifierDetailSyntax(
177+
leftParen: leftParen,
178+
unexpectedBeforeDetail,
179+
detail: detail,
180+
unexpectedBeforeRightParen,
181+
rightParen: rightParen,
182+
arena: self.arena)
171183
}
172184
}

0 commit comments

Comments
 (0)