Skip to content

Commit 4834b88

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 3a32d1b commit 4834b88

19 files changed

+634
-496
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -182,25 +182,21 @@ extension Parser {
182182
}
183183

184184

185-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
185+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
186186
let ident = self.consumeIdentifier()
187-
let unexpectedBeforeLeftParen: RawUnexpectedNodesSyntax?
188-
let leftParen: RawTokenSyntax?
187+
let leftParen = self.consume(if: .leftParen)
189188
let arg: RawSyntax?
190189
let unexpectedBeforeRightParen: RawUnexpectedNodesSyntax?
191190
let rightParen: RawTokenSyntax?
192-
if self.at(.leftParen) {
191+
if leftParen != nil {
193192
var args = [RawTokenSyntax]()
194-
(unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
195193
var loopProgress = LoopProgressCondition()
196-
while !self.at(.eof) && !self.at(.rightParen) && loopProgress.evaluate(currentToken) {
194+
while !self.at(.eof), !self.at(.rightParen) && loopProgress.evaluate(currentToken) {
197195
args.append(self.consumeAnyToken())
198196
}
199197
arg = RawSyntax(RawTokenListSyntax(elements: args, arena: self.arena))
200198
(unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
201199
} else {
202-
unexpectedBeforeLeftParen = nil
203-
leftParen = nil
204200
arg = nil
205201
unexpectedBeforeRightParen = nil
206202
rightParen = nil
@@ -209,7 +205,6 @@ extension Parser {
209205
unexpectedBeforeAtSign,
210206
atSignToken: atSign,
211207
attributeName: ident,
212-
unexpectedBeforeLeftParen,
213208
leftParen: leftParen,
214209
argument: arg,
215210
unexpectedBeforeRightParen,
@@ -219,25 +214,25 @@ extension Parser {
219214
}
220215

221216
mutating func parseCustomAttribute() -> RawCustomAttributeSyntax {
222-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
217+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
223218
let attrName = self.parseType()
224219

225220
// Custom attributes are stricter than normal attributes about their
226221
// argument lists "immediately" following the attribute name.
227-
guard self.at(.leftParen) && !self.currentToken.isAtStartOfLine && self.lookahead().isCustomAttributeArgument() else {
222+
guard let leftParen = self.consume(if: .leftParen, where: { (lexeme, parser) in
223+
!lexeme.isAtStartOfLine && parser.lookahead().isCustomAttributeArgument()
224+
}) else {
228225
return RawCustomAttributeSyntax(
229226
atSignToken: atSign, attributeName: attrName,
230227
leftParen: nil, argumentList: nil, rightParen: nil,
231228
arena: self.arena)
232229
}
233-
let (unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
234230
let arguments = self.parseArgumentListElements()
235231
let (unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
236232
return RawCustomAttributeSyntax(
237233
unexpectedBeforeAtSign,
238234
atSignToken: atSign,
239235
attributeName: attrName,
240-
unexpectedBeforeLeftParen,
241236
leftParen: leftParen,
242237
argumentList: RawTupleExprElementListSyntax(elements: arguments, arena: self.arena),
243238
unexpectedBeforeRightParen,
@@ -248,7 +243,7 @@ extension Parser {
248243

249244
extension Parser {
250245
mutating func parseAvailabilityAttribute() -> RawAttributeSyntax {
251-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
246+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
252247
assert(self.currentToken.tokenText == "available")
253248
let available = self.consumeAnyToken()
254249
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -281,7 +276,7 @@ extension Parser {
281276

282277
extension Parser {
283278
mutating func parseDifferentiableAttribute() -> RawAttributeSyntax {
284-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
279+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
285280
assert(self.currentToken.tokenText == "differentiable")
286281
let differentiable = self.consumeAnyToken()
287282
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -351,7 +346,7 @@ extension Parser {
351346
let wrt = self.consumeIdentifier()
352347
let (unexpectedBeforeColon, colon) = self.expect(.colon)
353348

354-
guard self.at(.leftParen) else {
349+
guard let leftParen = self.consume(if: .leftParen) else {
355350
// If no opening '(' for parameter list, parse a single parameter.
356351
let param = self.parseDifferentiabilityParameter().map(RawSyntax.init(_:))
357352
?? RawSyntax(RawMissingSyntax(arena: self.arena))
@@ -364,7 +359,6 @@ extension Parser {
364359
)
365360
}
366361

367-
let (unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
368362
var elements = [RawDifferentiabilityParamSyntax]()
369363
var loopProgress = LoopProgressCondition()
370364
while !self.at(.eof) && !self.at(.rightParen) && loopProgress.evaluate(currentToken) {
@@ -377,7 +371,6 @@ extension Parser {
377371

378372
let parameters = RawDifferentiabilityParamListSyntax(elements: elements, arena: self.arena)
379373
let list = RawDifferentiabilityParamsSyntax(
380-
unexpectedBeforeLeftParen,
381374
leftParen: leftParen,
382375
diffParams: parameters,
383376
unexpectedBeforeRightParen,
@@ -394,50 +387,59 @@ extension Parser {
394387
}
395388

396389
mutating func parseDifferentiabilityParameter() -> RawDifferentiabilityParamSyntax? {
397-
switch self.currentToken.tokenKind {
398-
case .identifier:
399-
let token = self.consumeIdentifier()
390+
enum ExpectedTokenKind: RawTokenKindSubset {
391+
case identifier
392+
case integerLiteral
393+
case selfKeyword
394+
395+
var rawTokenKind: RawTokenKind {
396+
switch self {
397+
case .identifier: return .identifier
398+
case .integerLiteral: return .integerLiteral
399+
case .selfKeyword: return .selfKeyword
400+
}
401+
}
402+
}
403+
404+
switch self.at(anyIn: ExpectedTokenKind.self) {
405+
case (.identifier, let handle)?:
406+
let token = self.eat(handle)
400407
let comma = self.consume(if: .comma)
401408
return RawDifferentiabilityParamSyntax(
402409
parameter: RawSyntax(token), trailingComma: comma, arena: self.arena)
403-
case .integerLiteral:
404-
let token = self.consumeAnyToken()
410+
case (.integerLiteral, let handle)?:
411+
let token = self.eat(handle)
405412
let comma = self.consume(if: .comma)
406413
return RawDifferentiabilityParamSyntax(
407414
parameter: RawSyntax(token), trailingComma: comma, arena: self.arena)
408-
case .selfKeyword:
409-
let (unexpectedBeforeToken, token) = self.eat(.selfKeyword)
415+
case (.selfKeyword, let handle)?:
416+
let token = self.eat(handle)
410417
let comma = self.consume(if: .comma)
411418
return RawDifferentiabilityParamSyntax(
412-
unexpectedBeforeToken,
413419
parameter: RawSyntax(token),
414420
trailingComma: comma,
415421
arena: self.arena
416422
)
417-
default:
423+
case nil:
418424
return nil
419425
}
420426
}
421427
}
422428

423429
extension Parser {
424430
mutating func parseObjectiveCAttribute() -> RawAttributeSyntax {
425-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
431+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
426432
assert(self.currentToken.tokenText == "objc")
427433
let objc = self.consumeAnyToken()
428434

429-
let unexpectedBeforeLeftParen: RawUnexpectedNodesSyntax?
430-
let leftParen: RawTokenSyntax?
435+
let leftParen = self.consume(if: .leftParen)
431436
let argument: RawObjCSelectorSyntax?
432437
let unexpectedBeforeRightParen: RawUnexpectedNodesSyntax?
433438
let rightParen: RawTokenSyntax?
434-
if self.at(.leftParen) {
435-
(unexpectedBeforeLeftParen, leftParen) = self.eat(.leftParen)
439+
if leftParen != nil {
436440
argument = self.parseObjectiveCSelector()
437441
(unexpectedBeforeRightParen, rightParen) = self.expect(.rightParen)
438442
} else {
439-
unexpectedBeforeLeftParen = nil
440-
leftParen = nil
441443
argument = nil
442444
unexpectedBeforeRightParen = nil
443445
rightParen = nil
@@ -447,7 +449,6 @@ extension Parser {
447449
unexpectedBeforeAtSign,
448450
atSignToken: atSign,
449451
attributeName: objc,
450-
unexpectedBeforeLeftParen,
451452
leftParen: leftParen,
452453
argument: argument.map(RawSyntax.init),
453454
unexpectedBeforeRightParen,
@@ -461,11 +462,9 @@ extension Parser {
461462
var loopProgress = LoopProgressCondition()
462463
while !self.at(.eof) && !self.at(.rightParen) && loopProgress.evaluate(currentToken) {
463464
// Empty selector piece.
464-
if self.at(.colon) {
465-
let (unexpectedBeforeColon, colon) = self.eat(.colon)
465+
if let colon = self.consume(if: .colon) {
466466
elements.append(RawObjCSelectorPieceSyntax(
467467
name: nil,
468-
unexpectedBeforeColon,
469468
colon: colon,
470469
arena: self.arena
471470
))
@@ -488,7 +487,7 @@ extension Parser {
488487

489488
extension Parser {
490489
mutating func parseSpecializeAttribute() -> RawAttributeSyntax {
491-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
490+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
492491
assert(self.currentToken.tokenText == "_specialize")
493492
let specializeToken = self.consumeAnyToken()
494493
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -673,7 +672,7 @@ extension Parser {
673672

674673
extension Parser {
675674
mutating func parsePrivateImportAttribute() -> RawAttributeSyntax {
676-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
675+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
677676
assert(self.currentToken.tokenText == "_private")
678677
let privateToken = self.consumeAnyToken()
679678
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -703,7 +702,7 @@ extension Parser {
703702

704703
extension Parser {
705704
mutating func parseDynamicReplacementAttribute() -> RawAttributeSyntax {
706-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
705+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
707706
assert(self.currentToken.tokenText == "_dynamicReplacement")
708707
let dynamicReplacementToken = self.consumeAnyToken()
709708
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)
@@ -741,7 +740,7 @@ extension Parser {
741740

742741
extension Parser {
743742
mutating func parseSPIAttribute() -> RawAttributeSyntax {
744-
let (unexpectedBeforeAtSign, atSign) = self.eat(.atSign)
743+
let (unexpectedBeforeAtSign, atSign) = self.expect(.atSign)
745744
assert(self.currentToken.tokenText == "_spi")
746745
let spiToken = self.consumeAnyToken()
747746
let (unexpectedBeforeLeftParen, leftParen) = self.expect(.leftParen)

Sources/SwiftParser/Availability.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,10 @@ extension Parser {
131131
))
132132
case .deprecated:
133133
let argumentLabel = self.consumeAnyToken()
134-
if self.at(.colon) {
135-
let (unexpectedBeforeColon, colon) = self.eat(.colon)
134+
if let colon = self.consume(if: .colon) {
136135
let version = self.parseVersionTuple()
137136
entry = RawSyntax(RawAvailabilityLabeledArgumentSyntax(
138137
label: argumentLabel,
139-
unexpectedBeforeColon,
140138
colon: colon,
141139
value: RawSyntax(version),
142140
arena: self.arena

0 commit comments

Comments
 (0)