mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-22 11:12:07 +00:00
Implement macro args
This finally allows running 90% of the test suite, debugging time!
This commit is contained in:
112
src/asm/lexer.c
112
src/asm/lexer.c
@@ -373,7 +373,7 @@ struct LexerState *lexer_OpenFileView(char *buf, size_t size, uint32_t lineNo)
|
|||||||
struct LexerState *state = malloc(sizeof(*state));
|
struct LexerState *state = malloc(sizeof(*state));
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
error("Failed to allocate memory for lexer state: %s", strerror(errno));
|
error("Failed to allocate memory for lexer state: %s\n", strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// TODO: init `path`
|
// TODO: init `path`
|
||||||
@@ -1088,7 +1088,7 @@ static char const *readInterpolation(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
|
} else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
|
||||||
error("Unterminated interpolation\n");
|
error("Missing }\n");
|
||||||
break;
|
break;
|
||||||
} else if (c == '}') {
|
} else if (c == '}') {
|
||||||
shiftChars(1);
|
shiftChars(1);
|
||||||
@@ -1441,10 +1441,6 @@ static int yylex_NORMAL(void)
|
|||||||
shiftChars(1); /* Shift that EOL */
|
shiftChars(1); /* Shift that EOL */
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case '\n':
|
case '\n':
|
||||||
if (lexerStateEOL) {
|
|
||||||
lexer_SetState(lexerStateEOL);
|
|
||||||
lexerStateEOL = NULL;
|
|
||||||
}
|
|
||||||
return '\n';
|
return '\n';
|
||||||
|
|
||||||
case EOF:
|
case EOF:
|
||||||
@@ -1490,9 +1486,95 @@ static int yylex_NORMAL(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isWhitespace(int c)
|
||||||
|
{
|
||||||
|
return c == ' ' || c == '\t';
|
||||||
|
}
|
||||||
|
|
||||||
static int yylex_RAW(void)
|
static int yylex_RAW(void)
|
||||||
{
|
{
|
||||||
fatalerror("LEXER_RAW not yet implemented\n");
|
/* This is essentially a modified `readString` */
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
/* Trim left of string... */
|
||||||
|
while (isWhitespace(peek(0)))
|
||||||
|
shiftChars(1);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int c = peek(0);
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case ',':
|
||||||
|
shiftChars(1);
|
||||||
|
/* fallthrough */
|
||||||
|
case '\r':
|
||||||
|
case '\n': /* Do not shift these! */
|
||||||
|
case EOF:
|
||||||
|
if (c != ',')
|
||||||
|
lexer_SetMode(LEXER_NORMAL);
|
||||||
|
if (i == sizeof(yylval.tzString)) {
|
||||||
|
i--;
|
||||||
|
warning(WARNING_LONG_STR, "Macro argument too long\n");
|
||||||
|
}
|
||||||
|
/* Trim whitespace */
|
||||||
|
while (i && isWhitespace(yylval.tzString[i - 1]))
|
||||||
|
i--;
|
||||||
|
yylval.tzString[i] = '\0';
|
||||||
|
return T_STRING;
|
||||||
|
|
||||||
|
case '\\': /* Character escape */
|
||||||
|
c = peek(1);
|
||||||
|
switch (c) {
|
||||||
|
case ',':
|
||||||
|
case '\\': /* Return that character unchanged */
|
||||||
|
case '"':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
shiftChars(1);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
c = '\n';
|
||||||
|
shiftChars(1);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
c = '\r';
|
||||||
|
shiftChars(1);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
c = '\t';
|
||||||
|
shiftChars(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EOF: /* Can't really print that one */
|
||||||
|
error("Illegal character escape at end of input\n");
|
||||||
|
c = '\\';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Illegal character escape '%s'\n", print(c));
|
||||||
|
c = '\\';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '{': /* Symbol interpolation */
|
||||||
|
shiftChars(1);
|
||||||
|
char const *ptr = readInterpolation();
|
||||||
|
|
||||||
|
if (ptr) {
|
||||||
|
while (*ptr) {
|
||||||
|
if (i == sizeof(yylval.tzString))
|
||||||
|
break;
|
||||||
|
yylval.tzString[i++] = *ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; /* Do not copy an additional character */
|
||||||
|
|
||||||
|
/* Regular characters will just get copied */
|
||||||
|
}
|
||||||
|
if (i < sizeof(yylval.tzString)) /* Copy one extra to flag overflow */
|
||||||
|
yylval.tzString[i++] = c;
|
||||||
|
shiftChars(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1548,11 +1630,16 @@ static int yylex_SKIP_TO_ENDC(void)
|
|||||||
int yylex(void)
|
int yylex(void)
|
||||||
{
|
{
|
||||||
restart:
|
restart:
|
||||||
if (lexerState->atLineStart
|
if (lexerState->atLineStart) {
|
||||||
/* Newlines read within an expansion should not increase the line count */
|
/* Newlines read within an expansion should not increase the line count */
|
||||||
&& (!lexerState->expansions || lexerState->expansions->distance)) {
|
if (!lexerState->expansions || lexerState->expansions->distance) {
|
||||||
lexerState->lineNo++;
|
lexerState->lineNo++;
|
||||||
lexerState->colNo = 0;
|
lexerState->colNo = 0;
|
||||||
|
}
|
||||||
|
if (lexerStateEOL) {
|
||||||
|
lexer_SetState(lexerStateEOL);
|
||||||
|
lexerStateEOL = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int (* const lexerModeFuncs[])(void) = {
|
static int (* const lexerModeFuncs[])(void) = {
|
||||||
@@ -1572,6 +1659,7 @@ restart:
|
|||||||
if (!lexerState->capturing) {
|
if (!lexerState->capturing) {
|
||||||
if (!yywrap())
|
if (!yywrap())
|
||||||
goto restart;
|
goto restart;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user