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:
Rangi
2021-02-28 21:19:15 -05:00
committed by Eldred Habert
parent c637447d5d
commit 56071599e7
16 changed files with 155 additions and 153 deletions

View File

@@ -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