Support un-interpolated strings

This commit is contained in:
Kampfkarren 2022-07-27 18:10:06 -07:00
parent 8ef45854f7
commit 6e97add1ee
5 changed files with 10 additions and 51 deletions

View file

@ -84,9 +84,7 @@ struct Lexeme
BrokenString, BrokenString,
BrokenComment, BrokenComment,
BrokenUnicode, BrokenUnicode,
BrokenInterpDoubleBrace, BrokenInterpDoubleBrace,
BrokenInterpNoFormat,
Error, Error,
@ -219,7 +217,7 @@ private:
Lexeme readQuotedString(); Lexeme readQuotedString();
Lexeme readInterpolatedStringBegin(); Lexeme readInterpolatedStringBegin();
std::optional<Lexeme> readInterpolatedStringSection(Position start, Lexeme::Type formatType); Lexeme readInterpolatedStringSection(Position start, Lexeme::Type formatType, Lexeme::Type endType);
void readBackslashInString(); void readBackslashInString();

View file

@ -189,9 +189,6 @@ std::string Lexeme::toString() const
case BrokenInterpDoubleBrace: case BrokenInterpDoubleBrace:
return "'{{', which is invalid (did you mean '\\{'?)"; return "'{{', which is invalid (did you mean '\\{'?)";
case BrokenInterpNoFormat:
return "interpolated string with no formatting";
case BrokenUnicode: case BrokenUnicode:
if (codepoint) if (codepoint)
{ {
@ -595,15 +592,7 @@ const Lexeme Lexer::nextInterpolatedString()
Position start = position(); Position start = position();
unsigned int startOffset = offset; unsigned int startOffset = offset;
if (std::optional<Lexeme> readSection = readInterpolatedStringSection(start, Lexeme::InterpStringMid)) lexeme = readInterpolatedStringSection(start, Lexeme::InterpStringMid, Lexeme::InterpStringEnd);
{
lexeme = *readSection;
return lexeme;
}
consume();
lexeme = Lexeme(Location(start, position()), Lexeme::InterpStringEnd, &buffer[startOffset], offset - startOffset - 1);
return lexeme; return lexeme;
} }
@ -612,17 +601,10 @@ Lexeme Lexer::readInterpolatedStringBegin()
Position start = position(); Position start = position();
consume(); consume();
std::optional<Lexeme> readSectionOpt = readInterpolatedStringSection(start, Lexeme::InterpStringBegin); return readInterpolatedStringSection(start, Lexeme::InterpStringBegin, Lexeme::QuotedString);
if (!readSectionOpt)
{
return Lexeme(Location(start, position()), Lexeme::BrokenInterpNoFormat);
}
return *readSectionOpt;
} }
std::optional<Lexeme> Lexer::readInterpolatedStringSection(Position start, Lexeme::Type formatType) Lexeme Lexer::readInterpolatedStringSection(Position start, Lexeme::Type formatType, Lexeme::Type endType)
{ {
unsigned int startOffset = offset; unsigned int startOffset = offset;
@ -656,7 +638,8 @@ std::optional<Lexeme> Lexer::readInterpolatedStringSection(Position start, Lexem
} }
} }
return std::nullopt; consume();
return Lexeme(Location(start, position()), endType, &buffer[startOffset], offset - startOffset - 1);
} }
Lexeme Lexer::readNumber(const Position& start, unsigned int startOffset) Lexeme Lexer::readNumber(const Position& start, unsigned int startOffset)

View file

@ -2221,11 +2221,6 @@ AstExpr* Parser::parseSimpleExpr()
nextLexeme(); nextLexeme();
return reportExprError(start, {}, ERROR_INVALID_INTERP_DOUBLE_BRACE); return reportExprError(start, {}, ERROR_INVALID_INTERP_DOUBLE_BRACE);
} }
else if (lexer.current().type == Lexeme::BrokenInterpNoFormat)
{
nextLexeme();
return reportExprError(start, {}, "Interpolated strings must contain expressions, and cannot be constant");
}
else if (lexer.current().type == Lexeme::Dot3) else if (lexer.current().type == Lexeme::Dot3)
{ {
if (functionStack.back().vararg) if (functionStack.back().vararg)

View file

@ -1068,23 +1068,6 @@ TEST_CASE_FIXTURE(Fixture, "parse_interpolated_string_double_brace_mid")
} }
} }
TEST_CASE_FIXTURE(Fixture, "parse_interpolated_string_without_format")
{
ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true};
try
{
parse(R"(
_ = `doge`
)");
FAIL("Expected ParseErrors to be thrown");
}
catch (const ParseErrors& e)
{
CHECK_EQ("Interpolated strings must contain expressions, and cannot be constant", e.getErrors().front().getMessage());
}
}
TEST_CASE_FIXTURE(Fixture, "parse_interpolated_string_without_end_brace") TEST_CASE_FIXTURE(Fixture, "parse_interpolated_string_without_end_brace")
{ {
ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true}; ScopedFastFlag sff{"LuauInterpolatedStringBaseSupport", true};

View file

@ -31,10 +31,10 @@ assertEq(`This {localName} does not exist`, "This nil does not exist")
assertEq(`Welcome to \ assertEq(`Welcome to \
{name}!`, "Welcome to \nLuau!") {name}!`, "Welcome to \nLuau!")
assertEq(`Escaped brace: \{} ({1})`, "Escaped brace: {} (1)") assertEq(`Escaped brace: \{}`, "Escaped brace: {}")
assertEq(`Backslash \ that escapes the space is not a part of the string... ({2})`, "Backslash that escapes the space is not a part of the string... (2)") assertEq(`Backslash \ that escapes the space is not a part of the string...`, "Backslash that escapes the space is not a part of the string...")
assertEq(`Escaped backslash \\ ({3})`, "Escaped backslash \\ (3)") assertEq(`Escaped backslash \\`, "Escaped backslash \\")
assertEq(`Escaped backtick: \` ({4})`, "Escaped backtick: ` (4)") assertEq(`Escaped backtick: \``, "Escaped backtick: `")
assertEq(`Hello {`from inside {"a nested string"}`}`, "Hello from inside a nested string") assertEq(`Hello {`from inside {"a nested string"}`}`, "Hello from inside a nested string")