Issue #2121: Support new block string literal syntax in explorer (#2399)

This commit is contained in:
Priyananda Shenoy
2023-01-04 15:53:47 -08:00
committed by GitHub
parent 4daaa4866f
commit c87d271c53
14 changed files with 111 additions and 101 deletions
+53 -43
View File
@@ -308,29 +308,15 @@ operand_start [(A-Za-z0-9_\"]
return CARBON_ARG_TOKEN(integer_literal, val);
}
#*(\"\"\"|\") {
// Raw string literal.
// yytext (the token that matches the above regex) and chars scanned by
// str_lex_helper hold the source text, not the string the source represents.
#*\" {
// Found a double quote character.
Carbon::StringLexHelper str_lex_helper(yytext, yyscanner, context);
const std::string& s = str_lex_helper.str();
const int hashtag_num = s.find_first_of('"');
const int leading_quotes = s.size() - hashtag_num;
if (leading_quotes == 3 && hashtag_num > 0) {
// Check if it's a single-line string, like #"""#.
// TODO: Extend with other single-line string cases, like #""""#, based on
// the definition of block string in the design doc.
if (Carbon::ReadHashTags(str_lex_helper, hashtag_num)) {
return Carbon::ProcessSingleLineString(str_lex_helper.str(), context,
hashtag_num);
} else if (str_lex_helper.is_eof()) {
return CARBON_SIMPLE_TOKEN(END_OF_FILE);
}
} else if (!str_lex_helper.Advance()) {
if (!str_lex_helper.Advance()) {
return CARBON_SIMPLE_TOKEN(END_OF_FILE);
}
// 3 quotes indicates multi-line, otherwise it'll be one.
const bool multi_line = leading_quotes == 3;
while (!str_lex_helper.is_eof()) {
switch (str_lex_helper.last_char()) {
@@ -338,36 +324,60 @@ operand_start [(A-Za-z0-9_\"]
case '\v': // Fall through.
case '\f': // Fall through.
case '\r':
if (!multi_line) {
return context.RecordSyntaxError(
llvm::formatv("missing closing quote in single-line string: {0}",
str_lex_helper.str()));
}
str_lex_helper.Advance();
return context.RecordSyntaxError(
llvm::formatv("missing closing quote in single-line string: {0}",
str_lex_helper.str()));
break;
case '"':
if (multi_line) {
// Check for 2 more '"'s on block string.
if (!(str_lex_helper.Advance() &&
str_lex_helper.last_char() == '"')) {
continue;
}
if (!(str_lex_helper.Advance() &&
str_lex_helper.last_char() == '"')) {
continue;
}
// Now we are at the last " of """.
}
if (Carbon::ReadHashTags(str_lex_helper, hashtag_num)) {
// Reach closing quotes, break out of the loop.
if (leading_quotes == 3) {
return Carbon::ProcessMultiLineString(str_lex_helper.str(), context,
hashtag_num);
} else {
return Carbon::ProcessSingleLineString(str_lex_helper.str(),
context, hashtag_num);
return Carbon::ProcessSingleLineString(str_lex_helper.str(), context,
hashtag_num);
}
break;
case '\\':
if (Carbon::ReadHashTags(str_lex_helper, hashtag_num)) {
// Read the escaped char.
if (!str_lex_helper.Advance()) {
continue;
}
// Read the next char.
str_lex_helper.Advance();
}
break;
default:
str_lex_helper.Advance();
}
}
return CARBON_SIMPLE_TOKEN(END_OF_FILE);
}
#*\'\'\' {
// Multi-line string literal.
Carbon::StringLexHelper str_lex_helper(yytext, yyscanner, context);
const std::string& s = str_lex_helper.str();
const int hashtag_num = s.find_first_of('\'');
if (!str_lex_helper.Advance()) {
return CARBON_SIMPLE_TOKEN(END_OF_FILE);
}
while (!str_lex_helper.is_eof()) {
switch (str_lex_helper.last_char()) {
case '\'':
// Check for 2 more '\''s on block string.
if (!(str_lex_helper.Advance() && str_lex_helper.last_char() == '\'')) {
continue;
}
if (!(str_lex_helper.Advance() && str_lex_helper.last_char() == '\'')) {
continue;
}
// Now we are at the last ' of '''.
if (Carbon::ReadHashTags(str_lex_helper, hashtag_num)) {
// Reach closing quotes, break out of the loop.
return Carbon::ProcessMultiLineString(str_lex_helper.str(), context,
hashtag_num);
}
break;
case '\\':