@@ -243,6 +243,9 @@ extension Lexer {
243
243
/// If we have already lexed a token, the kind of the previously lexed token
244
244
var previousTokenKind : RawTokenKind ?
245
245
246
+ /// If we have already lexed a token, stores whether the previous lexeme‘s ending contains a newline.
247
+ var previousLexemeTrailingNewlinePresence : NewlinePresence ?
248
+
246
249
/// If the `previousTokenKind` is `.keyword`, the keyword kind. Otherwise
247
250
/// `nil`.
248
251
var previousKeyword : Keyword ?
@@ -317,21 +320,25 @@ extension Lexer {
317
320
/// If `tokenKind` is `.keyword`, the kind of keyword produced, otherwise
318
321
/// `nil`.
319
322
let keywordKind : Keyword ?
323
+ /// Indicates whether the end of the lexed token text contains a newline.
324
+ let trailingNewlinePresence : Lexer . Cursor . NewlinePresence
320
325
321
326
private init (
322
327
_ tokenKind: RawTokenKind ,
323
328
flags: Lexer . Lexeme . Flags ,
324
329
error: Cursor . LexingDiagnostic ? ,
325
330
stateTransition: StateTransition ? ,
326
331
trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? ,
327
- keywordKind: Keyword ?
332
+ keywordKind: Keyword ? ,
333
+ trailingNewlinePresence: Lexer . Cursor . NewlinePresence
328
334
) {
329
335
self . tokenKind = tokenKind
330
336
self . flags = flags
331
337
self . error = error
332
338
self . stateTransition = stateTransition
333
339
self . trailingTriviaLexingMode = trailingTriviaLexingMode
334
340
self . keywordKind = keywordKind
341
+ self . trailingNewlinePresence = trailingNewlinePresence
335
342
}
336
343
337
344
/// Create a lexer result. Note that keywords should use `Result.keyword`
@@ -341,7 +348,8 @@ extension Lexer {
341
348
flags: Lexer . Lexeme . Flags = [ ] ,
342
349
error: Cursor . LexingDiagnostic ? = nil ,
343
350
stateTransition: StateTransition ? = nil ,
344
- trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil
351
+ trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil ,
352
+ trailingNewlinePresence: Lexer . Cursor . NewlinePresence = . absent
345
353
) {
346
354
precondition ( tokenKind != . keyword, " Use Result.keyword instead " )
347
355
self . init (
@@ -350,7 +358,8 @@ extension Lexer {
350
358
error: error,
351
359
stateTransition: stateTransition,
352
360
trailingTriviaLexingMode: trailingTriviaLexingMode,
353
- keywordKind: nil
361
+ keywordKind: nil ,
362
+ trailingNewlinePresence: trailingNewlinePresence
354
363
)
355
364
}
356
365
@@ -362,7 +371,8 @@ extension Lexer {
362
371
error: nil ,
363
372
stateTransition: nil ,
364
373
trailingTriviaLexingMode: nil ,
365
- keywordKind: kind
374
+ keywordKind: kind,
375
+ trailingNewlinePresence: . absent
366
376
)
367
377
}
368
378
}
@@ -430,6 +440,16 @@ extension Lexer.Cursor {
430
440
result = lexInRegexLiteral ( lexemes. pointee [ index... ] , existingPtr: lexemes)
431
441
}
432
442
443
+ var flags = result. flags
444
+ if newlineInLeadingTrivia == . present {
445
+ flags. insert ( . isAtStartOfLine)
446
+ }
447
+ if let previousLexemeTrailingNewlinePresence, previousLexemeTrailingNewlinePresence == . present {
448
+ flags. insert ( . isAtStartOfLine)
449
+ }
450
+
451
+ self . previousLexemeTrailingNewlinePresence = result. trailingNewlinePresence
452
+
433
453
if let stateTransition = result. stateTransition {
434
454
self . stateStack. perform ( stateTransition: stateTransition, stateAllocator: stateAllocator)
435
455
}
@@ -438,18 +458,14 @@ extension Lexer.Cursor {
438
458
let trailingTriviaStart = self
439
459
if let trailingTriviaMode = result. trailingTriviaLexingMode ?? currentState. trailingTriviaLexingMode ( cursor: self ) {
440
460
let triviaResult = self . lexTrivia ( mode: trailingTriviaMode)
461
+ self . previousLexemeTrailingNewlinePresence = triviaResult. newlinePresence
441
462
diagnostic = TokenDiagnostic ( combining: diagnostic, triviaResult. error? . tokenDiagnostic ( tokenStart: cursor) )
442
463
}
443
464
444
465
if self . currentState. shouldPopStateWhenReachingNewlineInTrailingTrivia && self . is ( at: " \r " , " \n " ) {
445
466
self . stateStack. perform ( stateTransition: . pop, stateAllocator: stateAllocator)
446
467
}
447
468
448
- var flags = result. flags
449
- if newlineInLeadingTrivia == . present {
450
- flags. insert ( . isAtStartOfLine)
451
- }
452
-
453
469
diagnostic = TokenDiagnostic ( combining: diagnostic, result. error? . tokenDiagnostic ( tokenStart: cursor) )
454
470
455
471
let lexeme = Lexer . Lexeme (
@@ -1889,7 +1905,7 @@ extension Lexer.Cursor {
1889
1905
if character == UInt8 ( ascii: " \r " ) {
1890
1906
_ = self . advance ( matching: " \n " )
1891
1907
}
1892
- return Lexer . Result ( . stringSegment, error: error)
1908
+ return Lexer . Result ( . stringSegment, error: error, trailingNewlinePresence : . present )
1893
1909
} else {
1894
1910
// Single line literals cannot span multiple lines.
1895
1911
// Terminate the string here and go back to normal lexing (instead of `afterStringLiteral`)
0 commit comments