@@ -75,6 +75,22 @@ extension Parser.Lookahead {
75
75
self . consumeAnyToken ( )
76
76
}
77
77
78
+ /// Consume tokens of lower precedence than `kind` until reaching a token of that kind.
79
+ /// The token of `kind` is also consumed.
80
+ @_spi ( RawSyntax)
81
+ public mutating func consume( to kind: RawTokenKind ) {
82
+ if self . consume ( if: kind) != nil {
83
+ return
84
+ }
85
+ var lookahead = self . lookahead ( )
86
+ if lookahead. canRecoverTo ( [ kind] ) {
87
+ for _ in 0 ..< lookahead. tokensConsumed {
88
+ self . consumeAnyToken ( )
89
+ }
90
+ self . consumeAnyToken ( )
91
+ }
92
+ }
93
+
78
94
/// Consumes a given token, or splits the current token into a leading token
79
95
/// matching the given token and a trailing token and consumes the leading
80
96
/// token.
@@ -220,143 +236,6 @@ extension Parser.Lookahead {
220
236
" _opaqueReturnTypeOf " ,
221
237
]
222
238
223
- func isStartOfDeclaration( ) -> Bool {
224
- guard self . at ( anyIn: CanBeDeclaratinStart . self) != nil else {
225
- // If this is obviously not the start of a decl, then we're done.
226
- return false
227
- }
228
-
229
- /*
230
- // When 'init' appears inside another 'init', it's likely the user wants to
231
- // invoke an initializer but forgets to prefix it with 'self.' or 'super.'
232
- // Otherwise, expect 'init' to be the start of a declaration (and complain
233
- // when the expectation is not fulfilled).
234
- if (Tok.is(tok::kw_init)) {
235
- return !isa<ConstructorDecl>(CurDeclContext);
236
- }
237
- */
238
-
239
- // Similarly, when 'case' appears inside a function, it's probably a switch
240
- // case, not an enum case declaration.
241
- if self . at ( . caseKeyword) {
242
- return false
243
- }
244
-
245
- /*
246
- // The protocol keyword needs more checking to reject "protocol<Int>".
247
- if (Tok.is(tok::kw_protocol)) {
248
- const Token &Tok2 = peekToken();
249
- return !Tok2.isAnyOperator() || !Tok2.getText().equals("<");
250
- }
251
-
252
- // The 'try' case is only for simple local recovery, so we only bother to
253
- // check 'let' and 'var' right now.
254
- if (Tok.is(tok::kw_try))
255
- return peekToken().isAny(tok::kw_let, tok::kw_var);
256
- */
257
-
258
- // Skip an attribute, since it might be a type attribute. This can't
259
- // happen at the top level of a scope, but we do use isStartOfSwiftDecl()
260
- // in positions like generic argument lists.
261
- if self . at ( . atSign) {
262
- var subparser = self . lookahead ( )
263
- _ = subparser. eatParseAttributeList ( )
264
- // If this attribute is the last element in the block,
265
- // consider it is a start of incomplete decl.
266
- if subparser. at ( any: [ . rightBrace, . eof, . poundEndifKeyword] ) {
267
- return true
268
- }
269
- return subparser. isStartOfDeclaration ( )
270
- }
271
-
272
- // If we have a decl modifying keyword, check if the next token is a valid
273
- // decl start. This is necessary to correctly handle Swift keywords that are
274
- // shared by SIL, e.g 'private' in 'sil private @foo :'. We need to make sure
275
- // this isn't considered a valid Swift decl start.
276
- if self . currentToken. tokenKind. isKeyword {
277
- if self . at ( any: [ ] , contextualKeywords: Self . declAttributeNames) {
278
- var subparser = self . lookahead ( )
279
- subparser. consumeAnyToken ( )
280
-
281
- // Eat paren after modifier name; e.g. private(set)
282
- if subparser. consume ( if: . leftParen) != nil {
283
- while !subparser. at ( any: [ . eof, . rightBrace, . poundEndifKeyword] ) {
284
- if subparser. consume ( if: . rightParen) != nil {
285
- break
286
- }
287
-
288
- // If we found the start of a decl while trying to skip over the
289
- // paren, then we have something incomplete like 'private('. Return
290
- // true for better recovery.
291
- if subparser. isStartOfDeclaration ( ) {
292
- return true
293
- }
294
-
295
- subparser. consumeAnyToken ( )
296
- }
297
- }
298
- return subparser. isStartOfDeclaration ( )
299
- }
300
- }
301
-
302
- // Otherwise, the only hard case left is the identifier case.
303
- guard self . at ( . identifier) else {
304
- return true
305
- }
306
-
307
- // If this is an operator declaration, handle it.
308
- if case . operatorKeyword = self . peek ( ) . tokenKind,
309
- ( self . atContextualKeyword ( " prefix " ) ||
310
- self . atContextualKeyword ( " postfix " ) ||
311
- self . atContextualKeyword ( " infix " ) ) {
312
- return true
313
- }
314
-
315
- // If this can't possibly be a contextual keyword, then this identifier is
316
- // not interesting. Bail out.
317
- guard self . at ( anyIn: ContextualDeclKeyword . self) != nil else {
318
- return false
319
- }
320
-
321
- // If it might be, we do some more digging.
322
-
323
- // If this is 'unowned', check to see if it is valid.
324
- let tok2 = self . peek ( )
325
- if self . atContextualKeyword ( " unowned " ) && tok2. tokenKind == . leftParen &&
326
- self . isParenthesizedUnowned ( ) {
327
- var lookahead = self . lookahead ( )
328
- lookahead. expectIdentifierWithoutRecovery ( )
329
- lookahead. eat ( . leftParen)
330
- lookahead. expectIdentifierWithoutRecovery ( )
331
- lookahead. eat ( . rightParen)
332
- return lookahead. isStartOfDeclaration ( )
333
- }
334
-
335
- if self . atContextualKeyword ( " actor " ) {
336
- if tok2. tokenKind == . identifier {
337
- return true
338
- }
339
- // actor may be somewhere in the modifier list. Eat the tokens until we get
340
- // to something that isn't the start of a decl. If that is an identifier,
341
- // it's an actor declaration, otherwise, it isn't.
342
- var lookahead = self . lookahead ( )
343
- repeat {
344
- lookahead. consumeAnyToken ( )
345
- } while lookahead. isStartOfDeclaration ( )
346
- return lookahead. at ( . identifier)
347
- }
348
-
349
- // If the next token is obviously not the start of a decl, bail early.
350
- guard CanBeDeclaratinStart ( tok2) != nil else {
351
- return false
352
- }
353
-
354
- // Otherwise, do a recursive parse.
355
- var next = self . lookahead ( )
356
- next. expectIdentifierWithoutRecovery ( )
357
- return next. isStartOfDeclaration ( )
358
- }
359
-
360
239
func isParenthesizedUnowned( ) -> Bool {
361
240
assert ( self . atContextualKeyword ( " unowned " ) && self . peek ( ) . tokenKind == . leftParen,
362
241
" Invariant violated " )
0 commit comments