From dd25371ed93e924aaea87b5b14177e6a6add5885 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 Sep 2023 19:22:44 +0100 Subject: [PATCH 1/5] NFC: Introduce `peek(isAtAnyIn:)` --- Sources/SwiftParser/Attributes.swift | 2 +- Sources/SwiftParser/Statements.swift | 8 +++----- Sources/SwiftParser/TokenConsumer.swift | 11 +++++++++++ Sources/SwiftParser/Types.swift | 6 ++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index 1f2267b9360..096dd0c2b2b 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -223,7 +223,7 @@ extension Parser { ) } - switch DeclarationAttributeWithSpecialSyntax(lexeme: self.peek()) { + switch peek(isAtAnyIn: DeclarationAttributeWithSpecialSyntax.self) { case .available, ._spi_available: return parseAttribute(argumentMode: .required) { parser in return .availability(parser.parseAvailabilityArgumentSpecList()) diff --git a/Sources/SwiftParser/Statements.swift b/Sources/SwiftParser/Statements.swift index 53559c6d8f7..1e618bf4046 100644 --- a/Sources/SwiftParser/Statements.swift +++ b/Sources/SwiftParser/Statements.swift @@ -943,15 +943,13 @@ extension Parser.Lookahead { return false } - let next = peek() - // If 'then' is followed by a binary or postfix operator, prefer to parse as // an expr. - if BinaryOperatorLike(lexeme: next) != nil || PostfixOperatorLike(lexeme: next) != nil { + if peek(isAtAnyIn: BinaryOperatorLike.self) != nil || peek(isAtAnyIn: PostfixOperatorLike.self) != nil { return false } - switch PrepareForKeywordMatch(next) { + switch PrepareForKeywordMatch(peek()) { case TokenSpec(.is), TokenSpec(.as): // Treat 'is' and 'as' like the binary operator case, and parse as an // expr. @@ -965,7 +963,7 @@ extension Parser.Lookahead { // These are handled based on whether there is trivia between the 'then' // and the token. If so, it's a 'then' statement. Otherwise it should // be treated as an expression, e.g `then(...)`, `then[...]`, `then.foo`. - return !self.currentToken.trailingTriviaText.isEmpty || !next.leadingTriviaText.isEmpty + return !self.currentToken.trailingTriviaText.isEmpty || !peek().leadingTriviaText.isEmpty default: break } diff --git a/Sources/SwiftParser/TokenConsumer.swift b/Sources/SwiftParser/TokenConsumer.swift index d319d064445..9462d2a2360 100644 --- a/Sources/SwiftParser/TokenConsumer.swift +++ b/Sources/SwiftParser/TokenConsumer.swift @@ -148,6 +148,17 @@ extension TokenConsumer { return nil } + /// Checks whether the parser's next token is any token in `SpecSet`. + /// If this is the case, return the corresponding `SpecSet` case. + @inline(__always) + func peek(isAtAnyIn specSet: SpecSet.Type) -> SpecSet? { + guard let matchedKind = SpecSet(lexeme: self.peek()) else { + return nil + } + precondition(matchedKind.spec ~= self.peek()) + return matchedKind + } + /// Whether the current token’s text starts with the given prefix. @inline(__always) mutating func at(prefix: SyntaxText) -> Bool { diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 36bfb2c7a9e..45e77a76709 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -798,7 +798,7 @@ extension Parser.Lookahead { return true } - if EffectSpecifier(lexeme: self.peek()) != nil { + if peek(isAtAnyIn: EffectSpecifier.self) != nil { var backtrack = self.lookahead() backtrack.consumeAnyToken() backtrack.consumeAnyToken() @@ -909,9 +909,7 @@ extension Parser { } mutating func parseTypeAttribute() -> RawAttributeListSyntax.Element { - let typeAttr = TypeAttribute(lexeme: self.peek()) - - switch typeAttr { + switch peek(isAtAnyIn: TypeAttribute.self) { case ._local, ._noMetadata, .async, .escaping, .noDerivative, .noescape, .Sendable, .unchecked, .autoclosure: // Known type attribute that doesn't take any arguments return parseAttributeWithoutArguments() From 7ef269fd73d4d779a242a32ea67e8137ff6c71ab Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 Sep 2023 19:22:45 +0100 Subject: [PATCH 2/5] [BasicFormat] Handle some additional cases for `self` + `Self` --- Sources/SwiftBasicFormat/BasicFormat.swift | 6 +++- .../BasicFormatTests.swift | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftBasicFormat/BasicFormat.swift b/Sources/SwiftBasicFormat/BasicFormat.swift index a433d133b52..3b277e42d5b 100644 --- a/Sources/SwiftBasicFormat/BasicFormat.swift +++ b/Sources/SwiftBasicFormat/BasicFormat.swift @@ -307,7 +307,11 @@ open class BasicFormat: SyntaxRewriter { (.keyword(.`init`), .leftAngle), // init() (.keyword(.`init`), .leftParen), // init() (.keyword(.self), .period), // self.someProperty - (.keyword(.Self), .period), // self.someProperty + (.keyword(.self), .leftParen), // self() + (.keyword(.self), .leftSquare), // self[] + (.keyword(.Self), .period), // Self.someProperty + (.keyword(.Self), .leftParen), // Self() + (.keyword(.Self), .leftSquare), // Self[] (.keyword(.set), .leftParen), // var mVar: Int { set(value) {} } (.keyword(.subscript), .leftParen), // subscript(x: Int) (.keyword(.super), .period), // super.someProperty diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 744cce1aa62..5a11a387663 100644 --- a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift +++ b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift @@ -190,6 +190,34 @@ final class BasicFormatTest: XCTestCase { ) } + func testSelfCall1() { + assertFormatted( + source: "self(0)", + expected: "self(0)" + ) + } + + func testSelfCall2() { + assertFormatted( + source: "Self(0)", + expected: "Self(0)" + ) + } + + func testSelfSubscript1() { + assertFormatted( + source: "self[0]", + expected: "self[0]" + ) + } + + func testSelfSubscript2() { + assertFormatted( + source: "Self[0]", + expected: "Self[0]" + ) + } + func testCustomIndentationInBlockThatDoesntHaveNewline() { assertFormatted( source: """ From a99853b32c97d5ef9d8134fbff4adc2eaee059d1 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 Sep 2023 19:22:46 +0100 Subject: [PATCH 3/5] Teach TokenSpecSet about experimental features Pass down the current set of experimental features to TokenSpecSets, and have generated TokenSpecSets automatically account for experimental features by returning `nil` if a given feature isn't active. --- .../SyntaxSupport/ExperimentalFeatures.swift | 33 +++++++++ .../Sources/SyntaxSupport/KeywordSpec.swift | 24 +++--- .../Sources/SyntaxSupport/Node.swift | 18 +++-- .../Sources/SyntaxSupport/StmtNodes.swift | 2 +- .../Sources/SyntaxSupport/TokenSpec.swift | 20 +++-- .../GenerateSwiftSyntax.swift | 1 + .../ExperimentalFeaturesFile.swift | 43 +++++++++++ .../swiftparser/ParserTokenSpecSetFile.swift | 22 ++++-- Sources/SwiftParser/Attributes.swift | 4 +- Sources/SwiftParser/Availability.swift | 2 +- Sources/SwiftParser/Declarations.swift | 4 +- Sources/SwiftParser/Directives.swift | 2 +- Sources/SwiftParser/Expressions.swift | 2 +- Sources/SwiftParser/Lookahead.swift | 2 +- Sources/SwiftParser/Modifiers.swift | 2 +- Sources/SwiftParser/Names.swift | 4 +- Sources/SwiftParser/Patterns.swift | 4 +- Sources/SwiftParser/Specifiers.swift | 42 +++++------ Sources/SwiftParser/Statements.swift | 2 +- Sources/SwiftParser/TokenConsumer.swift | 4 +- Sources/SwiftParser/TokenSpecSet.swift | 73 ++++++++++--------- Sources/SwiftParser/Types.swift | 2 +- 22 files changed, 209 insertions(+), 103 deletions(-) create mode 100644 CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift create mode 100644 CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ExperimentalFeaturesFile.swift diff --git a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift new file mode 100644 index 00000000000..2ea4c215ef0 --- /dev/null +++ b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +public enum ExperimentalFeature: String, CaseIterable { + case referenceBindings + case thenStatements + + /// The name of the feature, which is used in the doc comment. + public var featureName: String { + switch self { + case .referenceBindings: + return "reference bindings" + case .thenStatements: + return "'then' statements" + } + } + + /// The token that represents the experimental feature case name. + public var token: TokenSyntax { + .identifier(rawValue) + } +} diff --git a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift index 4e14169dc7f..5742d47458b 100644 --- a/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift @@ -16,14 +16,18 @@ public struct KeywordSpec { /// The name of the keyword. public let name: String + /// The experimental feature the keyword is part of, or `nil` if this isn't + /// for an experimental feature. + public let experimentalFeature: ExperimentalFeature? + + /// Indicates if the token kind is switched from being an identifier to a keyword in the lexer. + public let isLexerClassified: Bool + /// Indicates if the keyword is part of an experimental language feature. /// /// If `true`, this keyword is for an experimental language feature, and any public /// API generated should be marked as SPI - public let isExperimental: Bool - - /// Indicates if the token kind is switched from being an identifier to a keyword in the lexer. - public let isLexerClassified: Bool + public var isExperimental: Bool { experimentalFeature != nil } /// The name of this keyword that's suitable to be used for variable or enum case names. public var varOrCaseName: TokenSyntax { @@ -46,15 +50,15 @@ public struct KeywordSpec { /// /// - Parameters: /// - name: A name of the keyword. - /// - isExperimental: Indicates if the keyword is part of an experimental language feature. + /// - experimentalFeature: The experimental feature the keyword is part of, or `nil` if this isn't for an experimental feature. /// - isLexerClassified: Indicates if the token kind is switched from being an identifier to a keyword in the lexer. init( _ name: String, - isExperimental: Bool = false, + experimentalFeature: ExperimentalFeature? = nil, isLexerClassified: Bool = false ) { self.name = name - self.isExperimental = isExperimental + self.experimentalFeature = experimentalFeature self.isLexerClassified = isLexerClassified } } @@ -692,11 +696,11 @@ public enum Keyword: CaseIterable { case .yield: return KeywordSpec("yield") case ._borrowing: - return KeywordSpec("_borrowing", isExperimental: true) + return KeywordSpec("_borrowing", experimentalFeature: .referenceBindings) case ._consuming: - return KeywordSpec("_consuming", isExperimental: true) + return KeywordSpec("_consuming", experimentalFeature: .referenceBindings) case ._mutating: - return KeywordSpec("_mutating", isExperimental: true) + return KeywordSpec("_mutating", experimentalFeature: .referenceBindings) } } } diff --git a/CodeGeneration/Sources/SyntaxSupport/Node.swift b/CodeGeneration/Sources/SyntaxSupport/Node.swift index 36bd7830db6..4ccda5a0d85 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Node.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Node.swift @@ -40,9 +40,9 @@ public class Node { /// The kind of node’s supertype. This kind must have `isBase == true` public let base: SyntaxNodeKind - /// If `true`, this is for an experimental language feature, and any public - /// API generated should be SPI. - public let isExperimental: Bool + /// The experimental feature the node is part of, or `nil` if this isn't + /// for an experimental feature. + public let experimentalFeature: ExperimentalFeature? /// When the node name is printed for diagnostics, this name is used. /// If `nil`, `nameForDiagnostics` will print the parent node’s name. @@ -57,6 +57,10 @@ public class Node { /// function that should be invoked to create this node. public let parserFunction: TokenSyntax? + /// If `true`, this is for an experimental language feature, and any public + /// API generated should be SPI. + public var isExperimental: Bool { experimentalFeature != nil } + /// A name for this node that is suitable to be used as a variables or enum /// case's name. public var varOrCaseName: TokenSyntax { @@ -107,7 +111,7 @@ public class Node { init( kind: SyntaxNodeKind, base: SyntaxNodeKind, - isExperimental: Bool = false, + experimentalFeature: ExperimentalFeature? = nil, nameForDiagnostics: String?, documentation: String? = nil, parserFunction: TokenSyntax? = nil, @@ -119,7 +123,7 @@ public class Node { self.kind = kind self.base = base - self.isExperimental = isExperimental + self.experimentalFeature = experimentalFeature self.nameForDiagnostics = nameForDiagnostics self.documentation = docCommentTrivia(from: documentation) self.parserFunction = parserFunction @@ -226,7 +230,7 @@ public class Node { init( kind: SyntaxNodeKind, base: SyntaxNodeKind, - isExperimental: Bool = false, + experimentalFeature: ExperimentalFeature? = nil, nameForDiagnostics: String?, documentation: String? = nil, parserFunction: TokenSyntax? = nil, @@ -235,7 +239,7 @@ public class Node { self.kind = kind precondition(base == .syntaxCollection) self.base = base - self.isExperimental = isExperimental + self.experimentalFeature = experimentalFeature self.nameForDiagnostics = nameForDiagnostics self.documentation = docCommentTrivia(from: documentation) self.parserFunction = parserFunction diff --git a/CodeGeneration/Sources/SyntaxSupport/StmtNodes.swift b/CodeGeneration/Sources/SyntaxSupport/StmtNodes.swift index dd728c16fe8..4ee7d0286fd 100644 --- a/CodeGeneration/Sources/SyntaxSupport/StmtNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/StmtNodes.swift @@ -588,7 +588,7 @@ public let STMT_NODES: [Node] = [ kind: .thenStmt, base: .stmt, // FIXME: This should be marked experimental. - isExperimental: false, + experimentalFeature: nil, nameForDiagnostics: "'then' statement", documentation: """ A statement used to indicate the produced value from an if/switch diff --git a/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift b/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift index 2667854a716..c156f104207 100644 --- a/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift +++ b/CodeGeneration/Sources/SyntaxSupport/TokenSpec.swift @@ -24,11 +24,9 @@ public struct TokenSpec { /// The name of the token, suitable for use in variable or enum case names. public let varOrCaseName: TokenSyntax - /// Indicates if the token is part of an experimental language feature. - /// - /// If `true`, this keyword is for an experimental language feature, and any public - /// API generated should be marked as SPI - public let isExperimental: Bool + /// The experimental feature the token is part of, or `nil` if this isn't + /// for an experimental feature. + public let experimentalFeature: ExperimentalFeature? /// The name of the token that can be shown in diagnostics. public let nameForDiagnostics: String @@ -39,6 +37,12 @@ public struct TokenSpec { /// The kind of the token. public let kind: Kind + /// Indicates if the token is part of an experimental language feature. + /// + /// If `true`, this keyword is for an experimental language feature, and any public + /// API generated should be marked as SPI + public var isExperimental: Bool { experimentalFeature != nil } + /// The attributes that should be printed on any API for the generated keyword. /// /// This is typically used to mark APIs as SPI when the keyword is part of an experimental language feature. @@ -51,19 +55,19 @@ public struct TokenSpec { /// /// - Parameters: /// - name: A name of the token. - /// - isExperimental: Indicates if the token is part of an experimental language feature. + /// - experimentalFeature: The experimental feature the token is part of, or `nil` if this isn't for an experimental feature. /// - nameForDiagnostics: A name of the token that can be shown in diagnostics. /// - text: An actual text of the token, if available. /// - kind: A kind of the token. fileprivate init( name: String, - isExperimental: Bool = false, + experimentalFeature: ExperimentalFeature? = nil, nameForDiagnostics: String, text: String? = nil, kind: Kind ) { self.varOrCaseName = .identifier(name) - self.isExperimental = isExperimental + self.experimentalFeature = experimentalFeature self.nameForDiagnostics = nameForDiagnostics self.text = text self.kind = kind diff --git a/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift b/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift index 3384273d1c1..dd23798a666 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/GenerateSwiftSyntax.swift @@ -88,6 +88,7 @@ struct GenerateSwiftSyntax: ParsableCommand { var fileSpecs: [GeneratedFileSpec] = [ // SwiftParser + GeneratedFileSpec(swiftParserGeneratedDir + ["ExperimentalFeatures.swift"], experimentalFeaturesFile), GeneratedFileSpec(swiftParserGeneratedDir + ["IsLexerClassified.swift"], isLexerClassifiedFile), GeneratedFileSpec(swiftParserGeneratedDir + ["LayoutNodes+Parsable.swift"], layoutNodesParsableFile), GeneratedFileSpec(swiftParserGeneratedDir + ["Parser+TokenSpecSet.swift"], parserTokenSpecSetFile), diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ExperimentalFeaturesFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ExperimentalFeaturesFile.swift new file mode 100644 index 00000000000..ee22372fd29 --- /dev/null +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ExperimentalFeaturesFile.swift @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax +import SwiftSyntaxBuilder +import SyntaxSupport +import Utils + +let experimentalFeaturesFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { + DeclSyntax( + """ + extension Parser { + @_spi(ExperimentalLanguageFeatures) + public struct ExperimentalFeatures: OptionSet { + public let rawValue: UInt + public init(rawValue: UInt) { + self.rawValue = rawValue + } + } + } + """ + ) + + try! ExtensionDeclSyntax("extension Parser.ExperimentalFeatures") { + for (i, feature) in ExperimentalFeature.allCases.enumerated() { + DeclSyntax( + """ + /// Whether to enable the parsing of \(raw: feature.featureName). + public static let \(feature.token) = Self(rawValue: 1 << \(raw: i)) + """ + ) + } + } +} diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserTokenSpecSetFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserTokenSpecSetFile.swift index 66bfe9aa395..4e162beaad3 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserTokenSpecSetFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftparser/ParserTokenSpecSetFile.swift @@ -15,6 +15,14 @@ import SwiftSyntaxBuilder import SyntaxSupport import Utils +func tokenCaseMatch(_ caseName: TokenSyntax, experimentalFeature: ExperimentalFeature?) -> SwitchCaseSyntax { + let whereClause = + experimentalFeature.map { + "where experimentalFeatures.contains(.\($0.token))" + } ?? "" + return "case TokenSpec(.\(caseName))\(raw: whereClause): self = .\(caseName)" +} + let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { DeclSyntax("@_spi(RawSyntax) @_spi(ExperimentalLanguageFeatures) import SwiftSyntax") @@ -42,16 +50,20 @@ let parserTokenSpecSetFile = SourceFileSyntax(leadingTrivia: copyrightHeader) { } } - try InitializerDeclSyntax("init?(lexeme: Lexer.Lexeme)") { + try InitializerDeclSyntax("init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures)") { try SwitchExprSyntax("switch PrepareForKeywordMatch(lexeme)") { for choice in choices { switch choice { case .keyword(let keyword): - let caseName = keyword.spec.varOrCaseName - SwitchCaseSyntax("case TokenSpec(.\(caseName)): self = .\(caseName)") + tokenCaseMatch( + keyword.spec.varOrCaseName, + experimentalFeature: keyword.spec.experimentalFeature + ) case .token(let token): - let caseName = token.spec.varOrCaseName - SwitchCaseSyntax("case TokenSpec(.\(caseName)): self = .\(caseName)") + tokenCaseMatch( + token.spec.varOrCaseName, + experimentalFeature: token.spec.experimentalFeature + ) } } SwitchCaseSyntax("default: return nil") diff --git a/Sources/SwiftParser/Attributes.swift b/Sources/SwiftParser/Attributes.swift index 096dd0c2b2b..0429dfbc2b1 100644 --- a/Sources/SwiftParser/Attributes.swift +++ b/Sources/SwiftParser/Attributes.swift @@ -64,7 +64,7 @@ extension Parser { case objc case transpose - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._alignment): self = ._alignment case TokenSpec(._backDeploy): self = ._backDeploy @@ -1043,7 +1043,7 @@ extension Parser { } } - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.private): self = .private case TokenSpec(.fileprivate): self = .fileprivate diff --git a/Sources/SwiftParser/Availability.swift b/Sources/SwiftParser/Availability.swift index ac144c45187..4a784fb9e52 100644 --- a/Sources/SwiftParser/Availability.swift +++ b/Sources/SwiftParser/Availability.swift @@ -60,7 +60,7 @@ extension Parser { case star case identifier - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.message): self = .message case TokenSpec(.renamed): self = .renamed diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 43d6edcbf70..ea7e39f9efb 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -521,7 +521,7 @@ extension Parser { case postfixOperator case prefixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch (lexeme.rawTokenKind, lexeme.tokenText) { case (.colon, _): self = .colon case (.binaryOperator, "=="): self = .binaryOperator @@ -1719,7 +1719,7 @@ extension Parser { case higherThan case lowerThan - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.associativity): self = .associativity case TokenSpec(.assignment): self = .assignment diff --git a/Sources/SwiftParser/Directives.swift b/Sources/SwiftParser/Directives.swift index eb4c6e1b577..8e989a88c8c 100644 --- a/Sources/SwiftParser/Directives.swift +++ b/Sources/SwiftParser/Directives.swift @@ -26,7 +26,7 @@ extension Parser { } } - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.poundElseif): self = .poundElseif case TokenSpec(.poundElse): self = .poundElse diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index c75de582eb1..caece56ebdb 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -244,7 +244,7 @@ extension Parser { case arrow case `throws` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.binaryOperator): self = .binaryOperator case TokenSpec(.infixQuestionMark): self = .infixQuestionMark diff --git a/Sources/SwiftParser/Lookahead.swift b/Sources/SwiftParser/Lookahead.swift index e36108bde45..682e5e46f68 100644 --- a/Sources/SwiftParser/Lookahead.swift +++ b/Sources/SwiftParser/Lookahead.swift @@ -333,7 +333,7 @@ extension Parser.Lookahead { case poundElse case poundElseif - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch lexeme.rawTokenKind { case .leftParen: self = .leftParen case .leftBrace: self = .leftBrace diff --git a/Sources/SwiftParser/Modifiers.swift b/Sources/SwiftParser/Modifiers.swift index 48a32971166..a28e44c2343 100644 --- a/Sources/SwiftParser/Modifiers.swift +++ b/Sources/SwiftParser/Modifiers.swift @@ -169,7 +169,7 @@ extension Parser { } } - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.private): self = .private case TokenSpec(.fileprivate): self = .fileprivate diff --git a/Sources/SwiftParser/Names.swift b/Sources/SwiftParser/Names.swift index 17d5e00cdb0..a4a1f389f5d 100644 --- a/Sources/SwiftParser/Names.swift +++ b/Sources/SwiftParser/Names.swift @@ -304,7 +304,9 @@ extension Lexer.Lexeme { } func isContextualPunctuator(_ name: SyntaxText) -> Bool { - return Operator(lexeme: self) != nil && self.tokenText == name + // Currently we can ignore experimental features since a new kind of + // non-prefix/infix/postfix operator seems unlikely. + return Operator(lexeme: self, experimentalFeatures: []) != nil && self.tokenText == name } var isLexerClassifiedKeyword: Bool { diff --git a/Sources/SwiftParser/Patterns.swift b/Sources/SwiftParser/Patterns.swift index 159e18543e0..bbf21194a7f 100644 --- a/Sources/SwiftParser/Patterns.swift +++ b/Sources/SwiftParser/Patterns.swift @@ -21,7 +21,7 @@ extension Parser { case identifier case dollarIdentifier // For recovery - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.leftParen): self = .leftParen case TokenSpec(.wildcard): self = .wildcard @@ -282,7 +282,7 @@ extension Parser.Lookahead { case wildcard case leftParen - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier case TokenSpec(.wildcard): self = .wildcard diff --git a/Sources/SwiftParser/Specifiers.swift b/Sources/SwiftParser/Specifiers.swift index 2238cd54067..d901a118957 100644 --- a/Sources/SwiftParser/Specifiers.swift +++ b/Sources/SwiftParser/Specifiers.swift @@ -20,7 +20,7 @@ public enum AsyncEffectSpecifier: TokenSpecSet { case await case reasync - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { // We'll take 'await' too for recovery but they have to be on the same line // as the declaration they're modifying. switch PrepareForKeywordMatch(lexeme) { @@ -57,7 +57,7 @@ public enum ThrowsEffectSpecifier: TokenSpecSet { case `throws` case `try` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { // We'll take 'throw' and 'try' too for recovery but they have to // be on the same line as the declaration they're modifying. switch PrepareForKeywordMatch(lexeme) { @@ -95,10 +95,10 @@ public enum EffectSpecifier: TokenSpecSet { case asyncSpecifier(AsyncEffectSpecifier) case throwsSpecifier(ThrowsEffectSpecifier) - init?(lexeme: Lexer.Lexeme) { - if let subset = AsyncEffectSpecifier(lexeme: lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + if let subset = AsyncEffectSpecifier(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .asyncSpecifier(subset) - } else if let subset = ThrowsEffectSpecifier(lexeme: lexeme) { + } else if let subset = ThrowsEffectSpecifier(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .throwsSpecifier(subset) } else { return nil @@ -210,7 +210,7 @@ extension RawFunctionEffectSpecifiersSyntax: RawEffectSpecifiersTrait { enum MisspelledAsyncTokenKinds: TokenSpecSet { case await - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.await, allowAtStartOfLine: false): self = .await default: return nil @@ -228,7 +228,7 @@ extension RawFunctionEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case async case reasync - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.async): self = .async case TokenSpec(.reasync): self = .reasync @@ -248,7 +248,7 @@ extension RawFunctionEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case `try` case `throw` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.try, allowAtStartOfLine: false): self = .try case TokenSpec(.throw, allowAtStartOfLine: false): self = .throw @@ -268,7 +268,7 @@ extension RawFunctionEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case `rethrows` case `throws` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.rethrows): self = .rethrows case TokenSpec(.throws): self = .throws @@ -290,7 +290,7 @@ extension RawTypeEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case await case reasync - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.await, allowAtStartOfLine: false): self = .await case TokenSpec(.reasync): self = .reasync @@ -309,7 +309,7 @@ extension RawTypeEffectSpecifiersSyntax: RawEffectSpecifiersTrait { enum CorrectAsyncTokenKinds: TokenSpecSet { case async - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.async): self = .async default: return nil @@ -328,7 +328,7 @@ extension RawTypeEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case `try` case `throw` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.rethrows): self = .rethrows case TokenSpec(.try, allowAtStartOfLine: false): self = .try @@ -349,7 +349,7 @@ extension RawTypeEffectSpecifiersSyntax: RawEffectSpecifiersTrait { enum CorrectThrowsTokenKinds: TokenSpecSet { case `throws` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.throws): self = .throws default: return nil @@ -369,7 +369,7 @@ extension RawAccessorEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case await case reasync - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.await, allowAtStartOfLine: false): self = .await case TokenSpec(.reasync): self = .reasync @@ -388,7 +388,7 @@ extension RawAccessorEffectSpecifiersSyntax: RawEffectSpecifiersTrait { enum CorrectAsyncTokenKinds: TokenSpecSet { case async - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.async): self = .async default: return nil @@ -407,7 +407,7 @@ extension RawAccessorEffectSpecifiersSyntax: RawEffectSpecifiersTrait { case `try` case `throw` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.rethrows): self = .rethrows case TokenSpec(.try, allowAtStartOfLine: false): self = .try @@ -428,7 +428,7 @@ extension RawAccessorEffectSpecifiersSyntax: RawEffectSpecifiersTrait { enum CorrectThrowsTokenKinds: TokenSpecSet { case `throws` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.throws): self = .throws default: return nil @@ -448,7 +448,7 @@ extension RawDeinitializerEffectSpecifiersSyntax: RawMisplacedEffectSpecifiersTr case await case reasync - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.await, allowAtStartOfLine: false): self = .await case TokenSpec(.reasync): self = .reasync @@ -467,7 +467,7 @@ extension RawDeinitializerEffectSpecifiersSyntax: RawMisplacedEffectSpecifiersTr enum CorrectAsyncTokenKinds: TokenSpecSet { case async - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.async): self = .async default: return nil @@ -487,7 +487,7 @@ extension RawDeinitializerEffectSpecifiersSyntax: RawMisplacedEffectSpecifiersTr case `throw` case `throws` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.rethrows): self = .rethrows case TokenSpec(.try, allowAtStartOfLine: false): self = .try @@ -510,7 +510,7 @@ extension RawDeinitializerEffectSpecifiersSyntax: RawMisplacedEffectSpecifiersTr enum CorrectThrowsTokenKinds: TokenSpecSet { // Uninhabited - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { return nil } diff --git a/Sources/SwiftParser/Statements.swift b/Sources/SwiftParser/Statements.swift index 1e618bf4046..540d52d0de2 100644 --- a/Sources/SwiftParser/Statements.swift +++ b/Sources/SwiftParser/Statements.swift @@ -601,7 +601,7 @@ extension Parser { case poundElseif case endOfFile - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.rightBrace): self = .rightBrace case TokenSpec(.case): self = .case diff --git a/Sources/SwiftParser/TokenConsumer.swift b/Sources/SwiftParser/TokenConsumer.swift index 9462d2a2360..a349aa8ed3b 100644 --- a/Sources/SwiftParser/TokenConsumer.swift +++ b/Sources/SwiftParser/TokenConsumer.swift @@ -138,7 +138,7 @@ extension TokenConsumer { recordAlternativeTokenChoice(for: self.currentToken, choices: specSet.allCases.map(\.spec)) } #endif - if let matchedKind = SpecSet(lexeme: self.currentToken) { + if let matchedKind = SpecSet(lexeme: self.currentToken, experimentalFeatures: self.experimentalFeatures) { precondition(matchedKind.spec ~= self.currentToken) return ( matchedKind, @@ -152,7 +152,7 @@ extension TokenConsumer { /// If this is the case, return the corresponding `SpecSet` case. @inline(__always) func peek(isAtAnyIn specSet: SpecSet.Type) -> SpecSet? { - guard let matchedKind = SpecSet(lexeme: self.peek()) else { + guard let matchedKind = SpecSet(lexeme: self.peek(), experimentalFeatures: self.experimentalFeatures) else { return nil } precondition(matchedKind.spec ~= self.peek()) diff --git a/Sources/SwiftParser/TokenSpecSet.swift b/Sources/SwiftParser/TokenSpecSet.swift index 87aa295d627..194c0dbc409 100644 --- a/Sources/SwiftParser/TokenSpecSet.swift +++ b/Sources/SwiftParser/TokenSpecSet.swift @@ -17,8 +17,9 @@ protocol TokenSpecSet: CaseIterable { var spec: TokenSpec { get } - /// Creates an instance if `lexeme` satisfy the condition of this subset. - init?(lexeme: Lexer.Lexeme) + /// Creates an instance if `lexeme` satisfies the condition of this subset, + /// taking into account any `experimentalFeatures` active. + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) } /// A way to combine two token spec sets into an aggregate token spec set. @@ -26,12 +27,12 @@ enum EitherTokenSpecSet: TokenSpecSet { case lhs(LHS) case rhs(RHS) - init?(lexeme: Lexer.Lexeme) { - if let x = LHS(lexeme: lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + if let x = LHS(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .lhs(x) return } - if let y = RHS(lexeme: lexeme) { + if let y = RHS(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .rhs(y) return } @@ -62,7 +63,7 @@ enum AccessorModifier: TokenSpecSet { case mutating case nonmutating - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.__consuming): self = .__consuming case TokenSpec(.consuming): self = .consuming @@ -102,7 +103,7 @@ enum CanBeStatementStart: TokenSpecSet { case `while` case yield - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.break): self = .break case TokenSpec(.continue): self = .continue @@ -151,7 +152,7 @@ enum CompilationCondition: TokenSpecSet { case compiler case canImport - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.swift): self = .swift case TokenSpec(.compiler): self = .compiler @@ -198,7 +199,7 @@ enum ContextualDeclKeyword: TokenSpecSet { case unowned case weak - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.__consuming): self = .__consuming case TokenSpec(._compilerInitialized): self = ._compilerInitialized @@ -286,7 +287,7 @@ enum PureDeclarationKeyword: TokenSpecSet { case `typealias` case pound - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.actor): self = .actor case TokenSpec(.macro): self = .macro @@ -376,7 +377,7 @@ enum DeclarationModifier: TokenSpecSet { case unowned case weak - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.__consuming): self = .__consuming case TokenSpec(.__setter_access): self = .__setter_access @@ -465,10 +466,10 @@ enum DeclarationStart: TokenSpecSet { case declarationModifier(DeclarationModifier) case declarationKeyword(DeclarationKeyword) - init?(lexeme: Lexer.Lexeme) { - if let subset = DeclarationModifier(lexeme: lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + if let subset = DeclarationModifier(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .declarationModifier(subset) - } else if let subset = DeclarationKeyword(lexeme: lexeme) { + } else if let subset = DeclarationKeyword(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .declarationKeyword(subset) } else { return nil @@ -492,7 +493,9 @@ enum Operator: TokenSpecSet { case postfixOperator case prefixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + // NOTE: If you ever add any experimental features here, + // `isContextualPunctuator` will need updating to handle that. switch lexeme.rawTokenKind { case .binaryOperator: self = .binaryOperator case .postfixOperator: self = .postfixOperator @@ -517,7 +520,7 @@ enum BinaryOperatorLike: TokenSpecSet { case equal case arrow - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch lexeme.rawTokenKind { case .binaryOperator: self = .binaryOperator case .infixQuestionMark: self = .infixQuestionMark @@ -543,7 +546,7 @@ enum PostfixOperatorLike: TokenSpecSet { case exclamationMark case postfixQuestionMark - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch lexeme.rawTokenKind { case .postfixOperator: self = .postfixOperator case .exclamationMark: self = .exclamationMark @@ -567,16 +570,16 @@ enum OperatorLike: TokenSpecSet { case binaryOperatorLike(BinaryOperatorLike) case postfixOperatorLike(PostfixOperatorLike) - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { if case .prefixOperator = lexeme.rawTokenKind { self = .prefixOperator return } - if let binOp = BinaryOperatorLike(lexeme: lexeme) { + if let binOp = BinaryOperatorLike(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .binaryOperatorLike(binOp) return } - if let postfixOp = PostfixOperatorLike(lexeme: lexeme) { + if let postfixOp = PostfixOperatorLike(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .postfixOperatorLike(postfixOp) return } @@ -600,7 +603,7 @@ enum SwitchCaseStart: TokenSpecSet { case `case` case `default` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.case): self = .case case TokenSpec(.default): self = .default @@ -630,7 +633,7 @@ enum TypeAttribute: TokenSpecSet { case Sendable case unchecked - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._local): self = ._local case TokenSpec(._noMetadata): self = ._noMetadata @@ -674,7 +677,7 @@ public enum TypeSpecifier: TokenSpecSet { case borrowing case consuming - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.inout): self = .inout case TokenSpec(.__owned): self = .owned @@ -721,7 +724,7 @@ enum ExpressionModifierKeyword: TokenSpecSet { case each case any - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.await): self = .await case TokenSpec(._move): self = ._move @@ -755,7 +758,7 @@ enum IfOrSwitch: TokenSpecSet { case `if` case `switch` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.if): self = .if case TokenSpec(.switch): self = .switch @@ -776,7 +779,7 @@ enum ExpressionPrefixOperator: TokenSpecSet { case prefixAmpersand case prefixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch lexeme.rawTokenKind { case .backslash: self = .backslash case .prefixAmpersand: self = .prefixAmpersand @@ -801,7 +804,7 @@ enum ExpressionPrefixOperator: TokenSpecSet { enum PureMatchingPatternStart: TokenSpecSet { case `is` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.is): self = .is default: return nil @@ -824,7 +827,7 @@ enum ParameterModifier: TokenSpecSet { case _const case isolated - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._const): self = ._const case TokenSpec(.isolated): self = .isolated @@ -869,7 +872,7 @@ enum PrimaryExpressionStart: TokenSpecSet { case multilineStringQuote case singleQuote - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.Any): self = .Any case TokenSpec(.atSign): self = .atSign @@ -946,14 +949,14 @@ enum ExpressionStart: TokenSpecSet { case primaryExpressionStart(PrimaryExpressionStart) case ifOrSwitch(IfOrSwitch) - init?(lexeme: Lexer.Lexeme) { - if let subset = ExpressionModifierKeyword(lexeme: lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { + if let subset = ExpressionModifierKeyword(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .awaitTryMove(subset) - } else if let subset = ExpressionPrefixOperator(lexeme: lexeme) { + } else if let subset = ExpressionPrefixOperator(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .expressionPrefixOperator(subset) - } else if let subset = PrimaryExpressionStart(lexeme: lexeme) { + } else if let subset = PrimaryExpressionStart(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .primaryExpressionStart(subset) - } else if let subset = IfOrSwitch(lexeme: lexeme) { + } else if let subset = IfOrSwitch(lexeme: lexeme, experimentalFeatures: experimentalFeatures) { self = .ifOrSwitch(subset) } else { return nil @@ -986,7 +989,7 @@ enum EffectSpecifiers: TokenSpecSet { case `throws` case `try` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.async): self = .async case TokenSpec(.await, allowAtStartOfLine: false): self = .await diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift index 45e77a76709..31ac8474de5 100644 --- a/Sources/SwiftParser/Types.swift +++ b/Sources/SwiftParser/Types.swift @@ -203,7 +203,7 @@ extension Parser { case leftSquare case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case .keyword(.Self): self = .Self case .keyword(.Any): self = .Any From 6e20f5462c238cdc7d866b64638ca919955bf9dc Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 Sep 2023 19:22:46 +0100 Subject: [PATCH 4/5] [generated] Re-generate code --- Sources/SwiftParser/CMakeLists.txt | 2 +- .../ExperimentalFeatures.swift | 9 +- .../generated/Parser+TokenSpecSet.swift | 132 +++++++++--------- 3 files changed, 73 insertions(+), 70 deletions(-) rename Sources/SwiftParser/{ => generated}/ExperimentalFeatures.swift (80%) diff --git a/Sources/SwiftParser/CMakeLists.txt b/Sources/SwiftParser/CMakeLists.txt index ae849ac9deb..061450b0209 100644 --- a/Sources/SwiftParser/CMakeLists.txt +++ b/Sources/SwiftParser/CMakeLists.txt @@ -13,7 +13,6 @@ add_swift_host_library(SwiftParser CollectionNodes+Parsable.swift Declarations.swift Directives.swift - ExperimentalFeatures.swift Expressions.swift IncrementalParseTransition.swift Lookahead.swift @@ -39,6 +38,7 @@ add_swift_host_library(SwiftParser TriviaParser.swift Types.swift + generated/ExperimentalFeatures.swift generated/IsLexerClassified.swift generated/LayoutNodes+Parsable.swift generated/Parser+TokenSpecSet.swift diff --git a/Sources/SwiftParser/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift similarity index 80% rename from Sources/SwiftParser/ExperimentalFeatures.swift rename to Sources/SwiftParser/generated/ExperimentalFeatures.swift index ee77a12322c..b8fe727b8de 100644 --- a/Sources/SwiftParser/ExperimentalFeatures.swift +++ b/Sources/SwiftParser/generated/ExperimentalFeatures.swift @@ -1,8 +1,10 @@ +//// Automatically generated by generate-swift-syntax +//// Do not edit directly! //===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // -// Copyright (c) 2023 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -14,6 +16,7 @@ extension Parser { @_spi(ExperimentalLanguageFeatures) public struct ExperimentalFeatures: OptionSet { public let rawValue: UInt + public init(rawValue: UInt) { self.rawValue = rawValue } @@ -21,9 +24,9 @@ extension Parser { } extension Parser.ExperimentalFeatures { - /// Whether to enable the parsing of 'reference bindings'. + /// Whether to enable the parsing of reference bindings. public static let referenceBindings = Self(rawValue: 1 << 0) - + /// Whether to enable the parsing of 'then' statements. public static let thenStatements = Self(rawValue: 1 << 1) } diff --git a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift index dadc43a1631..88b69cbe667 100644 --- a/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift +++ b/Sources/SwiftParser/generated/Parser+TokenSpecSet.swift @@ -31,7 +31,7 @@ extension AccessorDeclSyntax { case _modify case `init` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.get): self = .get @@ -138,7 +138,7 @@ extension AsExprSyntax { case postfixQuestionMark case exclamationMark - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.postfixQuestionMark): self = .postfixQuestionMark @@ -184,7 +184,7 @@ extension AttributedTypeSyntax { case borrowing case consuming - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.inout): self = .inout @@ -255,7 +255,7 @@ extension AvailabilityConditionSyntax { case poundAvailable case poundUnavailable - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.poundAvailable): self = .poundAvailable @@ -299,7 +299,7 @@ extension AvailabilityLabeledArgumentSyntax { case obsoleted case deprecated - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.message): self = .message @@ -358,7 +358,7 @@ extension BooleanLiteralExprSyntax { case `true` case `false` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.true): self = .true @@ -399,7 +399,7 @@ extension CanImportVersionInfoSyntax { case _version case _underlyingVersion - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._version): self = ._version @@ -440,7 +440,7 @@ extension ClosureCaptureSpecifierSyntax { case weak case unowned - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.weak): self = .weak @@ -481,7 +481,7 @@ extension ClosureCaptureSpecifierSyntax { case safe case unsafe - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.safe): self = .safe @@ -522,7 +522,7 @@ extension ClosureParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -563,7 +563,7 @@ extension ClosureParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -604,7 +604,7 @@ extension ClosureShorthandParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -645,7 +645,7 @@ extension ConsumeExprSyntax { case _move case consume - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._move): self = ._move @@ -719,7 +719,7 @@ extension DeclModifierSyntax { case unowned case weak - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.__consuming): self = .__consuming @@ -963,7 +963,7 @@ extension DeclReferenceExprSyntax { case binaryOperator case integerLiteral - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1034,7 +1034,7 @@ extension DerivativeAttributeArgumentsSyntax { case get case set - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.get): self = .get @@ -1076,7 +1076,7 @@ extension DifferentiabilityArgumentSyntax { case integerLiteral case `self` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1124,7 +1124,7 @@ extension DifferentiableAttributeArgumentsSyntax { case reverse case _linear - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._forward): self = ._forward @@ -1171,7 +1171,7 @@ extension DocumentationAttributeArgumentSyntax { case visibility case metadata - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.visibility): self = .visibility @@ -1212,7 +1212,7 @@ extension EnumCaseParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1253,7 +1253,7 @@ extension EnumCaseParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1296,7 +1296,7 @@ extension FunctionDeclSyntax { case prefixOperator case postfixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1349,7 +1349,7 @@ extension FunctionEffectSpecifiersSyntax { case async case reasync - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.async): self = .async @@ -1390,7 +1390,7 @@ extension FunctionEffectSpecifiersSyntax { case `throws` case `rethrows` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.throws): self = .throws @@ -1431,7 +1431,7 @@ extension FunctionParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1472,7 +1472,7 @@ extension FunctionParameterSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1514,7 +1514,7 @@ extension IdentifierPatternSyntax { case `self` case `init` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1563,7 +1563,7 @@ extension IdentifierTypeSyntax { case `Any` case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1617,7 +1617,7 @@ extension IfConfigClauseSyntax { case poundElseif case poundElse - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.poundIf): self = .poundIf @@ -1671,7 +1671,7 @@ extension ImportDeclSyntax { case `func` case `inout` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.typealias): self = .typealias @@ -1756,7 +1756,7 @@ extension ImportPathComponentSyntax { case prefixOperator case postfixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1809,7 +1809,7 @@ extension InitializerDeclSyntax { case postfixQuestionMark case exclamationMark - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.postfixQuestionMark): self = .postfixQuestionMark @@ -1850,7 +1850,7 @@ extension KeyPathOptionalComponentSyntax { case postfixQuestionMark case exclamationMark - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.postfixQuestionMark): self = .postfixQuestionMark @@ -1891,7 +1891,7 @@ extension LabeledExprSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -1937,7 +1937,7 @@ extension LabeledSpecializeArgumentSyntax { case spiModule case available - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.target): self = .target @@ -2013,7 +2013,7 @@ extension LayoutRequirementSyntax { case _Class case _NativeClass - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(._Trivial): self = ._Trivial @@ -2084,7 +2084,7 @@ extension MemberTypeSyntax { case identifier case `self` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -2125,7 +2125,7 @@ extension MetatypeTypeSyntax { case `Type` case `Protocol` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.Type): self = .Type @@ -2166,7 +2166,7 @@ extension MultipleTrailingClosureElementSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -2208,7 +2208,7 @@ extension OperatorDeclSyntax { case postfix case infix - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.prefix): self = .prefix @@ -2256,7 +2256,7 @@ extension OperatorDeclSyntax { case prefixOperator case postfixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.binaryOperator): self = .binaryOperator @@ -2310,7 +2310,7 @@ extension OptionalBindingConditionSyntax { @_spi(ExperimentalLanguageFeatures) case _consuming - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.let): self = .let @@ -2318,11 +2318,11 @@ extension OptionalBindingConditionSyntax { self = .var case TokenSpec(.inout): self = .inout - case TokenSpec(._mutating): + case TokenSpec(._mutating) where experimentalFeatures.contains(.referenceBindings): self = ._mutating - case TokenSpec(._borrowing): + case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings): self = ._borrowing - case TokenSpec(._consuming): + case TokenSpec(._consuming) where experimentalFeatures.contains(.referenceBindings): self = ._consuming default: return nil @@ -2375,7 +2375,7 @@ extension PrecedenceGroupAssignmentSyntax { case `true` case `false` - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.true): self = .true @@ -2417,7 +2417,7 @@ extension PrecedenceGroupAssociativitySyntax { case right case none - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.left): self = .left @@ -2464,7 +2464,7 @@ extension PrecedenceGroupRelationSyntax { case higherThan case lowerThan - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.higherThan): self = .higherThan @@ -2506,7 +2506,7 @@ extension SameTypeRequirementSyntax { case prefixOperator case postfixOperator - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.binaryOperator): self = .binaryOperator @@ -2553,7 +2553,7 @@ extension SimpleStringLiteralExprSyntax { case stringQuote case multilineStringQuote - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.stringQuote): self = .stringQuote @@ -2594,7 +2594,7 @@ extension SimpleStringLiteralExprSyntax { case stringQuote case multilineStringQuote - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.stringQuote): self = .stringQuote @@ -2635,7 +2635,7 @@ extension SomeOrAnyTypeSyntax { case some case any - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.some): self = .some @@ -2677,7 +2677,7 @@ extension StringLiteralExprSyntax { case multilineStringQuote case singleQuote - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.stringQuote): self = .stringQuote @@ -2725,7 +2725,7 @@ extension StringLiteralExprSyntax { case multilineStringQuote case singleQuote - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.stringQuote): self = .stringQuote @@ -2772,7 +2772,7 @@ extension TryExprSyntax { case postfixQuestionMark case exclamationMark - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.postfixQuestionMark): self = .postfixQuestionMark @@ -2813,7 +2813,7 @@ extension TupleTypeElementSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -2854,7 +2854,7 @@ extension TupleTypeElementSyntax { case identifier case wildcard - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.identifier): self = .identifier @@ -2895,7 +2895,7 @@ extension UnresolvedAsExprSyntax { case postfixQuestionMark case exclamationMark - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.postfixQuestionMark): self = .postfixQuestionMark @@ -2943,7 +2943,7 @@ extension ValueBindingPatternSyntax { @_spi(ExperimentalLanguageFeatures) case _consuming - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.let): self = .let @@ -2951,11 +2951,11 @@ extension ValueBindingPatternSyntax { self = .var case TokenSpec(.inout): self = .inout - case TokenSpec(._mutating): + case TokenSpec(._mutating) where experimentalFeatures.contains(.referenceBindings): self = ._mutating - case TokenSpec(._borrowing): + case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings): self = ._borrowing - case TokenSpec(._consuming): + case TokenSpec(._consuming) where experimentalFeatures.contains(.referenceBindings): self = ._consuming default: return nil @@ -3015,7 +3015,7 @@ extension VariableDeclSyntax { @_spi(ExperimentalLanguageFeatures) case _consuming - init?(lexeme: Lexer.Lexeme) { + init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) { switch PrepareForKeywordMatch(lexeme) { case TokenSpec(.let): self = .let @@ -3023,11 +3023,11 @@ extension VariableDeclSyntax { self = .var case TokenSpec(.inout): self = .inout - case TokenSpec(._mutating): + case TokenSpec(._mutating) where experimentalFeatures.contains(.referenceBindings): self = ._mutating - case TokenSpec(._borrowing): + case TokenSpec(._borrowing) where experimentalFeatures.contains(.referenceBindings): self = ._borrowing - case TokenSpec(._consuming): + case TokenSpec(._consuming) where experimentalFeatures.contains(.referenceBindings): self = ._consuming default: return nil From 4695dc7f54810e021b3d514defd676efa2763cec Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Mon, 18 Sep 2023 19:22:46 +0100 Subject: [PATCH 5/5] Remove unnecessary feature checks We now check these with the spec set. --- Sources/SwiftParser/Declarations.swift | 14 +----- Sources/SwiftParser/Patterns.swift | 66 ++++++++------------------ 2 files changed, 23 insertions(+), 57 deletions(-) diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index ea7e39f9efb..0678ea87944 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -138,8 +138,6 @@ extension TokenConsumer { // FIXME: C++ parser returns true if this is a top-level non-"script" files. // But we don't have "is library" flag. return false - case .rhs(._borrowing), .rhs(._consuming), .rhs(._mutating): - return experimentalFeatures.contains(.referenceBindings) case .some(_): // All other decl start keywords unconditionally start a decl. return true @@ -249,16 +247,8 @@ extension Parser { return RawDeclSyntax(self.parseMacroDeclaration(attrs: attrs, introducerHandle: handle)) case (.lhs(.pound), let handle)?: return RawDeclSyntax(self.parseMacroExpansionDeclaration(attrs, handle)) - case (.rhs(let binding), let handle)?: - switch binding { - case ._mutating, ._borrowing, ._consuming: - guard experimentalFeatures.contains(.referenceBindings) else { - break - } - fallthrough - case .let, .var, .inout: - return RawDeclSyntax(self.parseBindingDeclaration(attrs, handle, inMemberDeclList: inMemberDeclList)) - } + case (.rhs, let handle)?: + return RawDeclSyntax(self.parseBindingDeclaration(attrs, handle, inMemberDeclList: inMemberDeclList)) case nil: break } diff --git a/Sources/SwiftParser/Patterns.swift b/Sources/SwiftParser/Patterns.swift index bbf21194a7f..f82d0452873 100644 --- a/Sources/SwiftParser/Patterns.swift +++ b/Sources/SwiftParser/Patterns.swift @@ -86,24 +86,16 @@ extension Parser { arena: self.arena ) ) - case (.rhs(let binding), let handle)?: - switch binding { - case ._mutating, ._borrowing, ._consuming: - guard experimentalFeatures.contains(.referenceBindings) else { - break - } - fallthrough - case .let, .var, .inout: - let bindingSpecifier = self.eat(handle) - let value = self.parsePattern() - return RawPatternSyntax( - RawValueBindingPatternSyntax( - bindingSpecifier: bindingSpecifier, - pattern: value, - arena: self.arena - ) + case (.rhs, let handle)?: + let bindingSpecifier = self.eat(handle) + let value = self.parsePattern() + return RawPatternSyntax( + RawValueBindingPatternSyntax( + bindingSpecifier: bindingSpecifier, + pattern: value, + arena: self.arena ) - } + ) case nil: break } @@ -227,24 +219,16 @@ extension Parser { arena: self.arena ) ) - case (.rhs(let binding), let handle)?: - switch binding { - case ._mutating, ._borrowing, ._consuming: - guard experimentalFeatures.contains(.referenceBindings) else { - break - } - fallthrough - case .let, .var, .inout: - let bindingSpecifier = self.eat(handle) - let value = self.parseMatchingPattern(context: .bindingIntroducer) - return RawPatternSyntax( - RawValueBindingPatternSyntax( - bindingSpecifier: bindingSpecifier, - pattern: value, - arena: self.arena - ) + case (.rhs, let handle)?: + let bindingSpecifier = self.eat(handle) + let value = self.parseMatchingPattern(context: .bindingIntroducer) + return RawPatternSyntax( + RawValueBindingPatternSyntax( + bindingSpecifier: bindingSpecifier, + pattern: value, + arena: self.arena ) - } + ) case nil: break } @@ -311,17 +295,9 @@ extension Parser.Lookahead { return true case (.lhs(.leftParen), _)?: return self.canParsePatternTuple() - case (.rhs(let binding), let handle)?: - switch binding { - case ._mutating, ._borrowing, ._consuming: - guard experimentalFeatures.contains(.referenceBindings) else { - return false - } - fallthrough - case .let, .var, .inout: - self.eat(handle) - return self.canParsePattern() - } + case (.rhs, let handle)?: + self.eat(handle) + return self.canParsePattern() case nil: return false }