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