|
|
|
|
@@ -3,6 +3,8 @@
|
|
|
|
|
#include "SolsToken.h"
|
|
|
|
|
#include "../include/error.h"
|
|
|
|
|
#include "../include/estr.h"
|
|
|
|
|
#include "../include/ansii.h"
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ResultType(SolsLexer, charptr) createLexer(char* input) {
|
|
|
|
|
@@ -48,10 +50,16 @@ ResultType(char, Nothing) lexerConsume(SolsLexer* lexer) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
|
|
|
|
printf("Passed token: '%s'\n", token);
|
|
|
|
|
// Process strings
|
|
|
|
|
if (token[0] == '"') {
|
|
|
|
|
if (token[strlen(token) - 1] == '"') {
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_STRING, token);
|
|
|
|
|
// Cut out the quotes
|
|
|
|
|
char* tokencopy = malloc(strlen(token) + 1);
|
|
|
|
|
strncpy(tokencopy, token + 1, strlen(token) - 2);
|
|
|
|
|
tokencopy[strlen(token) - 2] = '\0';
|
|
|
|
|
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_STRING, tokencopy);
|
|
|
|
|
free(tokencopy);
|
|
|
|
|
if (literal.error) {
|
|
|
|
|
Estr str = CREATE_ESTR(literal.as.error);
|
|
|
|
|
APPEND_ESTR(str, " (in identifyToken() function)");
|
|
|
|
|
@@ -59,12 +67,110 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
|
|
|
|
}
|
|
|
|
|
SolsToken tok = {
|
|
|
|
|
.type = STT_LITERAL,
|
|
|
|
|
.as.literal = literal.as.success
|
|
|
|
|
};
|
|
|
|
|
return Success(SolsToken, charptr, {STT_LITERAL});
|
|
|
|
|
return Success(SolsToken, charptr, tok);
|
|
|
|
|
}
|
|
|
|
|
return Error(SolsToken, charptr, "Unterminated string (in identifyToken() function)");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process characters
|
|
|
|
|
if (token[0] == '\'') {
|
|
|
|
|
if (strlen(token) != 3) {
|
|
|
|
|
return Error(SolsToken, charptr, "Characters can only hold one character at a time (try using \"this\" for strings?)");
|
|
|
|
|
}
|
|
|
|
|
if (token[2] == '\'') {
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_CHAR, token[1]);
|
|
|
|
|
if (literal.error) {
|
|
|
|
|
Estr str = CREATE_ESTR(literal.as.error);
|
|
|
|
|
APPEND_ESTR(str, " (in identifyToken() function)");
|
|
|
|
|
return Error(SolsToken, charptr, str.str);
|
|
|
|
|
}
|
|
|
|
|
SolsToken tok = {
|
|
|
|
|
.type = STT_LITERAL,
|
|
|
|
|
.as.literal = literal.as.success
|
|
|
|
|
};
|
|
|
|
|
return Success(SolsToken, charptr, tok);
|
|
|
|
|
} else {
|
|
|
|
|
return Error(SolsToken, charptr, "Unterminated character (in identifyToken() function)");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process integers and floats
|
|
|
|
|
if (isdigit(token[0]) || token[0] == '-') {
|
|
|
|
|
size_t len = strlen(token);
|
|
|
|
|
bool isInt = true;
|
|
|
|
|
bool isDouble = false;
|
|
|
|
|
for (size_t i = 1; i < len; i++) {
|
|
|
|
|
if (isInt && token[i] == '.') {
|
|
|
|
|
isInt = false;
|
|
|
|
|
isDouble = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!isdigit(token[i])) {
|
|
|
|
|
isInt = false;
|
|
|
|
|
isDouble = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (isInt) {
|
|
|
|
|
int64_t newInt = atoll(token);
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_INT, newInt);
|
|
|
|
|
if (literal.error) {
|
|
|
|
|
Estr str = CREATE_ESTR(literal.as.error);
|
|
|
|
|
APPEND_ESTR(str, " (in identifyToken() function)");
|
|
|
|
|
return Error(SolsToken, charptr, str.str);
|
|
|
|
|
}
|
|
|
|
|
SolsToken tok = {
|
|
|
|
|
.type = STT_LITERAL,
|
|
|
|
|
.as.literal = literal.as.success
|
|
|
|
|
};
|
|
|
|
|
return Success(SolsToken, charptr, tok);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isDouble) {
|
|
|
|
|
double newDouble = atof(token);
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_DOUBLE, newDouble);
|
|
|
|
|
if (literal.error) {
|
|
|
|
|
Estr str = CREATE_ESTR(literal.as.error);
|
|
|
|
|
APPEND_ESTR(str, " (in identifyToken() function)");
|
|
|
|
|
return Error(SolsToken, charptr, str.str);
|
|
|
|
|
}
|
|
|
|
|
SolsToken tok = {
|
|
|
|
|
.type = STT_LITERAL,
|
|
|
|
|
.as.literal = literal.as.success
|
|
|
|
|
};
|
|
|
|
|
return Success(SolsToken, charptr, tok);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle boolean (true/false)
|
|
|
|
|
if (strcmp(token, "true") == 0) {
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_BOOL, true);
|
|
|
|
|
if (literal.error) {
|
|
|
|
|
Estr str = CREATE_ESTR(literal.as.error);
|
|
|
|
|
APPEND_ESTR(str, " (in identifyToken() function)");
|
|
|
|
|
return Error(SolsToken, charptr, str.str);
|
|
|
|
|
}
|
|
|
|
|
SolsToken tok = {
|
|
|
|
|
.type = STT_LITERAL,
|
|
|
|
|
.as.literal = literal.as.success
|
|
|
|
|
};
|
|
|
|
|
return Success(SolsToken, charptr, tok);
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(token, "false") == 0) {
|
|
|
|
|
ResultType(SolsLiteral, charptr) literal = createSolsLiteral(SLT_BOOL, false);
|
|
|
|
|
if (literal.error) {
|
|
|
|
|
Estr str = CREATE_ESTR(literal.as.error);
|
|
|
|
|
APPEND_ESTR(str, " (in identifyToken() function)");
|
|
|
|
|
return Error(SolsToken, charptr, str.str);
|
|
|
|
|
}
|
|
|
|
|
SolsToken tok = {
|
|
|
|
|
.type = STT_LITERAL,
|
|
|
|
|
.as.literal = literal.as.success
|
|
|
|
|
};
|
|
|
|
|
return Success(SolsToken, charptr, tok);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FIXME do tihs better sometime
|
|
|
|
|
if (strcmp(token, "puts") == 0) {
|
|
|
|
|
return Success(SolsToken, charptr, {STT_KW_PUTS});
|
|
|
|
|
@@ -79,10 +185,10 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
|
|
|
|
return Success(SolsToken, charptr, {STT_KW_DEF});
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(token, "struct") == 0) {
|
|
|
|
|
return Success(SolsToken, charptr, {STT_KW_DEF});
|
|
|
|
|
return Success(SolsToken, charptr, {STT_KW_STRUCT});
|
|
|
|
|
}
|
|
|
|
|
// Shh, this is our little secret now
|
|
|
|
|
if (strcmp(token, "{") == 0 || strcmp(token, "then")) {
|
|
|
|
|
if (strcmp(token, "{") == 0 || strcmp(token, "then") == 0) {
|
|
|
|
|
return Success(SolsToken, charptr, {STT_OPEN_CURLY});
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(token, "}") == 0 || strcmp(token, "end") == 0) {
|
|
|
|
|
@@ -110,19 +216,30 @@ ResultType(SolsToken, charptr) identifyToken(const char* token) {
|
|
|
|
|
return Success(SolsToken, charptr, {STT_OP_SET});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Success(SolsToken, charptr, {STT_IDENTIFIER});
|
|
|
|
|
// No appropriate token found, it's an identifier (I hope)
|
|
|
|
|
SolsToken id = {
|
|
|
|
|
.type = STT_IDENTIFIER,
|
|
|
|
|
.as.idName = malloc(strlen(token) + 1)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (id.as.idName == NULL) {
|
|
|
|
|
return Error(SolsToken, charptr, "Couldn't allocate memory to copy string (in identifyToken() function)");
|
|
|
|
|
}
|
|
|
|
|
strcpy(id.as.idName, token);
|
|
|
|
|
|
|
|
|
|
return Success(SolsToken, charptr, id);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* createParsingError(size_t lineNum, char* line, char* why) {
|
|
|
|
|
Estr error = CREATE_ESTR("\e[0;34mParsing Error \e[0;36mon line ");
|
|
|
|
|
Estr error = CREATE_ESTR(ESC_RESET ESC_BOLD ESC_RED_FG "Lexing Error " ESC_RESET ESC_YELLOW_FG "on line ");
|
|
|
|
|
char buf[256];
|
|
|
|
|
snprintf(buf, sizeof(buf), "%zu", lineNum);
|
|
|
|
|
APPEND_ESTR(error, buf);
|
|
|
|
|
APPEND_ESTR(error, ":\n\n ");
|
|
|
|
|
APPEND_ESTR(error, ":\n\n" ESC_RESET ESC_BLUE_FG " ");
|
|
|
|
|
APPEND_ESTR(error, line);
|
|
|
|
|
APPEND_ESTR(error, "\n\n");
|
|
|
|
|
APPEND_ESTR(error, "-> ");
|
|
|
|
|
APPEND_ESTR(error, ESC_RESET ESC_MAGENTA_FG "-> ");
|
|
|
|
|
APPEND_ESTR(error, why);
|
|
|
|
|
APPEND_ESTR(error, "\n");
|
|
|
|
|
return error.str;
|
|
|
|
|
@@ -154,8 +271,8 @@ ResultType(voidptr, charptr) lex(SolsLexer* lexer) {
|
|
|
|
|
if (lexer->input[lineStart] == '\n') {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
char buf[] = {lexer->input[lineStart], '\0'};
|
|
|
|
|
APPEND_ESTR(currentLine, buf);
|
|
|
|
|
char tmp[] = {lexer->input[lineStart], '\0'};
|
|
|
|
|
APPEND_ESTR(currentLine, tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
@@ -191,6 +308,59 @@ ResultType(voidptr, charptr) lex(SolsLexer* lexer) {
|
|
|
|
|
APPEND_ESTR(buf, "\"");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These characters require themselves added seperately from the previous token.
|
|
|
|
|
case '{':
|
|
|
|
|
case '}':
|
|
|
|
|
case '(':
|
|
|
|
|
case ')':
|
|
|
|
|
case ',':
|
|
|
|
|
case ':':
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(buf.str, "") != 0) {
|
|
|
|
|
ResultType(SolsToken, charptr) result = identifyToken(buf.str);
|
|
|
|
|
if (result.error) {
|
|
|
|
|
return Error(voidptr, charptr, createParsingError(lineNum, currentLine.str, result.as.error));
|
|
|
|
|
}
|
|
|
|
|
addTokenToSolsTokens(&lexer->output, result.as.success);
|
|
|
|
|
DESTROY_ESTR(buf);
|
|
|
|
|
buf = CREATE_ESTR("");
|
|
|
|
|
}
|
|
|
|
|
char tmp[] = {chr.as.success, '\0'};
|
|
|
|
|
ResultType(SolsToken, charptr) result = identifyToken(tmp);
|
|
|
|
|
if (result.error) {
|
|
|
|
|
return Error(voidptr, charptr, createParsingError(lineNum, currentLine.str, result.as.error));
|
|
|
|
|
}
|
|
|
|
|
addTokenToSolsTokens(&lexer->output, result.as.success);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// '.' requires checking whether it's a number or an identifier after
|
|
|
|
|
case '.': {
|
|
|
|
|
ResultType(char, Nothing) peek = lexerPeek(lexer, 1);
|
|
|
|
|
if (peek.error) {
|
|
|
|
|
return Error(voidptr, charptr, createParsingError(lineNum, currentLine.str, "Expecting token after '.'"));
|
|
|
|
|
}
|
|
|
|
|
if (isdigit(peek.as.success)) {
|
|
|
|
|
char tmp[] = {peek.as.success, '\0'};
|
|
|
|
|
APPEND_ESTR(buf, tmp);
|
|
|
|
|
lexerConsume(lexer);
|
|
|
|
|
} else {
|
|
|
|
|
if (strcmp(buf.str, "") != 0) {
|
|
|
|
|
ResultType(SolsToken, charptr) result = identifyToken(buf.str);
|
|
|
|
|
if (result.error) {
|
|
|
|
|
return Error(voidptr, charptr, createParsingError(lineNum, currentLine.str, result.as.error));
|
|
|
|
|
}
|
|
|
|
|
addTokenToSolsTokens(&lexer->output, result.as.success);
|
|
|
|
|
DESTROY_ESTR(buf);
|
|
|
|
|
buf = CREATE_ESTR("");
|
|
|
|
|
}
|
|
|
|
|
addTokenToSolsTokens(&lexer->output, (SolsToken) {STT_DOT});
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This whitespace splits the program and does not get appended as it's own token.
|
|
|
|
|
case '\n':
|
|
|
|
|
case ' ': {
|
|
|
|
|
if (strcmp(buf.str, "") != 0) {
|
|
|
|
|
|