Skip to content

Commit aea4442

Browse files
committed
Fix multiple cases where the parser produced token kinds that didn’t match the token kinds in the syntax node definitions
The main problem here was that we were accepting `self` and `Self` in `expectIdentifier` but not handling that in the syntax tree. I went through every call of `expectIdentifier` and checked what the C++ parser does to maintain the behavior. Where we need to accept `self` or `Self` for compatibility reasons, it is now remapped to an identifier.
1 parent 94add47 commit aea4442

File tree

15 files changed

+57
-135
lines changed

15 files changed

+57
-135
lines changed

CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ public let ATTRIBUTE_NODES: [Node] = [
301301
children: [
302302
Child(
303303
name: "DeclBaseName",
304-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "PrefixOperatorToken"), .keyword(text: "init")]),
304+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "BinaryOperatorToken"), .keyword(text: "init"), .keyword(text: "self"), .keyword(text: "Self")]),
305305
nameForDiagnostics: "base name",
306306
description: "The base name of the protocol's requirement."
307307
),
@@ -468,7 +468,7 @@ public let ATTRIBUTE_NODES: [Node] = [
468468
children: [
469469
Child(
470470
name: "DiffKind",
471-
kind: .token(choices: [.keyword(text: "forward"), .keyword(text: "reverse"), .keyword(text: "linear")]),
471+
kind: .token(choices: [.keyword(text: "_forward"), .keyword(text: "reverse"), .keyword(text: "_linear")]),
472472
isOptional: true
473473
),
474474
Child(
@@ -644,7 +644,7 @@ public let ATTRIBUTE_NODES: [Node] = [
644644
children: [
645645
Child(
646646
name: "Label",
647-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "available"), .keyword(text: "exported"), .keyword(text: "kind"), .keyword(text: "spi"), .keyword(text: "spiModule")]),
647+
kind: .node(kind: "Token"),
648648
nameForDiagnostics: "label",
649649
description: "The label of the argument"
650650
),
@@ -677,7 +677,7 @@ public let ATTRIBUTE_NODES: [Node] = [
677677
children: [
678678
Child(
679679
name: "Name",
680-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
680+
kind: .node(kind: "Token"),
681681
nameForDiagnostics: "name",
682682
isOptional: true
683683
),
@@ -779,7 +779,7 @@ public let ATTRIBUTE_NODES: [Node] = [
779779
),
780780
Child(
781781
name: "Name",
782-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "BinaryOperatorToken"), .token(tokenKind: "PrefixOperatorToken"), .token(tokenKind: "PostfixOperatorToken")]),
782+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "self"), .keyword(text: "Self"), .keyword(text: "init"), .token(tokenKind: "BinaryOperatorToken")]),
783783
nameForDiagnostics: "base name",
784784
description: "The base name of the referenced function."
785785
),

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public let DECL_NODES: [Node] = [
1919
children: [
2020
Child(
2121
name: "Name",
22-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
22+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "BinaryOperatorToken"), .token(tokenKind: "PrefixOperatorToken"), .token(tokenKind: "PostfixOperatorToken")]),
2323
nameForDiagnostics: "name"
2424
),
2525
Child(

Sources/SwiftParser/Attributes.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,12 @@ extension Parser {
575575
let (unexpectedBetweenOfLabelAndColon, colon) = self.expect(.colon)
576576
let originalDeclName = self.parseQualifiedDeclarationName()
577577
let period = self.consume(if: .period)
578+
let unexpectedBeforeAccessor: RawUnexpectedNodesSyntax?
578579
let accessor: RawTokenSyntax?
579580
if period != nil {
580-
accessor = self.parseAnyIdentifier()
581+
(unexpectedBeforeAccessor, accessor) = self.expect(.keyword(.get), .keyword(.set), default: .keyword(.get))
581582
} else {
582-
accessor = nil
583+
(unexpectedBeforeAccessor, accessor) = (nil, nil)
583584
}
584585
let comma = self.consume(if: .comma)
585586
let diffParams: RawDifferentiabilityParamsClauseSyntax?
@@ -595,6 +596,7 @@ extension Parser {
595596
colon: colon,
596597
originalDeclName: originalDeclName,
597598
period: period,
599+
unexpectedBeforeAccessor,
598600
accessorKind: accessor,
599601
comma: comma,
600602
diffParams: diffParams,

Sources/SwiftParser/Declarations.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ extension Parser {
476476
// Parse the 'each' keyword for a type parameter pack 'each T'.
477477
var each = self.consume(if: .keyword(.each))
478478

479-
let (unexpectedBetweenEachAndName, name) = self.expectIdentifier()
479+
let (unexpectedBetweenEachAndName, name) = self.expectIdentifier(allowSelfOrCapitalSelfAsIdentifier: true)
480480
if attributes == nil && each == nil && unexpectedBetweenEachAndName == nil && name.isMissing && elements.isEmpty {
481481
break
482482
}
@@ -631,7 +631,7 @@ extension Parser {
631631
body: .sameTypeRequirement(
632632
RawSameTypeRequirementSyntax(
633633
leftTypeIdentifier: RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)),
634-
equalityToken: missingToken(.equal),
634+
equalityToken: missingToken(.binaryOperator, text: "=="),
635635
rightTypeIdentifier: RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)),
636636
arena: self.arena
637637
)
@@ -890,7 +890,7 @@ extension Parser {
890890
var loopProgress = LoopProgressCondition()
891891
repeat {
892892
let unexpectedPeriod = self.consume(if: .period)
893-
let (unexpectedBeforeName, name) = self.expectIdentifier(allowIdentifierLikeKeywords: false, keywordRecovery: true)
893+
let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)
894894

895895
let associatedValue: RawParameterClauseSyntax?
896896
if self.at(TokenSpec(.leftParen, allowAtStartOfLine: false)) {
@@ -1916,7 +1916,7 @@ extension Parser {
19161916
// checking.
19171917
let precedenceAndTypes: RawOperatorPrecedenceAndTypesSyntax?
19181918
if let colon = self.consume(if: .colon) {
1919-
let (unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(keywordRecovery: true)
1919+
let (unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(allowSelfOrCapitalSelfAsIdentifier: true)
19201920
var types = [RawDesignatedTypeElementSyntax]()
19211921
while let comma = self.consume(if: .comma) {
19221922
// FIXME: The compiler accepts... anything here. This is a bug.
@@ -2001,7 +2001,7 @@ extension Parser {
20012001
_ handle: RecoveryConsumptionHandle
20022002
) -> RawPrecedenceGroupDeclSyntax {
20032003
let (unexpectedBeforeGroup, group) = self.eat(handle)
2004-
let (unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(keywordRecovery: true)
2004+
let (unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(allowSelfOrCapitalSelfAsIdentifier: true)
20052005
let (unexpectedBeforeLBrace, lbrace) = self.expect(.leftBrace)
20062006

20072007
let groupAttributes = self.parsePrecedenceGroupAttributeListSyntax()

Sources/SwiftParser/Expressions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,7 @@ extension Parser {
17961796
let expression: RawExprSyntax
17971797
if self.peek().rawTokenKind == .equal {
17981798
// The name is a new declaration.
1799-
(unexpectedBeforeName, name) = self.expectIdentifier()
1799+
(unexpectedBeforeName, name) = self.expect(.identifier, TokenSpec(.self, remapping: .identifier), default: .identifier)
18001800
(unexpectedBeforeAssignToken, assignToken) = self.expect(.equal)
18011801
expression = self.parseExpression()
18021802
} else {

Sources/SwiftParser/Lookahead.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ extension Parser.Lookahead {
187187
while let _ = self.consume(if: .atSign) {
188188
// Consume qualified names that may or may not involve generic arguments.
189189
repeat {
190-
self.expectIdentifierOrRethrowsWithoutRecovery()
190+
self.consume(if: .identifier, .keyword(.rethrows))
191191
// We don't care whether this succeeds or fails to eat generic
192192
// parameters.
193193
_ = self.consumeGenericArguments()

Sources/SwiftParser/Names.swift

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,20 @@ extension Parser {
6363

6464
mutating func parseDeclNameRef(_ flags: DeclNameOptions = []) -> (RawTokenSyntax, RawDeclNameArgumentsSyntax?) {
6565
// Consume the base name.
66-
let ident: RawTokenSyntax
67-
if self.at(.identifier) || self.at(.keyword(.self), .keyword(.Self), .keyword(.`init`)) {
68-
ident = self.expectIdentifierWithoutRecovery()
66+
let base: RawTokenSyntax
67+
if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) ?? self.consume(if: .keyword(.`init`)) {
68+
base = identOrSelf
6969
} else if flags.contains(.operators), let (_, _) = self.at(anyIn: Operator.self) {
70-
ident = self.consumeAnyToken(remapping: .binaryOperator)
70+
base = self.consumeAnyToken(remapping: .binaryOperator)
7171
} else if flags.contains(.keywords) && self.currentToken.isLexerClassifiedKeyword {
72-
ident = self.consumeAnyToken(remapping: .identifier)
72+
base = self.consumeAnyToken(remapping: .identifier)
7373
} else {
74-
ident = self.expectIdentifierWithoutRecovery()
74+
base = missingToken(.identifier)
7575
}
7676

7777
// Parse an argument list, if the flags allow it and it's present.
7878
let args = self.parseArgLabelList(flags)
79-
return (ident, args)
79+
return (base, args)
8080
}
8181

8282
mutating func parseArgLabelList(_ flags: DeclNameOptions) -> RawDeclNameArgumentsSyntax? {
@@ -176,7 +176,7 @@ extension Parser {
176176
var keepGoing: RawTokenSyntax? = nil
177177
var loopProgress = LoopProgressCondition()
178178
repeat {
179-
let (name, _) = self.parseDeclNameRef()
179+
let (unexpectedBeforeName, name) = self.expect(.identifier, .keyword(.self), .keyword(.Self), default: .identifier)
180180
let generics: RawGenericArgumentClauseSyntax?
181181
if self.atContextualPunctuator("<") {
182182
generics = self.parseGenericArguments()
@@ -188,6 +188,7 @@ extension Parser {
188188
RawMemberTypeIdentifierSyntax(
189189
baseType: result!,
190190
period: keepGoing,
191+
unexpectedBeforeName,
191192
name: name,
192193
genericArgumentClause: generics,
193194
arena: self.arena
@@ -196,6 +197,7 @@ extension Parser {
196197
} else {
197198
result = RawTypeSyntax(
198199
RawSimpleTypeIdentifierSyntax(
200+
unexpectedBeforeName,
199201
name: name,
200202
genericArgumentClause: generics,
201203
arena: self.arena

Sources/SwiftParser/Nominals.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ extension Parser {
150150
introucerHandle: RecoveryConsumptionHandle
151151
) -> T where T: NominalTypeDeclarationTrait {
152152
let (unexpectedBeforeIntroducerKeyword, introducerKeyword) = self.eat(introucerHandle)
153-
let (unexpectedBeforeName, name) = self.expectIdentifier(allowIdentifierLikeKeywords: false, keywordRecovery: true)
153+
let (unexpectedBeforeName, name) = self.expectIdentifier(keywordRecovery: true)
154154
if unexpectedBeforeName == nil && name.isMissing && self.currentToken.isAtStartOfLine {
155155
return T.init(
156156
attributes: attrs.attributes,
@@ -258,7 +258,7 @@ extension Parser {
258258
var loopProgress = LoopProgressCondition()
259259
repeat {
260260
// Parse the name of the parameter.
261-
let (unexpectedBeforeName, name) = self.expectIdentifier()
261+
let (unexpectedBeforeName, name) = self.expectIdentifier(allowSelfOrCapitalSelfAsIdentifier: true)
262262
keepGoing = self.consume(if: .comma)
263263
associatedTypes.append(
264264
RawPrimaryAssociatedTypeSyntax(

Sources/SwiftParser/Parser.swift

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -417,18 +417,20 @@ extension Parser {
417417
/// incorrectly used a keyword as an identifier.
418418
/// This should be set if keywords aren't strong recovery marker at this
419419
/// position, e.g. because the parser expects a punctuator next.
420+
///
421+
/// If `allowSelfOrCapitalSelfAsIdentifier` is `true`, then `self` and `Self`
422+
/// are also accepted and remapped to identifiers. This is exclusively used
423+
/// to maintain compatibility with the C++ parser. No new uses of this should
424+
/// be introduced.
420425
mutating func expectIdentifier(
421-
allowIdentifierLikeKeywords: Bool = true,
422-
keywordRecovery: Bool = false
426+
keywordRecovery: Bool = false,
427+
allowSelfOrCapitalSelfAsIdentifier: Bool = false
423428
) -> (RawUnexpectedNodesSyntax?, RawTokenSyntax) {
424-
if allowIdentifierLikeKeywords {
425-
if let (_, handle) = self.canRecoverTo(anyIn: IdentifierTokens.self) {
426-
return self.eat(handle)
427-
}
428-
} else {
429-
if let identifier = self.consume(if: .identifier) {
430-
return (nil, identifier)
431-
}
429+
if let identifier = self.consume(if: .identifier) {
430+
return (nil, identifier)
431+
}
432+
if allowSelfOrCapitalSelfAsIdentifier, let selfOrCapitalSelf = self.consume(if: TokenSpec(.self, remapping: .identifier), TokenSpec(.Self, remapping: .identifier)) {
433+
return (nil, selfOrCapitalSelf)
432434
}
433435
if let unknown = self.consume(if: .unknown) {
434436
return (
@@ -457,22 +459,6 @@ extension Parser {
457459
)
458460
}
459461

460-
mutating func expectIdentifierOrRethrows() -> (RawUnexpectedNodesSyntax?, RawTokenSyntax) {
461-
if let (_, handle) = self.canRecoverTo(anyIn: IdentifierOrRethrowsTokens.self) {
462-
return self.eat(handle)
463-
}
464-
if let unknown = self.consume(if: .unknown) {
465-
return (
466-
RawUnexpectedNodesSyntax(elements: [RawSyntax(unknown)], arena: self.arena),
467-
self.missingToken(.identifier)
468-
)
469-
}
470-
return (
471-
nil,
472-
self.missingToken(.identifier)
473-
)
474-
}
475-
476462
/// Expect a right brace but with a little smart recovery logic:
477463
/// If `leftBrace` is missing, we only recover to a `}` whose indentation is greater or equal to that of `introducer`.
478464
/// That way, if the developer forgot to to type `{`, we won't eat `}` that were most likely intended to close an outer scope.

Sources/SwiftParser/Statements.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ extension Parser {
932932
return nil
933933
}
934934

935-
return self.expectIdentifierWithoutRecovery()
935+
return self.expectWithoutRecovery(.identifier)
936936
}
937937
}
938938

Sources/SwiftParser/TokenConsumer.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -219,22 +219,6 @@ extension TokenConsumer {
219219
// MARK: Convenience functions
220220

221221
extension TokenConsumer {
222-
@inline(__always)
223-
mutating func expectIdentifierWithoutRecovery() -> Token {
224-
if let (_, handle) = self.at(anyIn: IdentifierTokens.self) {
225-
return self.eat(handle)
226-
}
227-
return missingToken(.identifier)
228-
}
229-
230-
@inline(__always)
231-
mutating func expectIdentifierOrRethrowsWithoutRecovery() -> Token {
232-
if let (_, handle) = self.at(anyIn: IdentifierOrRethrowsTokens.self) {
233-
return self.eat(handle)
234-
}
235-
return missingToken(.identifier)
236-
}
237-
238222
var canHaveParameterSpecifier: Bool {
239223
// The parameter specifiers like `isolated`, `consuming`, `borrowing` are
240224
// also valid identifiers and could be the name of a type. Check whether

Sources/SwiftParser/TokenSpecSet.swift

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -298,64 +298,6 @@ enum DeclarationStart: TokenSpecSet {
298298
}
299299
}
300300

301-
enum IdentifierTokens: TokenSpecSet {
302-
case anyKeyword
303-
case capitalSelfKeyword
304-
case identifier
305-
case initKeyword
306-
case selfKeyword
307-
308-
init?(lexeme: Lexer.Lexeme) {
309-
switch PrepareForKeywordMatch(lexeme) {
310-
case TokenSpec(.Any): self = .anyKeyword
311-
case TokenSpec(.Self): self = .capitalSelfKeyword
312-
case TokenSpec(.identifier): self = .identifier
313-
case TokenSpec(.`init`): self = .initKeyword
314-
case TokenSpec(.self): self = .selfKeyword
315-
default: return nil
316-
}
317-
}
318-
319-
var spec: TokenSpec {
320-
switch self {
321-
case .anyKeyword: return .keyword(.Any)
322-
case .capitalSelfKeyword: return .keyword(.Self)
323-
case .identifier: return .identifier
324-
case .initKeyword: return .keyword(.`init`)
325-
case .selfKeyword: return .keyword(.self)
326-
}
327-
}
328-
}
329-
330-
enum IdentifierOrRethrowsTokens: TokenSpecSet {
331-
case anyKeyword
332-
case capitalSelfKeyword
333-
case identifier
334-
case selfKeyword
335-
case rethrowsKeyword
336-
337-
init?(lexeme: Lexer.Lexeme) {
338-
switch PrepareForKeywordMatch(lexeme) {
339-
case TokenSpec(.Any): self = .anyKeyword
340-
case TokenSpec(.Self): self = .capitalSelfKeyword
341-
case TokenSpec(.identifier): self = .identifier
342-
case TokenSpec(.self): self = .selfKeyword
343-
case TokenSpec(.rethrows): self = .rethrowsKeyword
344-
default: return nil
345-
}
346-
}
347-
348-
var spec: TokenSpec {
349-
switch self {
350-
case .anyKeyword: return .keyword(.Any)
351-
case .capitalSelfKeyword: return .keyword(.Self)
352-
case .identifier: return .identifier
353-
case .selfKeyword: return .keyword(.self)
354-
case .rethrowsKeyword: return TokenSpec(.rethrows, remapping: .identifier)
355-
}
356-
}
357-
}
358-
359301
enum Operator: TokenSpecSet {
360302
case binaryOperator
361303
case postfixOperator

Sources/SwiftParser/Types.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ extension Parser {
271271
)
272272
)
273273
} else {
274-
let (name, generics) = self.parseTypeNameWithGenerics(include: .keywords)
274+
let (name, generics) = self.parseTypeNameWithGenerics(allowKeywordAsName: true)
275275
base = RawTypeSyntax(
276276
RawMemberTypeIdentifierSyntax(
277277
baseType: base,
@@ -337,8 +337,15 @@ extension Parser {
337337
)
338338
}
339339

340-
mutating func parseTypeNameWithGenerics(include flags: DeclNameOptions = []) -> (RawTokenSyntax, RawGenericArgumentClauseSyntax?) {
341-
let (name, _) = self.parseDeclNameRef(flags)
340+
mutating func parseTypeNameWithGenerics(allowKeywordAsName: Bool) -> (RawTokenSyntax, RawGenericArgumentClauseSyntax?) {
341+
let name: RawTokenSyntax
342+
if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) {
343+
name = identOrSelf
344+
} else if allowKeywordAsName && self.currentToken.isLexerClassifiedKeyword {
345+
name = self.consumeAnyToken(remapping: .identifier)
346+
} else {
347+
name = missingToken(.identifier)
348+
}
342349
if self.atContextualPunctuator("<") {
343350
return (name, self.parseGenericArguments())
344351
}
@@ -356,7 +363,7 @@ extension Parser {
356363
return RawTypeSyntax(self.parseAnyType())
357364
}
358365

359-
let (name, generics) = parseTypeNameWithGenerics()
366+
let (name, generics) = parseTypeNameWithGenerics(allowKeywordAsName: false)
360367
return RawTypeSyntax(
361368
RawSimpleTypeIdentifierSyntax(
362369
name: name,

0 commit comments

Comments
 (0)