@@ -1862,10 +1862,22 @@ parseStringSegments(SmallVectorImpl<Lexer::StringSegment> &Segments,
1862
1862
SyntaxParsingContext ExprContext (SyntaxContext,
1863
1863
SyntaxKind::ExpressionSegment);
1864
1864
1865
+ unsigned DelimiterLen = EntireTok.getCustomDelimiterLen ();
1866
+ bool HasCustomDelimiter = DelimiterLen > 0 ;
1867
+
1865
1868
// Backslash is part of an expression segment.
1866
- SourceLoc BackSlashLoc = Segment.Loc .getAdvancedLoc (-1 );
1869
+ SourceLoc BackSlashLoc = Segment.Loc .getAdvancedLoc (-1 - DelimiterLen );
1867
1870
Token BackSlash (tok::backslash, CharSourceRange (BackSlashLoc, 1 ).str ());
1868
1871
ExprContext.addToken (BackSlash, EmptyTrivia, EmptyTrivia);
1872
+
1873
+ // Custom delimiter may be a part of an expression segment.
1874
+ if (HasCustomDelimiter) {
1875
+ SourceLoc DelimiterLoc = Segment.Loc .getAdvancedLoc (-DelimiterLen);
1876
+ Token Delimiter (tok::raw_string_delimiter,
1877
+ CharSourceRange (DelimiterLoc, DelimiterLen).str ());
1878
+ ExprContext.addToken (Delimiter, EmptyTrivia, EmptyTrivia);
1879
+ }
1880
+
1869
1881
// Create a temporary lexer that lexes from the body of the string.
1870
1882
LexerState BeginState =
1871
1883
L->getStateForBeginningOfTokenLoc (Segment.Loc );
@@ -1948,51 +1960,70 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
1948
1960
SourceLoc Loc = Tok.getLoc ();
1949
1961
SourceLoc EndLoc = Loc.getAdvancedLoc (Tok.getLength ());
1950
1962
1951
- StringRef OpenQuoteStr, CloseQuoteStr;
1963
+ StringRef OpenDelimiterStr, OpenQuoteStr, CloseQuoteStr, CloseDelimiterStr;
1964
+ unsigned DelimiterLength = Tok.getCustomDelimiterLen ();
1965
+ bool HasCustomDelimiter = DelimiterLength > 0 ;
1966
+ unsigned QuoteLength;
1952
1967
tok QuoteKind;
1953
- std::tie (OpenQuoteStr, CloseQuoteStr, QuoteKind) = Tok.isMultilineString () ?
1954
- std::make_tuple (Tok.getRawText ().take_front (3 ),
1955
- Tok.getRawText ().take_back (3 ),
1956
- tok::multiline_string_quote) :
1957
- std::make_tuple (Tok.getRawText ().take_front (1 ),
1958
- Tok.getRawText ().take_back (1 ),
1959
- tok::string_quote);
1968
+ std::tie (QuoteLength, QuoteKind) =
1969
+ Tok.isMultilineString () ? std::make_tuple (3 , tok::multiline_string_quote)
1970
+ : std::make_tuple (1 , tok::string_quote);
1971
+ unsigned CloseQuoteBegin = Tok.getLength () - DelimiterLength - QuoteLength;
1972
+
1973
+ OpenDelimiterStr = Tok.getRawText ().take_front (DelimiterLength);
1974
+ OpenQuoteStr = Tok.getRawText ().substr (DelimiterLength, QuoteLength);
1975
+ CloseQuoteStr = Tok.getRawText ().substr (CloseQuoteBegin, QuoteLength);
1976
+ CloseDelimiterStr = Tok.getRawText ().take_back (DelimiterLength);
1960
1977
1961
1978
// Make unknown tokens to represent the open and close quote.
1962
1979
Token OpenQuote (QuoteKind, OpenQuoteStr);
1963
1980
Token CloseQuote (QuoteKind, CloseQuoteStr);
1964
1981
ParsedTrivia EmptyTrivia;
1965
1982
ParsedTrivia EntireTrailingTrivia = TrailingTrivia;
1966
1983
1967
- // Add the open quote to the context; the quote should have the leading trivia
1968
- // of the entire string token and a void trailing trivia.
1969
- SyntaxContext->addToken (OpenQuote, LeadingTrivia, EmptyTrivia);
1970
-
1984
+ if (HasCustomDelimiter) {
1985
+ Token OpenDelimiter (tok::raw_string_delimiter, OpenDelimiterStr);
1986
+ // When a custom delimiter is present, it owns the leading trivia.
1987
+ SyntaxContext->addToken (OpenDelimiter, LeadingTrivia, EmptyTrivia);
1988
+
1989
+ SyntaxContext->addToken (OpenQuote, EmptyTrivia, EmptyTrivia);
1990
+ } else {
1991
+ // Without custom delimiter the quote owns trailing trivia.
1992
+ SyntaxContext->addToken (OpenQuote, LeadingTrivia, EmptyTrivia);
1993
+ }
1994
+
1971
1995
// The simple case: just a single literal segment.
1972
1996
if (Segments.size () == 1 &&
1973
1997
Segments.front ().Kind == Lexer::StringSegment::Literal) {
1974
1998
{
1975
1999
consumeExtraToken (Tok);
1976
2000
consumeTokenWithoutFeedingReceiver ();
1977
-
2001
+
1978
2002
SyntaxParsingContext SegmentsCtx (SyntaxContext,
1979
2003
SyntaxKind::StringLiteralSegments);
1980
-
2004
+
1981
2005
SyntaxParsingContext StrSegContext (SyntaxContext,
1982
2006
SyntaxKind::StringSegment);
1983
-
2007
+
1984
2008
// Make an unknown token to encapsulate the entire string segment and add
1985
2009
// such token to the context.
1986
2010
auto Segment = Segments.front ();
1987
2011
Token content (tok::string_segment,
1988
2012
CharSourceRange (Segment.Loc , Segment.Length ).str ());
1989
2013
SyntaxContext->addToken (content, EmptyTrivia, EmptyTrivia);
1990
2014
}
1991
-
1992
- // Add the close quote the context; the quote should have a void leading trivia
1993
- // and the trailing trivia of the entire string token.
1994
- SyntaxContext->addToken (CloseQuote, EmptyTrivia, EntireTrailingTrivia);
1995
-
2015
+
2016
+ if (HasCustomDelimiter) {
2017
+ SyntaxContext->addToken (CloseQuote, EmptyTrivia, EmptyTrivia);
2018
+
2019
+ Token CloseDelimiter (tok::raw_string_delimiter, CloseDelimiterStr);
2020
+ // When a custom delimiter is present it owns the trailing trivia.
2021
+ SyntaxContext->addToken (CloseDelimiter, EmptyTrivia, EntireTrailingTrivia);
2022
+ } else {
2023
+ // Without custom delimiter the quote owns trailing trivia.
2024
+ SyntaxContext->addToken (CloseQuote, EmptyTrivia, EntireTrailingTrivia);
2025
+ }
2026
+
1996
2027
return makeParserResult (
1997
2028
createStringLiteralExprFromSegment (Context, L, Segments.front (), Loc));
1998
2029
}
@@ -2048,9 +2079,16 @@ ParserResult<Expr> Parser::parseExprStringLiteral() {
2048
2079
AppendingExpr = new (Context) TapExpr (nullptr , Body);
2049
2080
}
2050
2081
2051
- // Add the close quote the context; the quote should have a void leading trivia
2052
- // and the trailing trivia of the entire string token.
2053
- SyntaxContext->addToken (CloseQuote, EmptyTrivia, EntireTrailingTrivia);
2082
+ if (HasCustomDelimiter) {
2083
+ SyntaxContext->addToken (CloseQuote, EmptyTrivia, EmptyTrivia);
2084
+
2085
+ Token CloseDelimiter (tok::raw_string_delimiter, CloseDelimiterStr);
2086
+ // When a custom delimiter is present it owns the trailing trivia.
2087
+ SyntaxContext->addToken (CloseDelimiter, EmptyTrivia, EntireTrailingTrivia);
2088
+ } else {
2089
+ // Without custom delimiter the quote owns trailing trivia.
2090
+ SyntaxContext->addToken (CloseQuote, EmptyTrivia, EntireTrailingTrivia);
2091
+ }
2054
2092
2055
2093
if (AppendingExpr->getBody ()->getNumElements () == 1 ) {
2056
2094
Status.setIsParseError ();
0 commit comments