hell yeah if statements

This commit is contained in:
Maxwell 2025-04-26 20:46:32 +10:00
parent e9f6282446
commit 9ec709d4f2
6 changed files with 83 additions and 45 deletions

BIN
mx

Binary file not shown.

View File

@ -26,7 +26,7 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
// Collect tokens until semicolon
while (auto nextToken = peek(1)) {
if (nextToken->keyword == keywords::SEMICOLON) {
if (nextToken->keyword == keywords::SEMICOLON || nextToken->keyword == keywords::OBRAC || nextToken->keyword == keywords::CBRAC) {
consume(); // consume the semicolon
break;
}
@ -123,21 +123,31 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
newToken.type = valtype::BOOL;
newToken.value.type = valtype::BOOL;
if (currentInstruction.size() < i + 1) syntaxError.mathTooFewArgs();
if (currentInstruction[i - 1].value.type != currentInstruction[i + 1].value.type) syntaxError.mathTypeMismatch();
log.debug("Comparing stuff");
if (currentInstruction[i - 1].value.type == valtype::INT) {
if (get<int>(currentInstruction[i - 1].value.value) == get<int>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
else newToken.value.value = false;
} else if (currentInstruction[i - 1].value.type == valtype::DEC) {
if (get<double>(currentInstruction[i - 1].value.value) == get<double>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
else newToken.value.value = false;
} else if (currentInstruction[i - 1].value.type == valtype::STR) {
if (get<string>(currentInstruction[i - 1].value.value) == get<string>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
else newToken.value.value = false;
} else if (currentInstruction[i - 1].value.type == valtype::BOOL) {
if (get<bool>(currentInstruction[i - 1].value.value) == get<bool>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
else newToken.value.value = false;
if (currentInstruction[i - 1].type != currentInstruction[i + 1].type) syntaxError.mathTypeMismatch();
log.debug("Comparing values of type: " + to_string(static_cast<int>(currentInstruction[i - 1].type)));
// Make sure both operands are values
if (currentInstruction[i - 1].keyword != keywords::VALUE ||
currentInstruction[i + 1].keyword != keywords::VALUE) {
syntaxError.generalError("Can only compare values");
return;
}
// Ensure value types are set correctly
if (currentInstruction[i - 1].value.type == valtype::INT) {
newToken.value.value = (get<int>(currentInstruction[i - 1].value.value) ==
get<int>(currentInstruction[i + 1].value.value));
} else if (currentInstruction[i - 1].value.type == valtype::DEC) {
newToken.value.value = (get<double>(currentInstruction[i - 1].value.value) ==
get<double>(currentInstruction[i + 1].value.value));
} else if (currentInstruction[i - 1].value.type == valtype::STR) {
newToken.value.value = (get<string>(currentInstruction[i - 1].value.value) ==
get<string>(currentInstruction[i + 1].value.value));
} else if (currentInstruction[i - 1].value.type == valtype::BOOL) {
newToken.value.value = (get<bool>(currentInstruction[i - 1].value.value) ==
get<bool>(currentInstruction[i + 1].value.value));
}
currentInstruction[i - 1] = newToken;
currentInstruction.erase(currentInstruction.begin() + i);
currentInstruction.erase(currentInstruction.begin() + i);
@ -153,6 +163,13 @@ void Interpreter::executeCode(vector<Token> tokens) {
SyntaxError syntaxError;
log.debug("Token length for this expression is " + to_string(tokens.size()));
for (int i = 0; i < tokens.size(); i++) {
if (skipScope > 0) {
while (tokens[i].keyword != keywords::CBRAC) {
i++;
}
skipScope --;
return;
}
if (tokens[i].keyword == keywords::PRINT) {
i++;
if (tokens.size() <= i) break;
@ -160,21 +177,21 @@ void Interpreter::executeCode(vector<Token> tokens) {
// Handle different value types
if (nextToken.keyword == keywords::VALUE) {
switch (nextToken.type) {
case valtype::INT:
cout << get<int>(nextToken.value.value) << endl;
break;
case valtype::DEC:
cout << get<double>(nextToken.value.value) << endl;
break;
case valtype::STR:
cout << get<string>(nextToken.value.value) << endl;
break;
case valtype::BOOL:
cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl;
break;
default:
vector<string> validTypes = {"int", "dec", "str", "bool"};
syntaxError.fnTypeMismatch("print", validTypes, nextToken.type);
case valtype::INT:
cout << get<int>(nextToken.value.value) << endl;
break;
case valtype::DEC:
cout << get<double>(nextToken.value.value) << endl;
break;
case valtype::STR:
cout << get<string>(nextToken.value.value) << endl;
break;
case valtype::BOOL:
cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl;
break;
default:
vector<string> validTypes = {"int", "dec", "str", "bool"};
syntaxError.fnTypeMismatch("print", validTypes, nextToken.type);
}
} else {
syntaxError.fnNotSufficientArgs("print", 1, 1, 0);
@ -185,15 +202,15 @@ void Interpreter::executeCode(vector<Token> tokens) {
Token nextToken = tokens[i];
if (nextToken.keyword == keywords::VALUE) {
switch (nextToken.type) {
case valtype::INT:
exit(get<int>(nextToken.value.value));
break;
case valtype::DEC:
exit(get<double>(nextToken.value.value));
break;
default:
vector<string> validTypes = {"int", "dec"};
syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type);
case valtype::INT:
exit(get<int>(nextToken.value.value));
break;
case valtype::DEC:
exit(get<double>(nextToken.value.value));
break;
default:
vector<string> validTypes = {"int", "dec"};
syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type);
}
}
} else if (tokens[i].keyword == keywords::LET) {
@ -202,23 +219,23 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.fnNotSufficientArgs("let", 3, 3, tokens.size() - i);
break;
}
Token typeToken = tokens[i];
Token nameToken = tokens[i + 1];
Token valueToken = tokens[i + 2];
i += 2;
// Validate that we have a valid variable name
if (nameToken.type != valtype::STR) {
vector<string> validTypes = {"str"};
syntaxError.fnTypeMismatch("let (variable name)", validTypes, nameToken.type);
continue;
}
string varName = get<string>(nameToken.value.value);
Value newValue;
// Check the type declaration matches the value
if (typeToken.keyword == keywords::INT && valueToken.type == valtype::INT) {
newValue.type = valtype::INT;
@ -245,9 +262,20 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.fnTypeMismatch("let", validTypes, valueToken.type, "Variable name is " + varName);
continue;
}
// Store the variable
variables[varName] = newValue;
} else if (tokens[i].keyword == keywords::IF) {
i++;
if (tokens.size() < i) syntaxError.fnNotSufficientArgs("if", 1, 1, 0);
log.debug("IF statement token type: " + to_string(static_cast<int>(tokens[i].type)));
log.debug("IF statement token keyword: " + to_string(static_cast<int>(tokens[i].keyword)));
if (tokens[i].keyword != keywords::VALUE) syntaxError.generalError("if needs a value, not a keyword");
if (tokens[i].type != valtype::BOOL) syntaxError.comparisonTypeError("in an if statement");
if (!get<bool>(tokens[i].value.value)) {
skipScope ++;
return;
}
} else {
if (tokens[i].keyword == keywords::VALUE && tokens[i].value.type == valtype::STR && variables.find(get<string>(tokens[i].value.value)) != variables.end()) {
log.debug("Manipulating variable...");
@ -300,7 +328,7 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.mathCannotDoOperationOnType("unknown", "any");
}
} else {
syntaxError.unknownFn();
if (tokens[i].keyword != keywords::CBRAC) syntaxError.unknownFn();
}
}
}

View File

@ -6,6 +6,8 @@
class Interpreter {
private:
int skipScope = 0;
int repeatScope = 0;
SyntaxError syntaxError;
vector<Token> tokens;
map<string, Value> variables;

View File

@ -107,6 +107,8 @@ void Parser::processLines() {
else if (ct == "dec") token.keyword = keywords::DEC;
else if (ct == "str") token.keyword = keywords::STR;
else if (ct == "bool") token.keyword = keywords::BOOL;
else if (ct == "if") token.keyword = keywords::IF;
else if (ct == "while") token.keyword = keywords::WHILE;
else if (ct == "{") token.keyword = keywords::OBRAC;
else if (ct == "}") token.keyword = keywords::CBRAC;
else if (ct == "(") token.keyword = keywords::OPARE;

View File

@ -55,4 +55,9 @@ void SyntaxError::generalError(string notes) {
void SyntaxError::cannotCompareDifferentTypes(string notes) {
cerr << "ComparisonError: cannot compare two different types" << endl;
if (!notes.empty()) cerr << "Notes: " << notes << endl;
exit(1);
}
void SyntaxError::comparisonTypeError(string notes) {
cerr << "ComparisonError: cannot use a non-bool type in an if or while statement" << endl;
if (!notes.empty()) cerr << "Notes: " << notes << endl;
}

View File

@ -11,5 +11,6 @@ public:
void mathTooFewArgs(string notes = "");
void mathCannotDoOperationOnType(string operatorUsed, string type, string notes = "");
void cannotCompareDifferentTypes(string notes = "");
void comparisonTypeError(string notes = "");
void generalError(string notes = "");
};