@@ -85,16 +85,29 @@ extension Parser {
85
85
arena: self . arena
86
86
)
87
87
)
88
- case ( . rhs, let handle) ? :
89
- let bindingSpecifier = self . eat ( handle)
90
- let value = self . parsePattern ( )
91
- return RawPatternSyntax (
92
- RawValueBindingPatternSyntax (
93
- bindingSpecifier: bindingSpecifier,
94
- pattern: value,
95
- arena: self . arena
88
+ case ( . rhs( let introducer) , let handle) ? :
89
+ var backtrack = self . lookahead ( )
90
+ if backtrack. shouldParsePatternBinding ( introducer: introducer) {
91
+ let bindingSpecifier = self . eat ( handle)
92
+ let value = self . parsePattern ( )
93
+ return RawPatternSyntax (
94
+ RawValueBindingPatternSyntax (
95
+ bindingSpecifier: bindingSpecifier,
96
+ pattern: value,
97
+ arena: self . arena
98
+ )
96
99
)
97
- )
100
+ } else {
101
+ // If we shouldn't contextually parse as a pattern binding introducer,
102
+ // then parse as an identifier.
103
+ let identifier = self . eat ( handle)
104
+ return RawPatternSyntax (
105
+ RawIdentifierPatternSyntax (
106
+ identifier: identifier,
107
+ arena: self . arena
108
+ )
109
+ )
110
+ }
98
111
case nil :
99
112
break
100
113
}
@@ -218,16 +231,19 @@ extension Parser {
218
231
arena: self . arena
219
232
)
220
233
)
221
- case ( . rhs, let handle) ? :
222
- let bindingSpecifier = self . eat ( handle)
223
- let value = self . parseMatchingPattern ( context: . bindingIntroducer)
224
- return RawPatternSyntax (
225
- RawValueBindingPatternSyntax (
226
- bindingSpecifier: bindingSpecifier,
227
- pattern: value,
228
- arena: self . arena
234
+ case ( . rhs( let introducer) , let handle) ? :
235
+ var backtrack = lookahead ( )
236
+ if backtrack. shouldParsePatternBinding ( introducer: introducer) {
237
+ let bindingSpecifier = self . eat ( handle)
238
+ let value = self . parseMatchingPattern ( context: . bindingIntroducer)
239
+ return RawPatternSyntax (
240
+ RawValueBindingPatternSyntax (
241
+ bindingSpecifier: bindingSpecifier,
242
+ pattern: value,
243
+ arena: self . arena
244
+ )
229
245
)
230
- )
246
+ }
231
247
case nil :
232
248
break
233
249
}
@@ -253,6 +269,21 @@ extension Parser {
253
269
// MARK: Lookahead
254
270
255
271
extension Parser . Lookahead {
272
+ /// Returns true if we should parse a pattern binding specifier contextually
273
+ /// as one.
274
+ mutating func shouldParsePatternBinding( introducer: ValueBindingPatternSyntax . BindingSpecifierOptions ) -> Bool {
275
+ switch introducer {
276
+ // TODO: the other ownership modifiers (borrowing/consuming/mutating) more
277
+ // than likely need to be made contextual as well before finalizing their
278
+ // grammar.
279
+ case . _borrowing where experimentalFeatures. contains ( . borrowingSwitch) :
280
+ return peek ( isAt: TokenSpec ( . identifier, allowAtStartOfLine: false ) )
281
+ default :
282
+ // Other keywords can be parsed unconditionally.
283
+ return true
284
+ }
285
+ }
286
+
256
287
/// pattern ::= identifier
257
288
/// pattern ::= '_'
258
289
/// pattern ::= pattern-tuple
@@ -294,9 +325,14 @@ extension Parser.Lookahead {
294
325
return true
295
326
case ( . lhs( . leftParen) , _) ? :
296
327
return self . canParsePatternTuple ( )
297
- case ( . rhs, let handle) ? :
298
- self . eat ( handle)
299
- return self . canParsePattern ( )
328
+ case ( . rhs( let introducer) , let handle) ? :
329
+ if shouldParsePatternBinding ( introducer: introducer) {
330
+ self . eat ( handle)
331
+ return self . canParsePattern ( )
332
+ } else {
333
+ self . eat ( handle)
334
+ return true
335
+ }
300
336
case nil :
301
337
return false
302
338
}
0 commit comments