Skip to content

Commit cfd5f0d

Browse files
committed
Eliminate eat from the parser
Use one of the following alternatives instead: - `expect` (mostly at start of productions) - `consume(if:)` where this paradigm is applicable - `consume(if:followedBy:)` to consume two tokens at once - A new `at(anyIn:)` paradigm that allows the parser to check if it is currently positioned at a known token kind, which can be exhausitively switched. If this is the case, the token can be safely consumed using a handle. - This function might seem overly complicated at the moment but it should allow us to later switch to a similar function that also does recovery.
1 parent 5e8636a commit cfd5f0d

19 files changed

+632
-493
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -181,24 +181,20 @@ extension Parser {
181181
}
182182

183183

184-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
184+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
185185
let ident = self.consumeIdentifier()
186-
let unexpectedBeforeLeftParen: RawUnexpectedNodesSyntax?
187-
let leftParen: RawTokenSyntax?
186+
let leftParen = self.consume(if: .leftParen)
188187
let arg: RawSyntax?
189188
let unexpectedBeforeRightParen: RawUnexpectedNodesSyntax?
190189
let rightParen: RawTokenSyntax?
191-
if self.at(.leftParen) {
190+
if leftParen != nil {
192191
var args = [RawTokenSyntax]()
193-
(unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
194192
while !self.at(.eof), !self.at(.rightParen) {
195193
args.append(self.consumeAnyToken())
196194
}
197195
arg = RawSyntax(RawTokenListSyntax(elements: args, arena: self.arena))
198196
(unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
199197
} else {
200-
unexpectedBeforeLeftParen = nil
201-
leftParen = nil
202198
arg = nil
203199
unexpectedBeforeRightParen = nil
204200
rightParen = nil
@@ -207,7 +203,6 @@ extension Parser {
207203
unexpectedBeforeAtSign,
208204
atSignToken: atSign,
209205
attributeName: ident,
210-
unexpectedBeforeLeftParen,
211206
leftParen: leftParen,
212207
argument: arg,
213208
unexpectedBeforeRightParen,
@@ -217,25 +212,25 @@ extension Parser {
217212
}
218213

219214
mutating func parseCustomAttribute() -> RawCustomAttributeSyntax {
220-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
215+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
221216
let attrName = self.parseType()
222217

223218
// Custom attributes are stricter than normal attributes about their
224219
// argument lists "immediately" following the attribute name.
225-
guard self.at(.leftParen) && !self.currentToken.isAtStartOfLine && self.lookahead().isCustomAttributeArgument() else {
220+
guard let leftParen = self.consume(if: .leftParen, where: { (lexeme, parser) in
221+
!lexeme.isAtStartOfLine && parser.lookahead().isCustomAttributeArgument()
222+
}) else {
226223
return RawCustomAttributeSyntax(
227224
atSignToken: atSign, attributeName: attrName,
228225
leftParen: nil, argumentList: nil, rightParen: nil,
229226
arena: self.arena)
230227
}
231-
let (unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
232228
let arguments = self.parseArgumentListElements()
233229
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
234230
return RawCustomAttributeSyntax(
235231
unexpectedBeforeAtSign,
236232
atSignToken: atSign,
237233
attributeName: attrName,
238-
unexpectedBeforeLeftParen,
239234
leftParen: leftParen,
240235
argumentList: RawTupleExprElementListSyntax(elements: arguments, arena: self.arena),
241236
unexpectedBeforeRightParen,
@@ -246,7 +241,7 @@ extension Parser {
246241

247242
extension Parser {
248243
mutating func parseAvailabilityAttribute() -> RawAttributeSyntax {
249-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
244+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
250245
assert(self.currentToken.tokenText == "available")
251246
let available = self.consumeAnyToken()
252247
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -279,7 +274,7 @@ extension Parser {
279274

280275
extension Parser {
281276
mutating func parseDifferentiableAttribute() -> RawAttributeSyntax {
282-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
277+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
283278
assert(self.currentToken.tokenText == "differentiable")
284279
let differentiable = self.consumeAnyToken()
285280
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -349,7 +344,7 @@ extension Parser {
349344
let wrt = self.consumeIdentifier()
350345
let (unexpectedBeforeColon, colon) = self.expect(.colon)
351346

352-
guard self.at(.leftParen) else {
347+
guard let leftParen = self.consume(if: .leftParen) else {
353348
// If no opening '(' for parameter list, parse a single parameter.
354349
let param = self.parseDifferentiabilityParameter().map(RawSyntax.init(_:))
355350
?? RawSyntax(RawMissingSyntax(arena: self.arena))
@@ -362,7 +357,6 @@ extension Parser {
362357
)
363358
}
364359

365-
let (unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
366360
var elements = [RawDifferentiabilityParamSyntax]()
367361
while !self.at(.eof) && !self.at(.rightParen) {
368362
guard let param = self.parseDifferentiabilityParameter() else {
@@ -374,7 +368,6 @@ extension Parser {
374368

375369
let parameters = RawDifferentiabilityParamListSyntax(elements: elements, arena: self.arena)
376370
let list = RawDifferentiabilityParamsSyntax(
377-
unexpectedBeforeLeftParen,
378371
leftParen: leftParen,
379372
diffParams: parameters,
380373
unexpectedBeforeRightParen,
@@ -391,50 +384,59 @@ extension Parser {
391384
}
392385

393386
mutating func parseDifferentiabilityParameter() -> RawDifferentiabilityParamSyntax? {
394-
switch self.currentToken.tokenKind {
395-
case .identifier:
396-
let token = self.consumeIdentifier()
387+
enum ExpectedTokenKind: RawTokenKindSubset {
388+
case identifier
389+
case integerLiteral
390+
case selfKeyword
391+
392+
var rawTokenKind: RawTokenKind {
393+
switch self {
394+
case .identifier: return .identifier
395+
case .integerLiteral: return .integerLiteral
396+
case .selfKeyword: return .selfKeyword
397+
}
398+
}
399+
}
400+
401+
switch self.at(anyIn: ExpectedTokenKind.self) {
402+
case (.identifier, let handle)?:
403+
let token = self.eat(handle)
397404
let comma = self.consume(if: .comma)
398405
return RawDifferentiabilityParamSyntax(
399406
parameter: RawSyntax(token), trailingComma: comma, arena: self.arena)
400-
case .integerLiteral:
401-
let token = self.consumeAnyToken()
407+
case (.integerLiteral, let handle)?:
408+
let token = self.eat(handle)
402409
let comma = self.consume(if: .comma)
403410
return RawDifferentiabilityParamSyntax(
404411
parameter: RawSyntax(token), trailingComma: comma, arena: self.arena)
405-
case .selfKeyword:
406-
let (unexpectedBeforeToken, token) = self.eat(.selfKeyword)
412+
case (.selfKeyword, let handle)?:
413+
let token = self.eat(handle)
407414
let comma = self.consume(if: .comma)
408415
return RawDifferentiabilityParamSyntax(
409-
unexpectedBeforeToken,
410416
parameter: RawSyntax(token),
411417
trailingComma: comma,
412418
arena: self.arena
413419
)
414-
default:
420+
case nil:
415421
return nil
416422
}
417423
}
418424
}
419425

420426
extension Parser {
421427
mutating func parseObjectiveCAttribute() -> RawAttributeSyntax {
422-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
428+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
423429
assert(self.currentToken.tokenText == "objc")
424430
let objc = self.consumeAnyToken()
425431

426-
let unexpectedBeforeLeftParen: RawUnexpectedNodesSyntax?
427-
let leftParen: RawTokenSyntax?
432+
let leftParen = self.consume(if: .leftParen)
428433
let argument: RawObjCSelectorSyntax?
429434
let unexpectedBeforeRightParen: RawUnexpectedNodesSyntax?
430435
let rightParen: RawTokenSyntax?
431-
if self.at(.leftParen) {
432-
(unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
436+
if leftParen != nil {
433437
argument = self.parseObjectiveCSelector()
434438
(unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
435439
} else {
436-
unexpectedBeforeLeftParen = nil
437-
leftParen = nil
438440
argument = nil
439441
unexpectedBeforeRightParen = nil
440442
rightParen = nil
@@ -444,7 +446,6 @@ extension Parser {
444446
unexpectedBeforeAtSign,
445447
atSignToken: atSign,
446448
attributeName: objc,
447-
unexpectedBeforeLeftParen,
448449
leftParen: leftParen,
449450
argument: argument.map(RawSyntax.init),
450451
unexpectedBeforeRightParen,
@@ -457,11 +458,9 @@ extension Parser {
457458
var elements = [RawObjCSelectorPieceSyntax]()
458459
while !self.at(.eof) && !self.at(.rightParen) {
459460
// Empty selector piece.
460-
if self.at(.colon) {
461-
let (unexpectedBeforeColon, colon) = self.eat(.colon)
461+
if let colon = self.consume(if: .colon) {
462462
elements.append(RawObjCSelectorPieceSyntax(
463463
name: nil,
464-
unexpectedBeforeColon,
465464
colon: colon,
466465
arena: self.arena
467466
))
@@ -484,7 +483,7 @@ extension Parser {
484483

485484
extension Parser {
486485
mutating func parseSpecializeAttribute() -> RawAttributeSyntax {
487-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
486+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
488487
assert(self.currentToken.tokenText == "_specialize")
489488
let specializeToken = self.consumeAnyToken()
490489
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -668,7 +667,7 @@ extension Parser {
668667

669668
extension Parser {
670669
mutating func parsePrivateImportAttribute() -> RawAttributeSyntax {
671-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
670+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
672671
assert(self.currentToken.tokenText == "_private")
673672
let privateToken = self.consumeAnyToken()
674673
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -698,7 +697,7 @@ extension Parser {
698697

699698
extension Parser {
700699
mutating func parseDynamicReplacementAttribute() -> RawAttributeSyntax {
701-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
700+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
702701
assert(self.currentToken.tokenText == "_dynamicReplacement")
703702
let dynamicReplacementToken = self.consumeAnyToken()
704703
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -736,7 +735,7 @@ extension Parser {
736735

737736
extension Parser {
738737
mutating func parseSPIAttribute() -> RawAttributeSyntax {
739-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
738+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
740739
assert(self.currentToken.tokenText == "_spi")
741740
let spiToken = self.consumeAnyToken()
742741
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)

Sources/SwiftParser/Availability.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,10 @@ extension Parser {
128128
))
129129
case .deprecated:
130130
let argumentLabel = self.consumeAnyToken()
131-
if self.at(.colon) {
132-
let (unexpectedBeforeColon, colon) = self.eat(.colon)
131+
if let colon = self.consume(if: .colon) {
133132
let version = self.parseVersionTuple()
134133
entry = RawSyntax(RawAvailabilityLabeledArgumentSyntax(
135134
label: argumentLabel,
136-
unexpectedBeforeColon,
137135
colon: colon,
138136
value: RawSyntax(version),
139137
arena: self.arena

0 commit comments

Comments
 (0)