@@ -147,7 +147,7 @@ extension Parser {
147147 return RawTokenSyntax (
148148 kind: token. tokenKind,
149149 text: SyntaxText ( rebasing: token. tokenText. dropFirst ( reclassifyLeading. count) . dropLast ( reclassifyTrailing. count) ) ,
150- leadingTriviaPieces: token. leadingTriviaPieces + TriviaParser. parseTrivia ( reclassifyLeading, position: . trailing ) ,
150+ leadingTriviaPieces: token. leadingTriviaPieces + TriviaParser. parseTrivia ( reclassifyLeading, position: . leading ) ,
151151 trailingTriviaPieces: TriviaParser . parseTrivia ( reclassifyTrailing, position: . trailing) + token. trailingTriviaPieces,
152152 presence: token. presence,
153153 tokenDiagnostic: token. tokenView. tokenDiagnostic ?? tokenDiagnostic,
@@ -595,10 +595,110 @@ extension Parser {
595595 )
596596 }
597597 }
598+
599+ mutating func parseSimpleString( ) -> RawSimpleStringLiteralExprSyntax {
600+ let openDelimiter = self . consume ( if: . rawStringPoundDelimiter)
601+ let ( unexpectedBeforeOpenQuote, openQuote) = self . expect ( anyIn: SimpleStringLiteralExprSyntax . OpeningQuoteOptions. self, default: . stringQuote)
602+
603+ /// Parse segments.
604+ var segments : [ RawStringSegmentSyntax ] = [ ]
605+ var loopProgress = LoopProgressCondition ( )
606+ while hasProgressed ( & loopProgress) {
607+ // If we encounter a token with leading trivia, we're no longer in the
608+ // string literal.
609+ guard currentToken. leadingTriviaText. isEmpty else { break }
610+
611+ if let stringSegment = self . consume ( if: . stringSegment, TokenSpec ( . identifier, remapping: . stringSegment) ) {
612+ var unexpectedAfterContent : RawUnexpectedNodesSyntax ?
613+
614+ if let ( backslash, leftParen) = self . consume ( if: . backslash, followedBy: . leftParen) {
615+ var unexpectedTokens : [ RawSyntax ] = [ RawSyntax ( backslash) , RawSyntax ( leftParen) ]
616+
617+ let ( unexpectedBeforeRightParen, rightParen) = self . expect ( TokenSpec ( . rightParen, allowAtStartOfLine: false ) )
618+ unexpectedTokens += unexpectedBeforeRightParen? . elements ?? [ ]
619+ unexpectedTokens. append ( RawSyntax ( rightParen) )
620+
621+ unexpectedAfterContent = RawUnexpectedNodesSyntax (
622+ unexpectedTokens,
623+ arena: self . arena
624+ )
625+ }
626+
627+ segments. append ( RawStringSegmentSyntax ( content: stringSegment, unexpectedAfterContent, arena: self . arena) )
628+ } else {
629+ break
630+ }
631+ }
632+
633+ let ( unexpectedBetweenSegmentAndCloseQuote, closeQuote) = self . expect (
634+ anyIn: SimpleStringLiteralExprSyntax . ClosingQuoteOptions. self,
635+ default: openQuote. closeTokenKind
636+ )
637+ let closeDelimiter = self . consume ( if: . rawStringPoundDelimiter)
638+
639+ if openQuote. tokenKind == . multilineStringQuote, !openQuote. isMissing, !closeQuote. isMissing {
640+ let postProcessed = postProcessMultilineStringLiteral (
641+ rawStringDelimitersToken: openDelimiter,
642+ openQuote: openQuote,
643+ segments: segments. compactMap { RawStringLiteralSegmentListSyntax . Element. stringSegment ( $0) } ,
644+ closeQuote: closeQuote
645+ )
646+
647+ return RawSimpleStringLiteralExprSyntax (
648+ RawUnexpectedNodesSyntax (
649+ combining: openDelimiter,
650+ unexpectedBeforeOpenQuote,
651+ postProcessed. unexpectedBeforeOpeningQuote,
652+ arena: self . arena
653+ ) ,
654+ openingQuote: postProcessed. openingQuote,
655+ segments: RawSimpleStringLiteralSegmentListSyntax (
656+ // `RawSimpleStringLiteralSegmentListSyntax` only accepts `RawStringSegmentSyntax`.
657+ // So we can safely cast.
658+ elements: postProcessed. segments. map { $0. cast ( RawStringSegmentSyntax . self) } ,
659+ arena: self . arena
660+ ) ,
661+ RawUnexpectedNodesSyntax (
662+ combining: unexpectedBetweenSegmentAndCloseQuote,
663+ postProcessed. unexpectedBeforeClosingQuote,
664+ arena: self . arena
665+ ) ,
666+ closingQuote: postProcessed. closingQuote,
667+ RawUnexpectedNodesSyntax (
668+ [ closeDelimiter] ,
669+ arena: self . arena
670+ ) ,
671+ arena: self . arena
672+ )
673+ } else {
674+ return RawSimpleStringLiteralExprSyntax (
675+ RawUnexpectedNodesSyntax ( combining: unexpectedBeforeOpenQuote, openDelimiter, arena: self . arena) ,
676+ openingQuote: openQuote,
677+ segments: RawSimpleStringLiteralSegmentListSyntax ( elements: segments, arena: self . arena) ,
678+ unexpectedBetweenSegmentAndCloseQuote,
679+ closingQuote: closeQuote,
680+ RawUnexpectedNodesSyntax ( [ closeDelimiter] , arena: self . arena) ,
681+ arena: self . arena
682+ )
683+ }
684+ }
598685}
599686
600687// MARK: - Utilities
601688
689+ fileprivate extension RawTokenSyntax {
690+ var closeTokenKind : SimpleStringLiteralExprSyntax . ClosingQuoteOptions {
691+ switch self {
692+ case . multilineStringQuote:
693+ return . multilineStringQuote
694+ case . stringQuote:
695+ return . stringQuote
696+ default :
697+ return . stringQuote
698+ }
699+ }
700+ }
701+
602702fileprivate extension SyntaxText {
603703 private func hasSuffix( _ other: String ) -> Bool {
604704 var other = other
0 commit comments