Skip to content

Commit 5300fa7

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

File tree

5 files changed

+53
-11
lines changed

5 files changed

+53
-11
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(anyIn: OperatorModifiers.self, default: .prefix, overrideRecoveryPrecedence: .declKeyword)
16991699

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

Sources/SwiftParser/Parser.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,12 @@ extension Parser {
402402
@inline(__always)
403403
mutating func expect<SpecSet: TokenSpecSet>(
404404
anyIn specSet: SpecSet.Type,
405-
default defaultKind: SpecSet
405+
default defaultKind: SpecSet,
406+
overrideRecoveryPrecedence: TokenPrecedence? = nil
406407
) -> (unexpected: RawUnexpectedNodesSyntax?, token: RawTokenSyntax) {
407408
return expectImpl(
408409
consume: { $0.consume(ifAnyIn: specSet) },
409-
canRecoverTo: { $0.canRecoverTo(anyIn: specSet)?.1 },
410+
canRecoverTo: { $0.canRecoverTo(anyIn: specSet, overrideRecoveryPrecedence: overrideRecoveryPrecedence)?.1 },
410411
makeMissing: { $0.missingToken(defaultKind.spec) }
411412
)
412413
}

Sources/SwiftParser/TokenPrecedence.swift

Lines changed: 13 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,21 @@ public enum TokenPrecedence: Comparable {
210213
// Return-like statements
211214
.break, .continue, .fallthrough, .return, .throw, .yield:
212215
self = .stmtKeyword
216+
// MARK: Decl Modifiers
217+
case // Operator Modifiers
218+
.infix, .prefix, .postfix,
219+
// Access modifiers
220+
.fileprivate, .internal, .private, .public, .static:
221+
self = .declModifier
213222
// MARK: Decl keywords
214223
case // Types
215224
.associatedtype, .class, .enum, .extension, .protocol, .struct, .typealias,
216-
// Access modifiers
217-
.fileprivate, .internal, .private, .public, .static,
218225
// Functions
219226
.deinit, .func, .`init`, .subscript,
220227
// Variables
221228
.let, .var,
222229
// Operator stuff
223-
.operator, .precedencegroup, .infix, .prefix, .postfix,
230+
.operator, .precedencegroup,
224231
// Misc
225232
.import:
226233
self = .declKeyword

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,29 @@ enum Operator: TokenSpecSet {
321321
}
322322
}
323323

324+
enum OperatorModifiers: TokenSpecSet {
325+
case `prefix`
326+
case `infix`
327+
case `postfix`
328+
329+
init?(lexeme: Lexer.Lexeme) {
330+
switch PrepareForKeywordMatch(lexeme) {
331+
case TokenSpec(.prefix): self = .prefix
332+
case TokenSpec(.infix): self = .infix
333+
case TokenSpec(.postfix): self = .postfix
334+
default: return nil
335+
}
336+
}
337+
338+
var spec: TokenSpec {
339+
switch self {
340+
case .prefix: return .keyword(.prefix)
341+
case .postfix: return .keyword(.postfix)
342+
case .infix: return .keyword(.infix)
343+
}
344+
}
345+
}
346+
324347
/// Tokens that can be used in operator declarations
325348
enum OperatorLike: TokenSpecSet {
326349
case `operator`(Operator)

Tests/SwiftParserTest/translated/OperatorDeclTests.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ final class OperatorDeclTests: XCTestCase {
479479
]
480480
)
481481
}
482-
482+
483483
func testOperatorDecl124() {
484484
assertParse(
485485
"""
@@ -491,7 +491,7 @@ final class OperatorDeclTests: XCTestCase {
491491
]
492492
)
493493
}
494-
494+
495495
func testOperatorDecl125() {
496496
assertParse(
497497
"""
@@ -503,6 +503,17 @@ final class OperatorDeclTests: XCTestCase {
503503
)
504504
}
505505

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+
}
516+
506517
func testIdentifierAsOperatorName() {
507518
assertParse(
508519
"postfix operator 1️⃣aa",

0 commit comments

Comments
 (0)