Implement SE-0200 (extended escaping in string literals)

Supports string literals like #"foo"\n"bar"#.
This commit is contained in:
John Holdsworth
2018-09-06 23:19:52 +01:00
committed by Brent Royal-Gordon
parent 5e2b705f6d
commit 4da8cbe655
9 changed files with 357 additions and 79 deletions

View File

@@ -364,12 +364,13 @@ public:
enum : char { Literal, Expr } Kind;
// Loc+Length for the segment inside the string literal, without quotes.
SourceLoc Loc;
unsigned Length, IndentToStrip;
unsigned Length, IndentToStrip, CustomDelimiterLen;
bool IsFirstSegment, IsLastSegment;
static StringSegment getLiteral(SourceLoc Loc, unsigned Length,
bool IsFirstSegment, bool IsLastSegment,
unsigned IndentToStrip) {
unsigned IndentToStrip,
unsigned CustomDelimiterLen) {
StringSegment Result;
Result.Kind = Literal;
Result.Loc = Loc;
@@ -377,6 +378,7 @@ public:
Result.IsFirstSegment = IsFirstSegment;
Result.IsLastSegment = IsLastSegment;
Result.IndentToStrip = IndentToStrip;
Result.CustomDelimiterLen = CustomDelimiterLen;
return Result;
}
@@ -388,6 +390,7 @@ public:
Result.IsFirstSegment = false;
Result.IsLastSegment = false;
Result.IndentToStrip = 0;
Result.CustomDelimiterLen = 0;
return Result;
}
@@ -404,13 +407,14 @@ public:
SmallVectorImpl<char> &Buffer,
bool IsFirstSegment = false,
bool IsLastSegment = false,
unsigned IndentToStrip = 0);
unsigned IndentToStrip = 0,
unsigned CustomDelimiterLen = 0);
StringRef getEncodedStringSegment(StringSegment Segment,
SmallVectorImpl<char> &Buffer) const {
return getEncodedStringSegment(
StringRef(getBufferPtrForSourceLoc(Segment.Loc), Segment.Length),
Buffer, Segment.IsFirstSegment, Segment.IsLastSegment,
Segment.IndentToStrip);
Segment.IndentToStrip, Segment.CustomDelimiterLen);
}
/// \brief Given a string literal token, separate it into string/expr segments
@@ -474,7 +478,8 @@ private:
return diagnose(Loc, Diagnostic(DiagID, std::forward<ArgTypes>(Args)...));
}
void formToken(tok Kind, const char *TokStart, bool MultilineString = false);
void formToken(tok Kind, const char *TokStart, bool IsMultilineString = false,
unsigned CustomDelimiterLen = 0);
void formEscapedIdentifierToken(const char *TokStart);
/// Advance to the end of the line.
@@ -498,10 +503,10 @@ private:
void lexTrivia(syntax::Trivia &T, bool IsForTrailingTrivia);
static unsigned lexUnicodeEscape(const char *&CurPtr, Lexer *Diags);
unsigned lexCharacter(const char *&CurPtr,
char StopQuote, bool EmitDiagnostics,
bool MultilineString = false);
void lexStringLiteral();
unsigned lexCharacter(const char *&CurPtr, char StopQuote,
bool EmitDiagnostics, bool IsMultilineString = false,
unsigned CustomDelimiterLen = 0);
void lexStringLiteral(unsigned CustomDelimiterLen = 0);
void lexEscapedIdentifier();
void tryLexEditorPlaceholder();

View File

@@ -45,7 +45,10 @@ class Token {
/// Modifiers for string literals
unsigned MultilineString : 1;
// Padding bits == 32 - sizeof(Kind) * 8 - 3;
/// Length of custom delimiter of "raw" string literals
unsigned CustomDelimiterLen : 8;
// Padding bits == 32 - 11;
/// \brief The length of the comment that precedes the token.
unsigned CommentLength;
@@ -62,8 +65,8 @@ class Token {
public:
Token(tok Kind, StringRef Text, unsigned CommentLength = 0)
: Kind(Kind), AtStartOfLine(false), EscapedIdentifier(false),
MultilineString(false), CommentLength(CommentLength),
Text(Text) {}
MultilineString(false), CustomDelimiterLen(0),
CommentLength(CommentLength), Text(Text) {}
Token() : Token(tok::NUM_TOKENS, {}, 0) {}
@@ -266,17 +269,24 @@ public:
/// \brief Set the token to the specified kind and source range.
void setToken(tok K, StringRef T, unsigned CommentLength = 0,
bool MultilineString = false) {
bool IsMultilineString = false, unsigned CustomDelimiterLen = 0) {
Kind = K;
Text = T;
this->CommentLength = CommentLength;
EscapedIdentifier = false;
this->MultilineString = MultilineString;
this->MultilineString = IsMultilineString;
this->CustomDelimiterLen = CustomDelimiterLen;
assert(this->CustomDelimiterLen == CustomDelimiterLen &&
"custom string delimiter length > 255");
}
bool IsMultilineString() const {
bool isMultilineString() const {
return MultilineString;
}
unsigned getCustomDelimiterLen() const {
return CustomDelimiterLen;
}
};
} // end namespace swift