@@ -243,6 +243,9 @@ extension Lexer {
243243 /// If we have already lexed a token, the kind of the previously lexed token
244244 var previousTokenKind : RawTokenKind ?
245245
246+ /// If we have already lexed a token, stores whether the previous lexeme‘s ending contains a newline.
247+ var previousLexemeTrailingNewlinePresence : NewlinePresence ?
248+
246249 /// If the `previousTokenKind` is `.keyword`, the keyword kind. Otherwise
247250 /// `nil`.
248251 var previousKeyword : Keyword ?
@@ -318,21 +321,25 @@ extension Lexer {
318321 /// If `tokenKind` is `.keyword`, the kind of keyword produced, otherwise
319322 /// `nil`.
320323 let keywordKind : Keyword ?
324+ /// Indicates whether the end of the lexed token text contains a newline.
325+ let trailingNewlinePresence : Lexer . Cursor . NewlinePresence
321326
322327 private init (
323328 _ tokenKind: RawTokenKind ,
324329 flags: Lexer . Lexeme . Flags ,
325330 error: Cursor . LexingDiagnostic ? ,
326331 stateTransition: StateTransition ? ,
327332 trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? ,
328- keywordKind: Keyword ?
333+ keywordKind: Keyword ? ,
334+ trailingNewlinePresence: Lexer . Cursor . NewlinePresence
329335 ) {
330336 self . tokenKind = tokenKind
331337 self . flags = flags
332338 self . error = error
333339 self . stateTransition = stateTransition
334340 self . trailingTriviaLexingMode = trailingTriviaLexingMode
335341 self . keywordKind = keywordKind
342+ self . trailingNewlinePresence = trailingNewlinePresence
336343 }
337344
338345 /// Create a lexer result. Note that keywords should use `Result.keyword`
@@ -342,7 +349,8 @@ extension Lexer {
342349 flags: Lexer . Lexeme . Flags = [ ] ,
343350 error: Cursor . LexingDiagnostic ? = nil ,
344351 stateTransition: StateTransition ? = nil ,
345- trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil
352+ trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil ,
353+ trailingNewlinePresence: Lexer . Cursor . NewlinePresence = . absent
346354 ) {
347355 precondition ( tokenKind != . keyword, " Use Result.keyword instead " )
348356 self . init (
@@ -351,7 +359,8 @@ extension Lexer {
351359 error: error,
352360 stateTransition: stateTransition,
353361 trailingTriviaLexingMode: trailingTriviaLexingMode,
354- keywordKind: nil
362+ keywordKind: nil ,
363+ trailingNewlinePresence: trailingNewlinePresence
355364 )
356365 }
357366
@@ -363,7 +372,8 @@ extension Lexer {
363372 error: nil ,
364373 stateTransition: nil ,
365374 trailingTriviaLexingMode: nil ,
366- keywordKind: kind
375+ keywordKind: kind,
376+ trailingNewlinePresence: . absent
367377 )
368378 }
369379 }
@@ -431,6 +441,16 @@ extension Lexer.Cursor {
431441 result = lexInRegexLiteral ( lexemes. pointee [ index... ] , existingPtr: lexemes)
432442 }
433443
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+
434454 if let stateTransition = result. stateTransition {
435455 self . stateStack. perform ( stateTransition: stateTransition, stateAllocator: stateAllocator)
436456 }
@@ -439,18 +459,14 @@ extension Lexer.Cursor {
439459 let trailingTriviaStart = self
440460 if let trailingTriviaMode = result. trailingTriviaLexingMode ?? currentState. trailingTriviaLexingMode ( cursor: self ) {
441461 let triviaResult = self . lexTrivia ( mode: trailingTriviaMode)
462+ self . previousLexemeTrailingNewlinePresence = triviaResult. newlinePresence
442463 diagnostic = TokenDiagnostic ( combining: diagnostic, triviaResult. error? . tokenDiagnostic ( tokenStart: cursor) )
443464 }
444465
445466 if self . currentState. shouldPopStateWhenReachingNewlineInTrailingTrivia && self . is ( at: " \r " , " \n " ) {
446467 self . stateStack. perform ( stateTransition: . pop, stateAllocator: stateAllocator)
447468 }
448469
449- var flags = result. flags
450- if newlineInLeadingTrivia == . present {
451- flags. insert ( . isAtStartOfLine)
452- }
453-
454470 diagnostic = TokenDiagnostic ( combining: diagnostic, result. error? . tokenDiagnostic ( tokenStart: cursor) )
455471
456472 let lexeme = Lexer . Lexeme (
@@ -1890,7 +1906,7 @@ extension Lexer.Cursor {
18901906 if character == UInt8 ( ascii: " \r " ) {
18911907 _ = self . advance ( matching: " \n " )
18921908 }
1893- return Lexer . Result ( . stringSegment, error: error)
1909+ return Lexer . Result ( . stringSegment, error: error, trailingNewlinePresence : . present )
18941910 } else {
18951911 // Single line literals cannot span multiple lines.
18961912 // Terminate the string here and go back to normal lexing (instead of `afterStringLiteral`)
0 commit comments