@@ -335,9 +335,7 @@ extension Parser.Lookahead {
335
335
336
336
extension Parser . Lookahead {
337
337
mutating func skipUntil( _ t1: RawTokenKind , _ t2: RawTokenKind ) {
338
- while !self . at ( any: [ . eof, t1, t2, . poundEndifKeyword, . poundElseKeyword, . poundElseifKeyword] ) {
339
- self . skipSingle ( )
340
- }
338
+ return skip ( initialState: . skipUntil( t1, t2) )
341
339
}
342
340
343
341
mutating func skipUntilEndOfLine( ) {
@@ -347,70 +345,99 @@ extension Parser.Lookahead {
347
345
}
348
346
349
347
mutating func skipSingle( ) {
350
- enum BracketedTokens : RawTokenKindSubset {
351
- case leftParen
352
- case leftBrace
353
- case leftSquareBracket
354
- case poundIfKeyword
355
- case poundElseKeyword
356
- case poundElseifKeyword
357
-
358
- init ? ( lexeme: Lexer . Lexeme ) {
359
- switch lexeme. tokenKind {
360
- case . leftParen: self = . leftParen
361
- case . leftBrace: self = . leftBrace
362
- case . leftSquareBracket: self = . leftSquareBracket
363
- case . poundIfKeyword: self = . poundIfKeyword
364
- case . poundElseKeyword: self = . poundElseKeyword
365
- case . poundElseifKeyword: self = . poundElseifKeyword
366
- default : return nil
367
- }
348
+ return skip ( initialState: . skipSingle)
349
+ }
350
+
351
+ private enum BracketedTokens : RawTokenKindSubset {
352
+ case leftParen
353
+ case leftBrace
354
+ case leftSquareBracket
355
+ case poundIfKeyword
356
+ case poundElseKeyword
357
+ case poundElseifKeyword
358
+
359
+ init ? ( lexeme: Lexer . Lexeme ) {
360
+ switch lexeme. tokenKind {
361
+ case . leftParen: self = . leftParen
362
+ case . leftBrace: self = . leftBrace
363
+ case . leftSquareBracket: self = . leftSquareBracket
364
+ case . poundIfKeyword: self = . poundIfKeyword
365
+ case . poundElseKeyword: self = . poundElseKeyword
366
+ case . poundElseifKeyword: self = . poundElseifKeyword
367
+ default : return nil
368
368
}
369
+ }
369
370
370
- var rawTokenKind : RawTokenKind {
371
- switch self {
372
- case . leftParen: return . leftParen
373
- case . leftBrace: return . leftBrace
374
- case . leftSquareBracket: return . leftSquareBracket
375
- case . poundIfKeyword: return . poundIfKeyword
376
- case . poundElseKeyword: return . poundElseKeyword
377
- case . poundElseifKeyword: return . poundElseifKeyword
378
- }
371
+ var rawTokenKind : RawTokenKind {
372
+ switch self {
373
+ case . leftParen: return . leftParen
374
+ case . leftBrace: return . leftBrace
375
+ case . leftSquareBracket: return . leftSquareBracket
376
+ case . poundIfKeyword: return . poundIfKeyword
377
+ case . poundElseKeyword: return . poundElseKeyword
378
+ case . poundElseifKeyword: return . poundElseifKeyword
379
379
}
380
380
}
381
+ }
381
382
382
- switch self . at ( anyIn: BracketedTokens . self) {
383
- case ( . leftParen, let handle) ? :
384
- self . eat ( handle)
385
- self . skipUntil ( . rightParen, . rightBrace)
386
- self . consume ( if: . rightParen)
387
- return
388
- case ( . leftBrace, let handle) ? :
389
- self . eat ( handle)
390
- self . skipUntil ( . rightBrace, . rightBrace)
391
- self . consume ( if: . rightBrace)
392
- return
393
- case ( . leftSquareBracket, let handle) ? :
394
- self . eat ( handle)
395
- self . skipUntil ( . rightSquareBracket, . rightSquareBracket)
396
- self . consume ( if: . rightSquareBracket)
397
- return
398
- case ( . poundIfKeyword, let handle) ? ,
399
- ( . poundElseKeyword, let handle) ? ,
400
- ( . poundElseifKeyword, let handle) ? :
401
- self . eat ( handle)
402
- // skipUntil also implicitly stops at tok::pound_endif.
403
- self . skipUntil ( . poundElseKeyword, . poundElseifKeyword)
383
+ private enum SkippingState {
384
+ /// Equivalent to a call to `skipSingle`. Skip a single token.
385
+ /// If that token is bracketed, skip until the closing bracket
386
+ case skipSingle
387
+ /// Execute code after skipping bracketed tokens detected from `skipSingle`.
388
+ case skipSinglePost( start: BracketedTokens )
389
+ /// Skip until either `t1` or `t2`.
390
+ case skipUntil( _ t1: RawTokenKind , _ t2: RawTokenKind )
391
+ }
404
392
405
- if self . at ( any: [ . poundElseKeyword, . poundElseifKeyword] ) {
406
- self . skipSingle ( )
407
- } else {
408
- self . consume ( if: . poundElseifKeyword)
393
+ /// A non-recursie function to skip tokens.
394
+ private mutating func skip( initialState: SkippingState ) {
395
+ var stack : [ SkippingState ] = [ initialState]
396
+
397
+ while let state = stack. popLast ( ) {
398
+ switch state {
399
+ case . skipSingle:
400
+ let t = self . at ( anyIn: BracketedTokens . self)
401
+ switch t {
402
+ case ( . leftParen, let handle) ? :
403
+ self . eat ( handle)
404
+ stack += [ . skipSinglePost( start: . leftParen) , . skipUntil( . rightParen, . rightBrace) ]
405
+ case ( . leftBrace, let handle) ? :
406
+ self . eat ( handle)
407
+ stack += [ . skipSinglePost( start: . leftBrace) , . skipUntil( . rightBrace, . rightBrace) ]
408
+ case ( . leftSquareBracket, let handle) ? :
409
+ self . eat ( handle)
410
+ stack += [ . skipSinglePost( start: . leftSquareBracket) , . skipUntil( . rightSquareBracket, . rightSquareBracket) ]
411
+ case ( . poundIfKeyword, let handle) ? ,
412
+ ( . poundElseKeyword, let handle) ? ,
413
+ ( . poundElseifKeyword, let handle) ? :
414
+ self . eat ( handle)
415
+ // skipUntil also implicitly stops at tok::pound_endif.
416
+ stack += [ . skipSinglePost( start: t!. 0 ) , . skipUntil( . poundElseKeyword, . poundElseifKeyword) ]
417
+ case nil :
418
+ self . consumeAnyToken ( )
419
+ }
420
+ case . skipSinglePost( start: let start) :
421
+ switch start {
422
+ case . leftParen:
423
+ self . consume ( if: . rightParen)
424
+ case . leftBrace:
425
+ self . consume ( if: . rightBrace)
426
+ case . leftSquareBracket:
427
+ self . consume ( if: . rightSquareBracket)
428
+ case . poundIfKeyword, . poundElseKeyword, . poundElseifKeyword:
429
+ if self . at ( any: [ . poundElseKeyword, . poundElseifKeyword] ) {
430
+ stack += [ . skipSingle]
431
+ } else {
432
+ self . consume ( if: . poundElseifKeyword)
433
+ }
434
+ return
435
+ }
436
+ case . skipUntil( let t1, let t2) :
437
+ if !self . at ( any: [ . eof, t1, t2, . poundEndifKeyword, . poundElseKeyword, . poundElseifKeyword] ) {
438
+ stack += [ . skipUntil( t1, t2) , . skipSingle]
439
+ }
409
440
}
410
- return
411
- case nil :
412
- self . consumeAnyToken ( )
413
- return
414
441
}
415
442
}
416
443
}
0 commit comments