Skip to content

Commit 3c8d46e

Browse files
committed
Add a declModifier token precedence to represent the declaration modifiers
1 parent 8aa865d commit 3c8d46e

File tree

5 files changed

+44
-19
lines changed

5 files changed

+44
-19
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1695,7 +1695,7 @@ extension Parser {
16951695
@_spi(RawSyntax)
16961696
public mutating func parseOperatorDeclaration() -> RawOperatorDeclSyntax {
16971697

1698-
let (unexpectedBeforeModifier, modifier) = self.expect(.keyword(.infix), .keyword(.postfix), .keyword(.prefix), default: .keyword(.prefix))
1698+
let (unexpectedBeforeModifier, modifier) = self.expect(.keyword(.infix), .keyword(.postfix), .keyword(.prefix), default: .keyword(.prefix), overrideRecoveryPrecedence: .declKeyword)
16991699

17001700
let (unexpectedBeforeOperator, operatorKeyword) = self.expect(.keyword(.operator))
17011701

Sources/SwiftParser/Parser.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,11 +349,12 @@ extension Parser {
349349
/// a missing token of the requested kind.
350350
@inline(__always)
351351
mutating func expect(
352-
_ spec: TokenSpec
352+
_ spec: TokenSpec,
353+
overrideRecoveryPrecedence: TokenPrecedence? = nil
353354
) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) {
354355
return expectImpl(
355356
consume: { $0.consume(if: spec) },
356-
canRecoverTo: { $0.canRecoverTo(spec) },
357+
canRecoverTo: { $0.canRecoverTo(spec, overrideRecoveryPrecedence: overrideRecoveryPrecedence) },
357358
makeMissing: { $0.missingToken(spec) }
358359
)
359360
}
@@ -369,11 +370,12 @@ extension Parser {
369370
mutating func expect(
370371
_ spec1: TokenSpec,
371372
_ spec2: TokenSpec,
372-
default defaultKind: TokenSpec
373+
default defaultKind: TokenSpec,
374+
overrideRecoveryPrecedence: TokenPrecedence? = nil
373375
) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) {
374376
return expectImpl(
375377
consume: { $0.consume(if: spec1, spec2) },
376-
canRecoverTo: { $0.canRecoverTo(spec1, spec2) },
378+
canRecoverTo: { $0.canRecoverTo(spec1, spec2, overrideRecoveryPrecedence: overrideRecoveryPrecedence) },
377379
makeMissing: { $0.missingToken(defaultKind) }
378380
)
379381
}
@@ -390,11 +392,12 @@ extension Parser {
390392
_ spec1: TokenSpec,
391393
_ spec2: TokenSpec,
392394
_ spec3: TokenSpec,
393-
default defaultKind: TokenSpec
395+
default defaultKind: TokenSpec,
396+
overrideRecoveryPrecedence: TokenPrecedence? = nil
394397
) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) {
395398
return expectImpl(
396399
consume: { $0.consume(if: spec1, spec2, spec3) },
397-
canRecoverTo: { $0.canRecoverTo(spec1, spec2, spec3) },
400+
canRecoverTo: { $0.canRecoverTo(spec1, spec2, spec3, overrideRecoveryPrecedence: overrideRecoveryPrecedence) },
398401
makeMissing: { $0.missingToken(defaultKind) }
399402
)
400403
}

Sources/SwiftParser/Recovery.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,19 @@ public struct RecoveryConsumptionHandle {
4242
extension Parser.Lookahead {
4343
/// See `canRecoverTo` that takes 3 specs.
4444
mutating func canRecoverTo(
45-
_ spec: TokenSpec
45+
_ spec: TokenSpec,
46+
overrideRecoveryPrecedence: TokenPrecedence? = nil
4647
) -> RecoveryConsumptionHandle? {
47-
return canRecoverTo(spec, spec, spec)
48+
return canRecoverTo(spec, spec, spec, overrideRecoveryPrecedence: overrideRecoveryPrecedence)
4849
}
4950

5051
/// See `canRecoverTo` that takes 3 specs.
5152
mutating func canRecoverTo(
5253
_ spec1: TokenSpec,
53-
_ spec2: TokenSpec
54+
_ spec2: TokenSpec,
55+
overrideRecoveryPrecedence: TokenPrecedence? = nil
5456
) -> RecoveryConsumptionHandle? {
55-
return canRecoverTo(spec1, spec2, spec1)
57+
return canRecoverTo(spec1, spec2, spec1, overrideRecoveryPrecedence: overrideRecoveryPrecedence)
5658
}
5759

5860
/// Tries eating tokens until it finds a token that matches `spec1`, `spec2` or `spec3`
@@ -65,11 +67,12 @@ extension Parser.Lookahead {
6567
mutating func canRecoverTo(
6668
_ spec1: TokenSpec,
6769
_ spec2: TokenSpec,
68-
_ spec3: TokenSpec
70+
_ spec3: TokenSpec,
71+
overrideRecoveryPrecedence: TokenPrecedence? = nil
6972
) -> RecoveryConsumptionHandle? {
7073
let initialTokensConsumed = self.tokensConsumed
7174

72-
let recoveryPrecedence = min(spec1.recoveryPrecedence, spec2.recoveryPrecedence, spec3.recoveryPrecedence)
75+
let recoveryPrecedence = overrideRecoveryPrecedence ?? min(spec1.recoveryPrecedence, spec2.recoveryPrecedence, spec3.recoveryPrecedence)
7376
let shouldSkipOverNewlines = recoveryPrecedence.shouldSkipOverNewlines && spec1.allowAtStartOfLine && spec2.allowAtStartOfLine && spec3.allowAtStartOfLine
7477

7578
while !self.at(.eof) {

Sources/SwiftParser/TokenPrecedence.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public enum TokenPrecedence: Comparable {
3838
case strongPunctuator
3939
/// The closing delimiter of `strongBracketed`
4040
case closingBrace
41+
case declModifier
4142
/// Tokens that start a new declaration
4243
case declKeyword
4344
case openingPoundIf
@@ -81,12 +82,14 @@ public enum TokenPrecedence: Comparable {
8182
return 8
8283
case .closingBrace:
8384
return 9
84-
case .declKeyword:
85+
case .declModifier:
8586
return 10
86-
case .openingPoundIf:
87+
case .declKeyword:
8788
return 11
88-
case .closingPoundIf:
89+
case .openingPoundIf:
8990
return 12
91+
case .closingPoundIf:
92+
return 13
9093
}
9194
}
9295

@@ -210,17 +213,22 @@ public enum TokenPrecedence: Comparable {
210213
// Return-like statements
211214
.break, .continue, .fallthrough, .return, .throw, .yield:
212215
self = .stmtKeyword
216+
// MARK: Decl Modifiers
217+
case
218+
// Operator Modifiers
219+
.infix, .prefix, .postfix,
220+
// Access modifiers
221+
.fileprivate, .internal, .private, .public, .static:
222+
self = .declModifier
213223
// MARK: Decl keywords
214224
case // Types
215225
.associatedtype, .class, .enum, .extension, .protocol, .struct, .typealias,
216-
// Access modifiers
217-
.fileprivate, .internal, .private, .public, .static,
218226
// Functions
219227
.deinit, .func, .`init`, .subscript,
220228
// Variables
221229
.let, .var,
222230
// Operator stuff
223-
.operator, .precedencegroup, .infix, .prefix, .postfix,
231+
.operator, .precedencegroup,
224232
// Misc
225233
.import:
226234
self = .declKeyword

Tests/SwiftParserTest/translated/OperatorDeclTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,17 @@ final class OperatorDeclTests: XCTestCase {
502502
]
503503
)
504504
}
505+
506+
func testOperatorDecl126() {
507+
assertParse(
508+
"""
509+
1️⃣private(set) infix operator ~~~
510+
""",
511+
diagnostics: [
512+
DiagnosticSpec(message: "unexpected code 'private(set)' before operator declaration")
513+
]
514+
)
515+
}
505516

506517
func testIdentifierAsOperatorName() {
507518
assertParse(

0 commit comments

Comments
 (0)