Implement macro args

This finally allows running 90% of the test suite, debugging time!
This commit is contained in:
ISSOtm
2020-08-01 00:52:10 +02:00
parent e11f25024e
commit 6e805cd318

View File

@@ -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,12 +1630,17 @@ 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) = {
[LEXER_NORMAL] = yylex_NORMAL, [LEXER_NORMAL] = yylex_NORMAL,
@@ -1572,6 +1659,7 @@ restart:
if (!lexerState->capturing) { if (!lexerState->capturing) {
if (!yywrap()) if (!yywrap())
goto restart; goto restart;
return 0;
} }
} }
} }