Skip to content

Commit 3b3f372

Browse files
authored
Merge pull request #794 from CodaFi/dead-on-time
Another Grab Bag of Parser Fixes
2 parents 892b73b + 353100d commit 3b3f372

37 files changed

+2140
-219
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
extension Parser {
1616
mutating func parseAttributeList() -> RawAttributeListSyntax? {
17-
guard self.at(.atSign) else {
17+
guard self.at(any: [.atSign, .poundIfKeyword]) else {
1818
return nil
1919
}
2020

@@ -23,20 +23,30 @@ extension Parser {
2323
repeat {
2424
let attribute = self.parseAttribute()
2525
elements.append(attribute)
26-
} while self.at(.atSign) && loopProgress.evaluate(currentToken)
26+
} while self.at(any: [.atSign, .poundIfKeyword]) && loopProgress.evaluate(currentToken)
2727
return RawAttributeListSyntax(elements: elements, arena: self.arena)
2828
}
2929
}
3030

3131
extension Parser {
3232
mutating func parseAttribute() -> RawSyntax {
33+
if self.at(.poundIfKeyword) {
34+
return RawSyntax(self.parsePoundIfDirective { parser -> RawSyntax in
35+
return parser.parseAttribute()
36+
} syntax: { parser, attributes in
37+
return RawSyntax(RawAttributeListSyntax(elements: attributes, arena: parser.arena))
38+
})
39+
}
40+
3341
guard let declAttr = DeclarationAttribute(rawValue: self.peek().tokenText) else {
3442
return RawSyntax(self.parseCustomAttribute())
3543
}
3644

3745
switch declAttr {
3846
case .available:
3947
return RawSyntax(self.parseAvailabilityAttribute())
48+
case ._spi_available:
49+
return RawSyntax(self.parseSPIAvailableAttribute())
4050
case .differentiable:
4151
return RawSyntax(self.parseDifferentiableAttribute())
4252
case .derivative:
@@ -152,6 +162,37 @@ extension Parser {
152162
tokenList: nil,
153163
arena: self.arena)
154164
}
165+
166+
mutating func parseSPIAvailableAttribute() -> RawAttributeSyntax {
167+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
168+
let (unexpectedBeforeAvailable, available) = self.expectContextualKeyword("_spi_available")
169+
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
170+
171+
let argument: RawSyntax
172+
do {
173+
if self.peek().tokenKind == .integerLiteral {
174+
argument = RawSyntax(self.parseAvailabilitySpecList(from: .available))
175+
} else if self.peek().tokenKind == .floatingLiteral {
176+
argument = RawSyntax(self.parseAvailabilitySpecList(from: .available))
177+
} else {
178+
argument = RawSyntax(self.parseExtendedAvailabilitySpecList())
179+
}
180+
}
181+
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
182+
183+
return RawAttributeSyntax(
184+
unexpectedBeforeAtSign,
185+
atSignToken: atSign,
186+
unexpectedBeforeAvailable,
187+
attributeName: available,
188+
unexpectedBeforeLeftParen,
189+
leftParen: leftParen,
190+
argument: argument,
191+
unexpectedBeforeRightParen,
192+
rightParen: rightParen,
193+
tokenList: nil,
194+
arena: self.arena)
195+
}
155196
}
156197

157198
extension Parser {
@@ -508,13 +549,13 @@ extension Parser {
508549
let ident = self.eat(handle)
509550
let (unexpectedBeforeColon, colon) = self.expect(.colon)
510551
let availability = self.parseAvailabilitySpecList(from: .available)
511-
// FIXME: This is modeled incorrectly in libSyntax.
512-
let semi = RawTokenSyntax(missing: .semicolon, arena: self.arena)
552+
let (unexpectedBeforeSemi, semi) = self.expect(.semicolon)
513553
elements.append(RawSyntax(RawAvailabilityEntrySyntax(
514554
label: ident,
515555
unexpectedBeforeColon,
516556
colon: colon,
517557
availabilityList: availability,
558+
unexpectedBeforeSemi,
518559
semicolon: semi,
519560
arena: self.arena
520561
)))
@@ -761,6 +802,54 @@ extension Parser {
761802
}
762803
}
763804

805+
extension Parser {
806+
mutating func parseConventionArguments() -> RawSyntax {
807+
if let witnessMethod = self.consumeIfContextualKeyword("witness_method") {
808+
let (unexpectedBeforeColon, colon) = self.expect(.colon)
809+
let name = self.parseAnyIdentifier()
810+
return RawSyntax(RawConventionWitnessMethodAttributeArgumentsSyntax(
811+
witnessMethodLabel: witnessMethod,
812+
unexpectedBeforeColon,
813+
colon: colon,
814+
protocolName: name,
815+
arena: self.arena))
816+
} else {
817+
let label = self.consumeAnyToken()
818+
let unexpectedBeforeComma: RawUnexpectedNodesSyntax?
819+
let comma: RawTokenSyntax?
820+
let cTypeLabel: RawTokenSyntax?
821+
let unexpectedBeforeColon: RawUnexpectedNodesSyntax?
822+
let colon: RawTokenSyntax?
823+
let unexpectedBeforeCTypeString: RawUnexpectedNodesSyntax?
824+
let cTypeString: RawTokenSyntax?
825+
if self.at(.comma) {
826+
(unexpectedBeforeComma, comma) = self.expect(.comma)
827+
cTypeLabel = self.consumeAnyToken()
828+
(unexpectedBeforeColon, colon) = self.expect(.colon)
829+
(unexpectedBeforeCTypeString, cTypeString) = self.expect(.stringLiteral)
830+
} else {
831+
unexpectedBeforeComma = nil
832+
comma = nil
833+
cTypeLabel = nil
834+
unexpectedBeforeColon = nil
835+
colon = nil
836+
unexpectedBeforeCTypeString = nil
837+
cTypeString = nil
838+
}
839+
return RawSyntax(RawConventionAttributeArgumentsSyntax(
840+
conventionLabel: label,
841+
unexpectedBeforeComma,
842+
comma: comma,
843+
cTypeLabel: cTypeLabel,
844+
unexpectedBeforeColon,
845+
colon: colon,
846+
unexpectedBeforeCTypeString,
847+
cTypeString: cTypeString,
848+
arena: self.arena))
849+
}
850+
}
851+
}
852+
764853
// MARK: Lookahead
765854

766855
extension Parser.Lookahead {

Sources/SwiftParser/Availability.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,11 @@ extension Parser {
139139
case nil:
140140
// Not sure what this label is but, let's just eat it and
141141
// keep going.
142-
entry = RawSyntax(self.consumeAnyToken())
142+
var tokens = [RawTokenSyntax]()
143+
while !self.at(any: [.eof, .comma, .rightParen]) {
144+
tokens.append(self.consumeAnyToken())
145+
}
146+
entry = RawSyntax(RawNonEmptyTokenListSyntax(elements: tokens, arena: self.arena))
143147
}
144148

145149
keepGoing = self.consume(if: .comma)

Sources/SwiftParser/DeclarationAttribute.swift.gyb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ extension Parser {
2525
% for attr in DECL_ATTR_KINDS:
2626
case ${attr.swift_name} = "${attr.name}"
2727
% end
28+
case _spi_available = "_spi_available"
2829
}
2930
}

Sources/SwiftParser/Declarations.swift

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ extension TokenConsumer {
4747
}
4848
}
4949

50+
if subparser.at(.poundIfKeyword) {
51+
var attrLookahead = subparser.lookahead()
52+
return attrLookahead.consumeIfConfigOfAttributes()
53+
}
54+
5055
let declStartKeyword: DeclarationStart?
5156
if allowRecovery {
5257
declStartKeyword = subparser.canRecoverTo(
@@ -507,7 +512,13 @@ extension Parser {
507512
do {
508513
var loopProgress = LoopProgressCondition()
509514
while !self.at(any: [.eof, .rightBrace]) && loopProgress.evaluate(currentToken) {
510-
let decl = self.parseDeclaration()
515+
let decl: RawDeclSyntax
516+
if self.at(.poundSourceLocationKeyword) {
517+
decl = RawDeclSyntax(self.parsePoundSourceLocationDirective())
518+
} else {
519+
decl = self.parseDeclaration()
520+
}
521+
511522
let semi = self.consume(if: .semicolon)
512523
elements.append(RawMemberDeclListItemSyntax(
513524
decl: decl, semicolon: semi, arena: self.arena))
@@ -1876,10 +1887,22 @@ extension Parser {
18761887
// checking.
18771888
let precedenceAndTypes: RawOperatorPrecedenceAndTypesSyntax?
18781889
if let colon = self.consume(if: .colon) {
1879-
let identifier = self.expectIdentifierWithoutRecovery()
1890+
let (unexpectedBeforeIdentifier, identifier) = self.expectIdentifier()
1891+
var types = [RawDesignatedTypeElementSyntax]()
1892+
while let comma = self.consume(if: .comma) {
1893+
let (unexpectedBeforeDesignatedType, designatedType) = self.expectIdentifier()
1894+
types.append(RawDesignatedTypeElementSyntax(
1895+
leadingComma: comma,
1896+
unexpectedBeforeDesignatedType,
1897+
name: designatedType,
1898+
arena: self.arena))
1899+
}
18801900
precedenceAndTypes = RawOperatorPrecedenceAndTypesSyntax(
18811901
colon: colon,
1882-
precedenceGroupAndDesignatedTypes: RawIdentifierListSyntax(elements: [ identifier ], arena: self.arena),
1902+
unexpectedBeforeIdentifier,
1903+
precedenceGroup: identifier,
1904+
designatedTypes: RawDesignatedTypeListSyntax(
1905+
elements: types, arena: self.arena),
18831906
arena: self.arena)
18841907
} else {
18851908
precedenceAndTypes = nil

Sources/SwiftParser/Lookahead.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,44 @@ extension Parser.Lookahead {
197197
}
198198
return true
199199
}
200+
201+
mutating func consumeIfConfigOfAttributes() -> Bool {
202+
while true {
203+
// #if / #else / #elseif
204+
self.consumeAnyToken()
205+
206+
// <expression>
207+
self.skipUntilEndOfLine()
208+
209+
while true {
210+
if self.at(.atSign) {
211+
_ = self.consumeAttributeList()
212+
continue
213+
}
214+
215+
if self.at(.poundIfKeyword) {
216+
_ = self.consumeIfConfigOfAttributes()
217+
continue
218+
}
219+
220+
break
221+
}
222+
223+
guard self.at(any: [ .poundElseifKeyword, .poundElseKeyword ]) else {
224+
break
225+
}
226+
}
227+
228+
// If we ran out of tokens, say we consumed the rest.
229+
if self.at(.eof) {
230+
return true
231+
}
232+
233+
guard self.currentToken.isAtStartOfLine else {
234+
return false
235+
}
236+
return self.consume(if: .poundEndifKeyword) != nil
237+
}
200238
}
201239

202240
// MARK: Lookahead

Sources/SwiftParser/Types.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ extension Parser {
803803
let (unexpectedBeforeAt, at) = self.expect(.atSign)
804804
let (unexpectedBeforeIdent, ident) = self.expectIdentifier()
805805
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
806-
let (unexpectedBeforeArgument, argument) = self.expectIdentifier()
806+
let arguments = self.parseConventionArguments()
807807
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
808808
return RawSyntax(
809809
RawAttributeSyntax(
@@ -813,8 +813,7 @@ extension Parser {
813813
attributeName: ident,
814814
unexpectedBeforeLeftParen,
815815
leftParen: leftParen,
816-
unexpectedBeforeArgument,
817-
argument: RawSyntax(argument),
816+
argument: arguments,
818817
unexpectedBeforeRightParen,
819818
rightParen: rightParen,
820819
tokenList: nil,

Sources/SwiftParser/gyb_generated/DeclarationAttribute.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,6 @@ extension Parser {
119119
case _spiOnly = "_spiOnly"
120120
case _documentation = "_documentation"
121121
case typeWrapperIgnored = "typeWrapperIgnored"
122+
case _spi_available = "_spi_available"
122123
}
123124
}

Sources/SwiftSyntax/Documentation.docc/gyb_generated/SwiftSyntax.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
234234
- <doc:SwiftSyntax/PatternBindingSyntax>
235235
- <doc:SwiftSyntax/EnumCaseElementListSyntax>
236236
- <doc:SwiftSyntax/EnumCaseElementSyntax>
237+
- <doc:SwiftSyntax/DesignatedTypeListSyntax>
238+
- <doc:SwiftSyntax/DesignatedTypeElementSyntax>
237239
- <doc:SwiftSyntax/PrecedenceGroupNameListSyntax>
238240
- <doc:SwiftSyntax/PrecedenceGroupNameElementSyntax>
239241
- <doc:SwiftSyntax/ObjCSelectorSyntax>
@@ -328,7 +330,8 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
328330
- <doc:SwiftSyntax/PatternBindingListSyntax>
329331
- <doc:SwiftSyntax/EnumCaseElementSyntax>
330332
- <doc:SwiftSyntax/EnumCaseElementListSyntax>
331-
- <doc:SwiftSyntax/IdentifierListSyntax>
333+
- <doc:SwiftSyntax/DesignatedTypeListSyntax>
334+
- <doc:SwiftSyntax/DesignatedTypeElementSyntax>
332335
- <doc:SwiftSyntax/OperatorPrecedenceAndTypesSyntax>
333336
- <doc:SwiftSyntax/PrecedenceGroupAttributeListSyntax>
334337
- <doc:SwiftSyntax/PrecedenceGroupRelationSyntax>
@@ -362,6 +365,8 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
362365
- <doc:SwiftSyntax/BackDeployVersionListSyntax>
363366
- <doc:SwiftSyntax/BackDeployVersionArgumentSyntax>
364367
- <doc:SwiftSyntax/OpaqueReturnTypeOfAttributeArgumentsSyntax>
368+
- <doc:SwiftSyntax/ConventionAttributeArgumentsSyntax>
369+
- <doc:SwiftSyntax/ConventionWitnessMethodAttributeArgumentsSyntax>
365370
- <doc:SwiftSyntax/SwitchCaseListSyntax>
366371
- <doc:SwiftSyntax/WhereClauseSyntax>
367372
- <doc:SwiftSyntax/CatchClauseListSyntax>

0 commit comments

Comments
 (0)