mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-22 03:02:06 +00:00
Allow trailing commas in bare lists
This applies to macro arguments, DB, DW, DL, DS, PRINT, PRINTLN, EXPORT, PURGE, and OPT. It also removes support for empty entries in DB/DW/DL. (Deprecating it would require keeping parser support, which is ambiguous with trailing commas.) Fixes #753
This commit is contained in:
@@ -360,7 +360,6 @@ struct LexerState {
|
||||
bool disableMacroArgs;
|
||||
bool disableInterpolation;
|
||||
size_t macroArgScanDistance; /* Max distance already scanned for macro args */
|
||||
bool injectNewline; /* Whether to inject a newline at EOF */
|
||||
bool expandStrings;
|
||||
struct Expansion *expansions;
|
||||
size_t expansionOfs; /* Offset into the current top-level expansion (negative = before) */
|
||||
@@ -382,7 +381,6 @@ static void initState(struct LexerState *state)
|
||||
state->disableMacroArgs = false;
|
||||
state->disableInterpolation = false;
|
||||
state->macroArgScanDistance = 0;
|
||||
state->injectNewline = false;
|
||||
state->expandStrings = true;
|
||||
state->expansions = NULL;
|
||||
state->expansionOfs = 0;
|
||||
@@ -640,11 +638,6 @@ void lexer_SetMode(enum LexerMode mode)
|
||||
lexerState->mode = mode;
|
||||
}
|
||||
|
||||
bool lexer_IsRawMode(void)
|
||||
{
|
||||
return lexerState->mode == LEXER_RAW;
|
||||
}
|
||||
|
||||
void lexer_ToggleStringExpansion(bool enable)
|
||||
{
|
||||
lexerState->expandStrings = enable;
|
||||
@@ -2054,10 +2047,6 @@ static int yylex_NORMAL(void)
|
||||
return T_NEWLINE;
|
||||
|
||||
case EOF:
|
||||
if (lexerState->injectNewline) {
|
||||
lexerState->injectNewline = false;
|
||||
return T_NEWLINE;
|
||||
}
|
||||
return T_EOF;
|
||||
|
||||
/* Handle escapes */
|
||||
@@ -2129,13 +2118,14 @@ static int yylex_RAW(void)
|
||||
|
||||
/* This is essentially a modified `appendStringLiteral` */
|
||||
size_t i = 0;
|
||||
int c;
|
||||
|
||||
/* Trim left whitespace (stops at a block comment or line continuation) */
|
||||
while (isWhitespace(peek(0)))
|
||||
shiftChars(1);
|
||||
|
||||
for (;;) {
|
||||
int c = peek(0);
|
||||
c = peek(0);
|
||||
|
||||
switch (c) {
|
||||
case '"': /* String literals inside macro args */
|
||||
@@ -2151,29 +2141,7 @@ static int yylex_RAW(void)
|
||||
case '\r':
|
||||
case '\n':
|
||||
case EOF:
|
||||
// Returning T_COMMAs to the parser would mean that two consecutive commas
|
||||
// (i.e. an empty argument) need to return two different tokens (T_STRING
|
||||
// then T_COMMA) without advancing the read. To avoid this, commas in raw
|
||||
// mode end the current macro argument but are not tokenized themselves.
|
||||
if (c == ',')
|
||||
shiftChars(1);
|
||||
else
|
||||
lexer_SetMode(LEXER_NORMAL);
|
||||
// If a macro is invoked on the last line of a file, with no blank
|
||||
// line afterwards, returning EOF afterwards will cause Bison to
|
||||
// stop parsing, despite the lexer being ready to output more.
|
||||
if (c == EOF)
|
||||
lexerState->injectNewline = true;
|
||||
/* Trim right whitespace */
|
||||
while (i && isWhitespace(yylval.tzString[i - 1]))
|
||||
i--;
|
||||
if (i == sizeof(yylval.tzString)) {
|
||||
i--;
|
||||
warning(WARNING_LONG_STR, "Macro argument too long\n");
|
||||
}
|
||||
yylval.tzString[i] = '\0';
|
||||
dbgPrint("Read raw string \"%s\"\n", yylval.tzString);
|
||||
return T_STRING;
|
||||
goto finish;
|
||||
|
||||
case '/': /* Block comments inside macro args */
|
||||
shiftChars(1); /* Shift the slash */
|
||||
@@ -2235,6 +2203,49 @@ static int yylex_RAW(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finish:
|
||||
if (i == sizeof(yylval.tzString)) {
|
||||
i--;
|
||||
warning(WARNING_LONG_STR, "Macro argument too long\n");
|
||||
}
|
||||
/* Trim right whitespace */
|
||||
while (i && isWhitespace(yylval.tzString[i - 1]))
|
||||
i--;
|
||||
yylval.tzString[i] = '\0';
|
||||
|
||||
dbgPrint("Read raw string \"%s\"\n", yylval.tzString);
|
||||
|
||||
// Returning T_COMMAs to the parser would mean that two consecutive commas
|
||||
// (i.e. an empty argument) need to return two different tokens (T_STRING
|
||||
// then T_COMMA) without advancing the read. To avoid this, commas in raw
|
||||
// mode end the current macro argument but are not tokenized themselves.
|
||||
if (c == ',') {
|
||||
shiftChars(1);
|
||||
return T_STRING;
|
||||
}
|
||||
|
||||
// The last argument may end in a trailing comma, newline, or EOF.
|
||||
// To allow trailing commas, raw mode will continue after the last
|
||||
// argument, immediately lexing the newline or EOF again (i.e. with
|
||||
// an empty raw string before it). This will not be treated as a
|
||||
// macro argument. To pass an empty last argument, use a second
|
||||
// trailing comma.
|
||||
if (i > 0)
|
||||
return T_STRING;
|
||||
lexer_SetMode(LEXER_NORMAL);
|
||||
|
||||
// If a macro is invoked on the last line of a file, with no blank
|
||||
// line afterwards, returning EOF afterwards will cause Bison to
|
||||
// stop parsing, despite the lexer being ready to output more.
|
||||
// To avoid this, return T_NEWLINE for EOF as well.
|
||||
if (c == '\r' || c == '\n') {
|
||||
shiftChars(1);
|
||||
/* Handle CRLF */
|
||||
if (c == '\r' && peek(0) == '\n')
|
||||
shiftChars(1);
|
||||
}
|
||||
return T_NEWLINE;
|
||||
}
|
||||
|
||||
#undef append_yylval_tzString
|
||||
|
||||
Reference in New Issue
Block a user