diff --git a/CodeGeneration/Sources/SyntaxSupport/AvailabilityNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AvailabilityNodes.swift index b2e42bec97a..80134e48eb2 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AvailabilityNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AvailabilityNodes.swift @@ -128,9 +128,21 @@ public let AVAILABILITY_NODES: [Node] = [ kind: "Syntax", children: [ Child( - name: "MajorMinor", - kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken"), .token(tokenKind: "FloatingLiteralToken")]), - description: "In case the version consists only of the major version, an integer literal that specifies the major version. In case the version consists of major and minor version number, a floating literal in which the decimal part is interpreted as the minor version." + name: "Major", + kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken")]), + description: "The major version." + ), + Child( + name: "MinorPeriod", + kind: .token(choices: [.token(tokenKind: "PeriodToken")]), + description: "If the version contains a minor number, the period separating the major from the minor number.", + isOptional: true + ), + Child( + name: "Minor", + kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken")]), + description: "The minor version if specified.", + isOptional: true ), Child( name: "PatchPeriod", @@ -139,7 +151,7 @@ public let AVAILABILITY_NODES: [Node] = [ isOptional: true ), Child( - name: "PatchVersion", + name: "Patch", kind: .token(choices: [.token(tokenKind: "IntegerLiteralToken")]), description: "The patch version if specified.", isOptional: true diff --git a/Sources/SwiftParser/Availability.swift b/Sources/SwiftParser/Availability.swift index c329bfc2fd4..003b96bf045 100644 --- a/Sources/SwiftParser/Availability.swift +++ b/Sources/SwiftParser/Availability.swift @@ -241,6 +241,18 @@ extension Parser { ) } + /// If the next token is an integer literal only consisting of the digits 0-9 + /// consume and return it, otherwise return a missing integer token. + private mutating func expectDecimalIntegerWithoutRecovery() -> RawTokenSyntax { + guard self.at(.integerLiteral) else { + return missingToken(.integerLiteral, text: nil) + } + guard self.currentToken.tokenText.allSatisfy({ Unicode.Scalar($0).isDigit }) else { + return missingToken(.integerLiteral, text: nil) + } + return self.consumeAnyToken() + } + /// Parse a dot-separated list of version numbers. /// /// Grammar @@ -250,31 +262,43 @@ extension Parser { /// platform-version → decimal-digits '.' decimal-digits /// platform-version → decimal-digits '.' decimal-digits '.' decimal-digits mutating func parseVersionTuple() -> RawVersionTupleSyntax { - let (unexpectedBeforeMajorMinor, majorMinor) = self.expect(.integerLiteral, .floatingLiteral, default: .integerLiteral) - let patchPeriod: RawTokenSyntax? - let unexpectedBeforePatch: RawUnexpectedNodesSyntax? - let patch: RawTokenSyntax? - if majorMinor.tokenKind == .floatingLiteral { - patchPeriod = self.consume(if: .period) - if patchPeriod != nil { - (unexpectedBeforePatch, patch) = self.expect(.integerLiteral) + if self.at(.floatingLiteral), + let periodIndex = self.currentToken.tokenText.firstIndex(of: UInt8(ascii: ".")), + self.currentToken.tokenText[0..