Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public let DECL_NODES: [Node] = [
traits: [
"WithOptionalCodeBlock",
"WithAttributes",
"WithModifiers",
],
children: [
Child(
Expand All @@ -97,10 +98,10 @@ public let DECL_NODES: [Node] = [
nameForDiagnostics: "attributes"
),
Child(
name: "modifier",
kind: .node(kind: .declModifier),
name: "modifiers",
kind: .collection(kind: .declModifierList, collectionElementName: "Modifier", defaultsToEmpty: true),
nameForDiagnostics: "modifiers",
isOptional: true
documentation: "Modifiers like `mutating` or `yielding` that affect the accessor declaration."
),
Child(
name: "accessorSpecifier",
Expand Down Expand Up @@ -495,6 +496,7 @@ public let DECL_NODES: [Node] = [
.keyword(.unowned),
.keyword(.weak),
.keyword(.sending),
.keyword(.yielding),
])
),
Child(
Expand Down
3 changes: 3 additions & 0 deletions CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ public enum Keyword: CaseIterable {
case willSet
case wrt
case yield
case yielding

public var spec: KeywordSpec {
switch self {
Expand Down Expand Up @@ -692,6 +693,8 @@ public enum Keyword: CaseIterable {
return KeywordSpec("wrt")
case .yield:
return KeywordSpec("yield")
case .yielding:
return KeywordSpec("yielding", experimentalFeature: .coroutineAccessors)
}
}
}
2 changes: 1 addition & 1 deletion Sources/SwiftParser/CollectionNodes+Parsable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ extension AccessorDeclListSyntax: SyntaxParseable {
} makeMissing: { remainingTokens, arena in
return RawAccessorDeclSyntax(
attributes: RawAttributeListSyntax(elements: [], arena: arena),
modifier: nil,
modifiers: RawDeclModifierListSyntax(elements: [], arena: arena),
accessorSpecifier: RawTokenSyntax(missing: .keyword, text: "get", arena: arena),
parameters: nil,
effectSpecifiers: nil,
Expand Down
47 changes: 27 additions & 20 deletions Sources/SwiftParser/Declarations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1658,44 +1658,51 @@ extension Parser {

struct AccessorIntroducer {
var attributes: RawAttributeListSyntax
var modifier: RawDeclModifierSyntax?
var modifiers: RawDeclModifierListSyntax
var kind: AccessorDeclSyntax.AccessorSpecifierOptions
var unexpectedBeforeToken: RawUnexpectedNodesSyntax?
var token: RawTokenSyntax
}

mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax {
var elements = [RawDeclModifierSyntax]()

for _ in 0..<count {
let (unexpectedBeforeName, name) = self.expect(anyIn: AccessorModifier.self, default: .mutating)
let modifier = RawDeclModifierSyntax(
unexpectedBeforeName,
name: name,
detail: nil,
arena: self.arena
)
elements.append(modifier)
}

return RawDeclModifierListSyntax(
elements: elements,
arena: self.arena
)
}

mutating func parseAccessorIntroducer(
forcedKind: (AccessorDeclSyntax.AccessorSpecifierOptions, TokenConsumptionHandle)? = nil
) -> AccessorIntroducer? {
// Check there is an identifier before consuming
// Look ahead to verify attributes/modifiers/kind
var look = self.lookahead()
let _ = look.consumeAttributeList()
let hasModifier = look.consume(ifAnyIn: AccessorModifier.self) != nil
let modifierCount = look.consume(anySequence: AccessorModifier.self)
guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else {
return nil
}

let attrs = self.parseAttributeList()

// Parse the contextual keywords for 'mutating' and 'nonmutating' before
// get and set.
let modifier: RawDeclModifierSyntax?
if hasModifier {
let (unexpectedBeforeName, name) = self.expect(anyIn: AccessorModifier.self, default: .mutating)
modifier = RawDeclModifierSyntax(
unexpectedBeforeName,
name: name,
detail: nil,
arena: self.arena
)
} else {
modifier = nil
}
let modifiers = self.parseAccessorModifierList(count: modifierCount)

let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec)

return AccessorIntroducer(
attributes: attrs,
modifier: modifier,
modifiers: modifiers,
kind: kind,
unexpectedBeforeToken: unexpectedBeforeIntroducer,
token: introducer
Expand Down Expand Up @@ -1738,7 +1745,7 @@ extension Parser {
let body = self.parseOptionalCodeBlock()
return RawAccessorDeclSyntax(
attributes: introducer.attributes,
modifier: introducer.modifier,
modifiers: introducer.modifiers,
introducer.unexpectedBeforeToken,
accessorSpecifier: introducer.token,
parameters: parameters,
Expand Down
12 changes: 12 additions & 0 deletions Sources/SwiftParser/Lookahead.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ extension Parser.Lookahead {
}
}

// MARK: Skipping a sequence of tokens

extension Parser.Lookahead {
mutating func consume<SpecSet: TokenSpecSet>(anySequence: SpecSet.Type) -> Int {
var count = 0
while consume(ifAnyIn: SpecSet.self) != nil {
count += 1
}
return count
}
}

// MARK: Skipping Tokens

extension Parser.Lookahead {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftParser/TokenPrecedence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ enum TokenPrecedence: Comparable {
.dependsOn, .scoped, .sending,
// Accessors
.get, .set, .didSet, .willSet, .unsafeAddress, .addressWithOwner, .addressWithNativeOwner, .unsafeMutableAddress,
.mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, .mutate,
.mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, .mutate, .yielding,
// Misc
.import, .using:
self = .declKeyword
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftParser/TokenSpecSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ enum AccessorModifier: TokenSpecSet {
case borrowing
case mutating
case nonmutating
case yielding

init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) {
switch PrepareForKeywordMatch(lexeme) {
Expand All @@ -74,6 +75,7 @@ enum AccessorModifier: TokenSpecSet {
case TokenSpec(.borrowing): self = .borrowing
case TokenSpec(.mutating): self = .mutating
case TokenSpec(.nonmutating): self = .nonmutating
case TokenSpec(.yielding): self = .yielding
default: return nil
}
}
Expand All @@ -85,6 +87,7 @@ enum AccessorModifier: TokenSpecSet {
case .borrowing: return .keyword(.borrowing)
case .mutating: return .keyword(.mutating)
case .nonmutating: return .keyword(.nonmutating)
case .yielding: return .keyword(.yielding)
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions Sources/SwiftParser/generated/Parser+TokenSpecSet.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Sources/SwiftSyntax/generated/Keyword.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Sources/SwiftSyntax/generated/SyntaxCollections.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Sources/SwiftSyntax/generated/SyntaxTraits.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading