@@ -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 ?
@@ -317,21 +320,25 @@ extension Lexer {
317320 /// If `tokenKind` is `.keyword`, the kind of keyword produced, otherwise
318321 /// `nil`.
319322 let keywordKind : Keyword ?
323+ /// Indicates whether the end of the lexed token text contains a newline.
324+ let trailingNewlinePresence : Lexer . Cursor . NewlinePresence
320325
321326 private init (
322327 _ tokenKind: RawTokenKind ,
323328 flags: Lexer . Lexeme . Flags ,
324329 error: Cursor . LexingDiagnostic ? ,
325330 stateTransition: StateTransition ? ,
326331 trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? ,
327- keywordKind: Keyword ?
332+ keywordKind: Keyword ? ,
333+ trailingNewlinePresence: Lexer . Cursor . NewlinePresence
328334 ) {
329335 self . tokenKind = tokenKind
330336 self . flags = flags
331337 self . error = error
332338 self . stateTransition = stateTransition
333339 self . trailingTriviaLexingMode = trailingTriviaLexingMode
334340 self . keywordKind = keywordKind
341+ self . trailingNewlinePresence = trailingNewlinePresence
335342 }
336343
337344 /// Create a lexer result. Note that keywords should use `Result.keyword`
@@ -341,7 +348,8 @@ extension Lexer {
341348 flags: Lexer . Lexeme . Flags = [ ] ,
342349 error: Cursor . LexingDiagnostic ? = nil ,
343350 stateTransition: StateTransition ? = nil ,
344- trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil
351+ trailingTriviaLexingMode: Lexer . Cursor . TriviaLexingMode ? = nil ,
352+ trailingNewlinePresence: Lexer . Cursor . NewlinePresence = . absent
345353 ) {
346354 precondition ( tokenKind != . keyword, " Use Result.keyword instead " )
347355 self . init (
@@ -350,7 +358,8 @@ extension Lexer {
350358 error: error,
351359 stateTransition: stateTransition,
352360 trailingTriviaLexingMode: trailingTriviaLexingMode,
353- keywordKind: nil
361+ keywordKind: nil ,
362+ trailingNewlinePresence: trailingNewlinePresence
354363 )
355364 }
356365
@@ -362,7 +371,8 @@ extension Lexer {
362371 error: nil ,
363372 stateTransition: nil ,
364373 trailingTriviaLexingMode: nil ,
365- keywordKind: kind
374+ keywordKind: kind,
375+ trailingNewlinePresence: . absent
366376 )
367377 }
368378 }
@@ -430,6 +440,16 @@ extension Lexer.Cursor {
430440 result = lexInRegexLiteral ( lexemes. pointee [ index... ] , existingPtr: lexemes)
431441 }
432442
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+
433453 if let stateTransition = result. stateTransition {
434454 self . stateStack. perform ( stateTransition: stateTransition, stateAllocator: stateAllocator)
435455 }
@@ -438,18 +458,14 @@ extension Lexer.Cursor {
438458 let trailingTriviaStart = self
439459 if let trailingTriviaMode = result. trailingTriviaLexingMode ?? currentState. trailingTriviaLexingMode ( cursor: self ) {
440460 let triviaResult = self . lexTrivia ( mode: trailingTriviaMode)
461+ self . previousLexemeTrailingNewlinePresence = triviaResult. newlinePresence
441462 diagnostic = TokenDiagnostic ( combining: diagnostic, triviaResult. error? . tokenDiagnostic ( tokenStart: cursor) )
442463 }
443464
444465 if self . currentState. shouldPopStateWhenReachingNewlineInTrailingTrivia && self . is ( at: " \r " , " \n " ) {
445466 self . stateStack. perform ( stateTransition: . pop, stateAllocator: stateAllocator)
446467 }
447468
448- var flags = result. flags
449- if newlineInLeadingTrivia == . present {
450- flags. insert ( . isAtStartOfLine)
451- }
452-
453469 diagnostic = TokenDiagnostic ( combining: diagnostic, result. error? . tokenDiagnostic ( tokenStart: cursor) )
454470
455471 let lexeme = Lexer . Lexeme (
@@ -1889,7 +1905,7 @@ extension Lexer.Cursor {
18891905 if character == UInt8 ( ascii: " \r " ) {
18901906 _ = self . advance ( matching: " \n " )
18911907 }
1892- return Lexer . Result ( . stringSegment, error: error)
1908+ return Lexer . Result ( . stringSegment, error: error, trailingNewlinePresence : . present )
18931909 } else {
18941910 // Single line literals cannot span multiple lines.
18951911 // Terminate the string here and go back to normal lexing (instead of `afterStringLiteral`)
0 commit comments