mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Implement 'character' literals (#1747)
This commit is contained in:
@@ -1428,6 +1428,7 @@ static void appendExpandedString(std::string &str, std::string const &expanded)
|
||||
break;
|
||||
case '\\':
|
||||
case '"':
|
||||
case '\'':
|
||||
case '{':
|
||||
str += '\\';
|
||||
[[fallthrough]];
|
||||
@@ -1448,6 +1449,7 @@ static void appendCharInLiteral(std::string &str, int c) {
|
||||
// Character escape
|
||||
case '\\':
|
||||
case '"':
|
||||
case '\'':
|
||||
case '{':
|
||||
case '}':
|
||||
if (rawMode) {
|
||||
@@ -1518,7 +1520,7 @@ static void appendCharInLiteral(std::string &str, int c) {
|
||||
break;
|
||||
|
||||
case '{': // Symbol interpolation
|
||||
// We'll be exiting the string scope, so re-enable expansions
|
||||
// We'll be exiting the string/character scope, so re-enable expansions
|
||||
// (Not interpolations, since they're handled by the function itself...)
|
||||
lexerState->disableMacroArgs = false;
|
||||
if (auto interpolation = readInterpolation(0); interpolation) {
|
||||
@@ -1614,6 +1616,42 @@ static void readString(std::string &str, bool rawString) {
|
||||
}
|
||||
}
|
||||
|
||||
static void readCharacter(std::string &str) {
|
||||
// This is essentially a simplified `readString`
|
||||
Defer reenableExpansions = scopedDisableExpansions();
|
||||
|
||||
bool rawMode = lexerState->mode == LEXER_RAW;
|
||||
|
||||
// We reach this function after reading a single quote
|
||||
if (rawMode) {
|
||||
str += '\'';
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int c = peek();
|
||||
|
||||
// '\r', '\n' or EOF ends a character early
|
||||
if (c == EOF || c == '\r' || c == '\n') {
|
||||
error("Unterminated character");
|
||||
return;
|
||||
}
|
||||
|
||||
// We'll be staying in the character, so we can safely consume the char
|
||||
shiftChar();
|
||||
|
||||
// Close the character and return if it's terminated
|
||||
if (c == '\'') {
|
||||
if (rawMode) {
|
||||
str += c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Append the character or handle special ones
|
||||
appendCharInLiteral(str, c);
|
||||
}
|
||||
}
|
||||
|
||||
// Lexer core
|
||||
|
||||
static Token yylex_SKIP_TO_ENDC(); // forward declaration for yylex_NORMAL
|
||||
@@ -1896,7 +1934,7 @@ static Token yylex_NORMAL() {
|
||||
case '`': // Gfx constant
|
||||
return Token(T_(NUMBER), readGfxConstant());
|
||||
|
||||
// Handle strings
|
||||
// Handle string and character literals
|
||||
|
||||
case '"': {
|
||||
std::string str;
|
||||
@@ -1904,6 +1942,12 @@ static Token yylex_NORMAL() {
|
||||
return Token(T_(STRING), str);
|
||||
}
|
||||
|
||||
case '\'': {
|
||||
std::string chr;
|
||||
readCharacter(chr);
|
||||
return Token(T_(CHARACTER), chr);
|
||||
}
|
||||
|
||||
// Handle newlines and EOF
|
||||
|
||||
case '\r':
|
||||
@@ -2036,6 +2080,11 @@ static Token yylex_RAW() {
|
||||
readString(str, false);
|
||||
break;
|
||||
|
||||
case '\'': // Character literals inside macro args
|
||||
shiftChar();
|
||||
readCharacter(str);
|
||||
break;
|
||||
|
||||
case '#': // Raw string literals inside macro args
|
||||
str += c;
|
||||
shiftChar();
|
||||
@@ -2093,6 +2142,7 @@ backslash:
|
||||
case ')':
|
||||
case '\\': // Escapes shared with string literals
|
||||
case '"':
|
||||
case '\'':
|
||||
case '{':
|
||||
case '}':
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user