@@ -186,7 +186,7 @@ extension Parser {
186
186
var keepGoing : RawTokenSyntax ? = nil
187
187
var loopProgress = LoopProgressCondition ( )
188
188
repeat {
189
- let condition = self . parseConditionElement ( )
189
+ let condition = self . parseConditionElement ( lastBindingKind : elements . last ? . condition . as ( RawOptionalBindingConditionSyntax . self ) ? . bindingKeyword )
190
190
let unexpectedBeforeKeepGoing : RawUnexpectedNodesSyntax ?
191
191
keepGoing = self . consume ( if: . comma)
192
192
if keepGoing == nil , let andOperator = self . consumeIfContextualPunctuator ( " && " ) {
@@ -219,15 +219,16 @@ extension Parser {
219
219
/// optional-binding-condition → 'let' pattern initializer? | 'var' pattern initializer? |
220
220
/// 'inout' pattern initializer?
221
221
@_spi ( RawSyntax)
222
- public mutating func parseConditionElement( ) -> RawConditionElementSyntax . Condition {
222
+ /// `lastBindingKind` will be used to get a correct fall back, when there is missing `var` or `let` in a `if` statement etc.
223
+ public mutating func parseConditionElement( lastBindingKind: RawTokenSyntax ? ) -> RawConditionElementSyntax . Condition {
223
224
// Parse a leading #available/#unavailable condition if present.
224
225
if self . at ( . poundAvailableKeyword, . poundUnavailableKeyword) {
225
226
return self . parsePoundAvailableConditionElement ( )
226
227
}
227
228
228
229
// Parse the basic expression case. If we have a leading let, var, inout,
229
230
// borrow, case keyword or an assignment, then we know this is a binding.
230
- guard self . at ( . keyword( . let) , . keyword( . var) , . keyword( . case) ) || self . at ( . keyword( . inout) ) else {
231
+ guard self . at ( . keyword( . let) , . keyword( . var) , . keyword( . case) ) || self . at ( . keyword( . inout) ) || ( lastBindingKind != nil && self . peek ( ) . rawTokenKind == . equal ) else {
231
232
// If we lack it, then this is theoretically a boolean condition.
232
233
// However, we also need to handle migrating from Swift 2 syntax, in
233
234
// which a comma followed by an expression could actually be a pattern
@@ -244,20 +245,28 @@ extension Parser {
244
245
}
245
246
246
247
// We're parsing a conditional binding.
247
- precondition ( self . at ( . keyword( . let) , . keyword( . var) ) || self . at ( . keyword( . inout) , . keyword( . case) ) )
248
248
enum BindingKind {
249
249
case pattern( RawTokenSyntax , RawPatternSyntax )
250
- case optional( RawTokenSyntax , RawPatternSyntax )
250
+ case optional( RawUnexpectedNodesSyntax ? , RawTokenSyntax , RawPatternSyntax )
251
251
}
252
252
253
253
let kind : BindingKind
254
254
if let caseKeyword = self . consume ( if: . keyword( . case) ) {
255
255
let pattern = self . parseMatchingPattern ( context: . matching)
256
256
kind = . pattern( caseKeyword, pattern)
257
257
} else {
258
- let letOrVar = self . consumeAnyToken ( )
258
+ let unexpectedBeforeBindingKeyword : RawUnexpectedNodesSyntax ?
259
+ let letOrVar : RawTokenSyntax
260
+
261
+ if self . at ( . identifier) , let lastBindingKind = lastBindingKind {
262
+ ( unexpectedBeforeBindingKeyword, letOrVar) = self . expect ( . keyword( . let) , . keyword( . var) , default: . keyword( Keyword ( lastBindingKind. tokenText) ?? . let) )
263
+ } else {
264
+ letOrVar = self . consume ( if: TokenSpec . keyword ( . let) , . keyword( . var) ) ?? self . missingToken ( . let)
265
+ unexpectedBeforeBindingKeyword = nil
266
+ }
267
+
259
268
let pattern = self . parseMatchingPattern ( context: . bindingIntroducer)
260
- kind = . optional( letOrVar, pattern)
269
+ kind = . optional( unexpectedBeforeBindingKeyword , letOrVar, pattern)
261
270
}
262
271
263
272
// Now parse an optional type annotation.
@@ -289,9 +298,10 @@ extension Parser {
289
298
}
290
299
291
300
switch kind {
292
- case let . optional( bindingKeyword, pattern) :
301
+ case let . optional( unexpectedBeforeBindingKeyword , bindingKeyword, pattern) :
293
302
return . optionalBinding(
294
303
RawOptionalBindingConditionSyntax (
304
+ unexpectedBeforeBindingKeyword,
295
305
bindingKeyword: bindingKeyword,
296
306
pattern: pattern,
297
307
typeAnnotation: annotation,
0 commit comments