Refactor lexer for inline ground

This commit is contained in:
2026-03-01 15:30:15 +11:00
parent 1ec55565d6
commit d7de6ae7ba

View File

@@ -15,6 +15,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
{"return", STT_KW_RETURN}, {"return", STT_KW_RETURN},
{"use", STT_KW_USE}, {"use", STT_KW_USE},
{"struct", STT_KW_STRUCT}, {"struct", STT_KW_STRUCT},
{"ground", STT_KW_GROUND},
{"{", STT_OPEN_CURLY}, {"{", STT_OPEN_CURLY},
{"}", STT_CLOSE_CURLY}, {"}", STT_CLOSE_CURLY},
{"(", STT_OPEN_PAREN}, {"(", STT_OPEN_PAREN},
@@ -74,6 +75,107 @@ ResultType(SolsTokenType, Nothing) getTokenType(const char* input) {
return Error(SolsTokenType, Nothing, {}); return Error(SolsTokenType, Nothing, {});
} }
static ResultType(Nothing, charptr) handleGround(SolsLexer* lexer, SolsToken* token, size_t* lineNum, Estr* currentLine, char currentChr, bool* skipDelimiter) {
bool foundBrace = false;
if (currentChr == '{') {
foundBrace = true;
*skipDelimiter = true;
} else {
while (true) {
ResultType(char, Nothing) peek = lexerPeek(lexer, 1);
if (peek.error) break;
if (isspace(peek.as.success)) {
char c = lexerConsume(lexer).as.success;
if (c == '\n') {
(*lineNum)++;
DESTROY_ESTR((*currentLine));
*currentLine = CREATE_ESTR("");
size_t lineStart = lexer->current;
for (size_t i = lineStart; i < lexer->inputsize; i++) {
if (lexer->input[i] == '\n') break;
char buf_tmp[] = {lexer->input[i], '\0'};
APPEND_ESTR((*currentLine), buf_tmp);
}
}
} else if (peek.as.success == '{') {
lexerConsume(lexer);
foundBrace = true;
break;
} else {
break;
}
}
}
if (!foundBrace) {
return Error(Nothing, charptr, "Expected '{' after 'ground'");
}
Estr groundBuf = CREATE_ESTR("");
int depth = 1;
while (depth > 0) {
ResultType(char, Nothing) next = lexerConsume(lexer);
if (next.error) {
DESTROY_ESTR(groundBuf);
return Error(Nothing, charptr, "Unterminated 'ground' block");
}
if (next.as.success == '{') depth++;
if (next.as.success == '}') {
depth--;
if (depth == 0) break;
}
char tmp[] = {next.as.success, '\0'};
APPEND_ESTR(groundBuf, tmp);
if (next.as.success == '\n') {
(*lineNum)++;
DESTROY_ESTR((*currentLine));
*currentLine = CREATE_ESTR("");
size_t lineStart = lexer->current;
for (size_t i = lineStart; i < lexer->inputsize; i++) {
if (lexer->input[i] == '\n') break;
char buf_tmp[] = {lexer->input[i], '\0'};
APPEND_ESTR((*currentLine), buf_tmp);
}
}
}
token->as.inlineGround = malloc(strlen(groundBuf.str) + 1);
if (token->as.inlineGround == NULL) {
DESTROY_ESTR(groundBuf);
return Error(Nothing, charptr, "Memory allocation failed (in handleGround() function)");
}
strcpy(token->as.inlineGround, groundBuf.str);
DESTROY_ESTR(groundBuf);
return Success(Nothing, charptr, {});
}
static ResultType(Nothing, charptr) identifyAndAdd(SolsLexer* lexer, Estr* buf, size_t* lineNum, Estr* currentLine, char currentChr, bool* skipDelimiter) {
if (strcmp(buf->str, "") == 0) return Success(Nothing, charptr, {});
ResultType(SolsToken, charptr) result = identifyToken(buf->str);
if (result.error) {
return Error(Nothing, charptr, result.as.error);
}
result.as.success.line.num = *lineNum;
result.as.success.line.content = malloc(strlen(currentLine->str) + 1);
if (result.as.success.line.content == NULL) {
return Error(Nothing, charptr, "Couldn't allocate memory to store line information in token (in identifyAndAdd() function)");
}
strcpy(result.as.success.line.content, currentLine->str);
if (result.as.success.type == STT_KW_GROUND) {
ResultType(Nothing, charptr) res = handleGround(lexer, &result.as.success, lineNum, currentLine, currentChr, skipDelimiter);
if (res.error) return res;
}
addTokenToSolsTokens(&lexer->output, result.as.success);
DESTROY_ESTR((*buf));
*buf = CREATE_ESTR("");
return Success(Nothing, charptr, {});
}
ResultType(SolsLexer, charptr) createLexer(char* input) { ResultType(SolsLexer, charptr) createLexer(char* input) {
@@ -386,6 +488,7 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
APPEND_ESTR(currentLine, tmp); APPEND_ESTR(currentLine, tmp);
} }
bool skipDelimiter = false;
for (;;) { for (;;) {
ResultType(char, Nothing) chr = lexerConsume(lexer); ResultType(char, Nothing) chr = lexerConsume(lexer);
@@ -393,6 +496,8 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
break; break;
} }
skipDelimiter = false;
if (chr.as.success == '/' && !inString) { if (chr.as.success == '/' && !inString) {
ResultType(char, Nothing) peek = lexerPeek(lexer, 1); ResultType(char, Nothing) peek = lexerPeek(lexer, 1);
if (!peek.error && peek.as.success == '/') { if (!peek.error && peek.as.success == '/') {
@@ -481,27 +586,16 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
case ';': case ';':
case '\n': case '\n':
{ {
if (strcmp(buf.str, "") != 0) { ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, &currentLine, chr.as.success, &skipDelimiter);
ResultType(SolsToken, charptr) result = identifyToken(buf.str); if (res.error) {
if (result.error) { char* err = createLexingError(lineNum, currentLine.str, res.as.error);
char* err = createLexingError(lineNum, currentLine.str, result.as.error);
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
result.as.success.line.num = lineNum;
result.as.success.line.content = malloc(strlen(currentLine.str) + 1);
if (result.as.success.line.content == NULL) {
char* err = createLexingError(lineNum, currentLine.str, "Couldn't allocate memory to store line information in token (in lex() function)");
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
strcpy(result.as.success.line.content, currentLine.str);
addTokenToSolsTokens(&lexer->output, result.as.success);
DESTROY_ESTR(buf); DESTROY_ESTR(buf);
buf = CREATE_ESTR(""); DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
} }
if (skipDelimiter) break;
char tmp[] = {chr.as.success, '\0'}; char tmp[] = {chr.as.success, '\0'};
ResultType(SolsToken, charptr) result = identifyToken(tmp); ResultType(SolsToken, charptr) result = identifyToken(tmp);
if (result.error) { if (result.error) {
@@ -527,27 +621,16 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
// These characters may be repeated, or followed by an equals sign. // These characters may be repeated, or followed by an equals sign.
case '+': case '+':
case '-': { case '-': {
if (strcmp(buf.str, "") != 0) { ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, &currentLine, chr.as.success, &skipDelimiter);
ResultType(SolsToken, charptr) result = identifyToken(buf.str); if (res.error) {
if (result.error) { char* err = createLexingError(lineNum, currentLine.str, res.as.error);
char* err = createLexingError(lineNum, currentLine.str, result.as.error);
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
result.as.success.line.num = lineNum;
result.as.success.line.content = malloc(strlen(currentLine.str) + 1);
if (result.as.success.line.content == NULL) {
char* err = createLexingError(lineNum, currentLine.str, "Couldn't allocate memory to store line information in token (in lex() function)");
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
strcpy(result.as.success.line.content, currentLine.str);
addTokenToSolsTokens(&lexer->output, result.as.success);
DESTROY_ESTR(buf); DESTROY_ESTR(buf);
buf = CREATE_ESTR(""); DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
} }
// skipDelimiter is unlikely here but handled just in case
if (skipDelimiter) break;
ResultType(char, Nothing) next = lexerPeek(lexer, 1); ResultType(char, Nothing) next = lexerPeek(lexer, 1);
if (next.error || (next.as.success != chr.as.success && next.as.success != '=')) { if (next.error || (next.as.success != chr.as.success && next.as.success != '=')) {
char tmp[] = {chr.as.success, '\0'}; char tmp[] = {chr.as.success, '\0'};
@@ -621,27 +704,15 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
case '<': case '<':
case '*': case '*':
case '/': { case '/': {
if (strcmp(buf.str, "") != 0) { ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, &currentLine, chr.as.success, &skipDelimiter);
ResultType(SolsToken, charptr) result = identifyToken(buf.str); if (res.error) {
if (result.error) { char* err = createLexingError(lineNum, currentLine.str, res.as.error);
char* err = createLexingError(lineNum, currentLine.str, result.as.error);
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
result.as.success.line.num = lineNum;
result.as.success.line.content = malloc(strlen(currentLine.str) + 1);
if (result.as.success.line.content == NULL) {
char* err = createLexingError(lineNum, currentLine.str, "Couldn't allocate memory to store line information in token (in lex() function)");
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
strcpy(result.as.success.line.content, currentLine.str);
addTokenToSolsTokens(&lexer->output, result.as.success);
DESTROY_ESTR(buf); DESTROY_ESTR(buf);
buf = CREATE_ESTR(""); DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
} }
if (skipDelimiter) break;
ResultType(char, Nothing) next = lexerPeek(lexer, 1); ResultType(char, Nothing) next = lexerPeek(lexer, 1);
if (next.error || next.as.success != '=') { if (next.error || next.as.success != '=') {
char tmp[] = {chr.as.success, '\0'}; char tmp[] = {chr.as.success, '\0'};
@@ -695,28 +766,16 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
if (!peek.error && isdigit(peek.as.success)) { if (!peek.error && isdigit(peek.as.success)) {
APPEND_ESTR(buf, "."); APPEND_ESTR(buf, ".");
} else { } else {
if (strcmp(buf.str, "") != 0) { ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, &currentLine, chr.as.success, &skipDelimiter);
ResultType(SolsToken, charptr) result = identifyToken(buf.str); if (res.error) {
if (result.error) { char* err = createLexingError(lineNum, currentLine.str, res.as.error);
char* err = createLexingError(lineNum, currentLine.str, result.as.error);
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
result.as.success.line.num = lineNum;
result.as.success.line.content = malloc(strlen(currentLine.str) + 1);
if (result.as.success.line.content == NULL) {
char* err = createLexingError(lineNum, currentLine.str, "Couldn't allocate memory to store line information in token (in lex() function)");
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
strcpy(result.as.success.line.content, currentLine.str);
addTokenToSolsTokens(&lexer->output, result.as.success);
DESTROY_ESTR(buf); DESTROY_ESTR(buf);
buf = CREATE_ESTR(""); DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
if (!skipDelimiter) {
addTokenToSolsTokens(&lexer->output, (SolsToken) {.type = STT_DOT});
} }
addTokenToSolsTokens(&lexer->output, (SolsToken) {.type = STT_DOT});
} }
break; break;
} }
@@ -724,26 +783,12 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
// This whitespace splits the program and does not get appended as it's own token. // This whitespace splits the program and does not get appended as it's own token.
case '\t': case '\t':
case ' ': { case ' ': {
if (strcmp(buf.str, "") != 0) { ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, &currentLine, chr.as.success, &skipDelimiter);
ResultType(SolsToken, charptr) result = identifyToken(buf.str); if (res.error) {
if (result.error) { char* err = createLexingError(lineNum, currentLine.str, res.as.error);
char* err = createLexingError(lineNum, currentLine.str, result.as.error);
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
result.as.success.line.num = lineNum;
result.as.success.line.content = malloc(strlen(currentLine.str) + 1);
if (result.as.success.line.content == NULL) {
char* err = createLexingError(lineNum, currentLine.str, "Couldn't allocate memory to store line information in token (in lex() function)");
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
strcpy(result.as.success.line.content, currentLine.str);
addTokenToSolsTokens(&lexer->output, result.as.success);
DESTROY_ESTR(buf); DESTROY_ESTR(buf);
buf = CREATE_ESTR(""); DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
} }
break; break;
} }
@@ -774,24 +819,12 @@ ResultType(Nothing, charptr) lex(SolsLexer* lexer) {
} }
} }
if (strcmp(buf.str, "") != 0) { ResultType(Nothing, charptr) res = identifyAndAdd(lexer, &buf, &lineNum, &currentLine, '\0', &skipDelimiter);
ResultType(SolsToken, charptr) result = identifyToken(buf.str); if (res.error) {
if (result.error) { char* err = createLexingError(lineNum, currentLine.str, res.as.error);
char* err = createLexingError(lineNum, currentLine.str, result.as.error); DESTROY_ESTR(buf);
DESTROY_ESTR(buf); DESTROY_ESTR(currentLine);
DESTROY_ESTR(currentLine); return Error(Nothing, charptr, err);
return Error(Nothing, charptr, err);
}
result.as.success.line.num = lineNum;
result.as.success.line.content = malloc(strlen(currentLine.str) + 1);
if (result.as.success.line.content == NULL) {
char* err = createLexingError(lineNum, currentLine.str, "Couldn't allocate memory to store line information in token (in lex() function)");
DESTROY_ESTR(buf);
DESTROY_ESTR(currentLine);
return Error(Nothing, charptr, err);
}
strcpy(result.as.success.line.content, currentLine.str);
addTokenToSolsTokens(&lexer->output, result.as.success);
} }
if (inString) { if (inString) {