hell yeah if statements
This commit is contained in:
parent
e9f6282446
commit
9ec709d4f2
|
@ -26,7 +26,7 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
|
||||||
|
|
||||||
// Collect tokens until semicolon
|
// Collect tokens until semicolon
|
||||||
while (auto nextToken = peek(1)) {
|
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
|
consume(); // consume the semicolon
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -123,21 +123,31 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
|
||||||
newToken.type = valtype::BOOL;
|
newToken.type = valtype::BOOL;
|
||||||
newToken.value.type = valtype::BOOL;
|
newToken.value.type = valtype::BOOL;
|
||||||
if (currentInstruction.size() < i + 1) syntaxError.mathTooFewArgs();
|
if (currentInstruction.size() < i + 1) syntaxError.mathTooFewArgs();
|
||||||
if (currentInstruction[i - 1].value.type != currentInstruction[i + 1].value.type) syntaxError.mathTypeMismatch();
|
if (currentInstruction[i - 1].type != currentInstruction[i + 1].type) syntaxError.mathTypeMismatch();
|
||||||
log.debug("Comparing stuff");
|
log.debug("Comparing values of type: " + to_string(static_cast<int>(currentInstruction[i - 1].type)));
|
||||||
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;
|
// Make sure both operands are values
|
||||||
else newToken.value.value = false;
|
if (currentInstruction[i - 1].keyword != keywords::VALUE ||
|
||||||
} else if (currentInstruction[i - 1].value.type == valtype::DEC) {
|
currentInstruction[i + 1].keyword != keywords::VALUE) {
|
||||||
if (get<double>(currentInstruction[i - 1].value.value) == get<double>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
|
syntaxError.generalError("Can only compare values");
|
||||||
else newToken.value.value = false;
|
return;
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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[i - 1] = newToken;
|
||||||
currentInstruction.erase(currentInstruction.begin() + i);
|
currentInstruction.erase(currentInstruction.begin() + i);
|
||||||
currentInstruction.erase(currentInstruction.begin() + i);
|
currentInstruction.erase(currentInstruction.begin() + i);
|
||||||
|
@ -153,6 +163,13 @@ void Interpreter::executeCode(vector<Token> tokens) {
|
||||||
SyntaxError syntaxError;
|
SyntaxError syntaxError;
|
||||||
log.debug("Token length for this expression is " + to_string(tokens.size()));
|
log.debug("Token length for this expression is " + to_string(tokens.size()));
|
||||||
for (int i = 0; i < tokens.size(); i++) {
|
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) {
|
if (tokens[i].keyword == keywords::PRINT) {
|
||||||
i++;
|
i++;
|
||||||
if (tokens.size() <= i) break;
|
if (tokens.size() <= i) break;
|
||||||
|
@ -160,21 +177,21 @@ void Interpreter::executeCode(vector<Token> tokens) {
|
||||||
// Handle different value types
|
// Handle different value types
|
||||||
if (nextToken.keyword == keywords::VALUE) {
|
if (nextToken.keyword == keywords::VALUE) {
|
||||||
switch (nextToken.type) {
|
switch (nextToken.type) {
|
||||||
case valtype::INT:
|
case valtype::INT:
|
||||||
cout << get<int>(nextToken.value.value) << endl;
|
cout << get<int>(nextToken.value.value) << endl;
|
||||||
break;
|
break;
|
||||||
case valtype::DEC:
|
case valtype::DEC:
|
||||||
cout << get<double>(nextToken.value.value) << endl;
|
cout << get<double>(nextToken.value.value) << endl;
|
||||||
break;
|
break;
|
||||||
case valtype::STR:
|
case valtype::STR:
|
||||||
cout << get<string>(nextToken.value.value) << endl;
|
cout << get<string>(nextToken.value.value) << endl;
|
||||||
break;
|
break;
|
||||||
case valtype::BOOL:
|
case valtype::BOOL:
|
||||||
cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl;
|
cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vector<string> validTypes = {"int", "dec", "str", "bool"};
|
vector<string> validTypes = {"int", "dec", "str", "bool"};
|
||||||
syntaxError.fnTypeMismatch("print", validTypes, nextToken.type);
|
syntaxError.fnTypeMismatch("print", validTypes, nextToken.type);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
syntaxError.fnNotSufficientArgs("print", 1, 1, 0);
|
syntaxError.fnNotSufficientArgs("print", 1, 1, 0);
|
||||||
|
@ -185,15 +202,15 @@ void Interpreter::executeCode(vector<Token> tokens) {
|
||||||
Token nextToken = tokens[i];
|
Token nextToken = tokens[i];
|
||||||
if (nextToken.keyword == keywords::VALUE) {
|
if (nextToken.keyword == keywords::VALUE) {
|
||||||
switch (nextToken.type) {
|
switch (nextToken.type) {
|
||||||
case valtype::INT:
|
case valtype::INT:
|
||||||
exit(get<int>(nextToken.value.value));
|
exit(get<int>(nextToken.value.value));
|
||||||
break;
|
break;
|
||||||
case valtype::DEC:
|
case valtype::DEC:
|
||||||
exit(get<double>(nextToken.value.value));
|
exit(get<double>(nextToken.value.value));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vector<string> validTypes = {"int", "dec"};
|
vector<string> validTypes = {"int", "dec"};
|
||||||
syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type);
|
syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (tokens[i].keyword == keywords::LET) {
|
} 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);
|
syntaxError.fnNotSufficientArgs("let", 3, 3, tokens.size() - i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token typeToken = tokens[i];
|
Token typeToken = tokens[i];
|
||||||
Token nameToken = tokens[i + 1];
|
Token nameToken = tokens[i + 1];
|
||||||
Token valueToken = tokens[i + 2];
|
Token valueToken = tokens[i + 2];
|
||||||
|
|
||||||
i += 2;
|
i += 2;
|
||||||
|
|
||||||
// Validate that we have a valid variable name
|
// Validate that we have a valid variable name
|
||||||
if (nameToken.type != valtype::STR) {
|
if (nameToken.type != valtype::STR) {
|
||||||
vector<string> validTypes = {"str"};
|
vector<string> validTypes = {"str"};
|
||||||
syntaxError.fnTypeMismatch("let (variable name)", validTypes, nameToken.type);
|
syntaxError.fnTypeMismatch("let (variable name)", validTypes, nameToken.type);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string varName = get<string>(nameToken.value.value);
|
string varName = get<string>(nameToken.value.value);
|
||||||
Value newValue;
|
Value newValue;
|
||||||
|
|
||||||
// Check the type declaration matches the value
|
// Check the type declaration matches the value
|
||||||
if (typeToken.keyword == keywords::INT && valueToken.type == valtype::INT) {
|
if (typeToken.keyword == keywords::INT && valueToken.type == valtype::INT) {
|
||||||
newValue.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);
|
syntaxError.fnTypeMismatch("let", validTypes, valueToken.type, "Variable name is " + varName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the variable
|
// Store the variable
|
||||||
variables[varName] = newValue;
|
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 {
|
} else {
|
||||||
if (tokens[i].keyword == keywords::VALUE && tokens[i].value.type == valtype::STR && variables.find(get<string>(tokens[i].value.value)) != variables.end()) {
|
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...");
|
log.debug("Manipulating variable...");
|
||||||
|
@ -300,7 +328,7 @@ void Interpreter::executeCode(vector<Token> tokens) {
|
||||||
syntaxError.mathCannotDoOperationOnType("unknown", "any");
|
syntaxError.mathCannotDoOperationOnType("unknown", "any");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
syntaxError.unknownFn();
|
if (tokens[i].keyword != keywords::CBRAC) syntaxError.unknownFn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
class Interpreter {
|
class Interpreter {
|
||||||
private:
|
private:
|
||||||
|
int skipScope = 0;
|
||||||
|
int repeatScope = 0;
|
||||||
SyntaxError syntaxError;
|
SyntaxError syntaxError;
|
||||||
vector<Token> tokens;
|
vector<Token> tokens;
|
||||||
map<string, Value> variables;
|
map<string, Value> variables;
|
||||||
|
|
|
@ -107,6 +107,8 @@ void Parser::processLines() {
|
||||||
else if (ct == "dec") token.keyword = keywords::DEC;
|
else if (ct == "dec") token.keyword = keywords::DEC;
|
||||||
else if (ct == "str") token.keyword = keywords::STR;
|
else if (ct == "str") token.keyword = keywords::STR;
|
||||||
else if (ct == "bool") token.keyword = keywords::BOOL;
|
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::OBRAC;
|
||||||
else if (ct == "}") token.keyword = keywords::CBRAC;
|
else if (ct == "}") token.keyword = keywords::CBRAC;
|
||||||
else if (ct == "(") token.keyword = keywords::OPARE;
|
else if (ct == "(") token.keyword = keywords::OPARE;
|
||||||
|
|
|
@ -55,4 +55,9 @@ void SyntaxError::generalError(string notes) {
|
||||||
void SyntaxError::cannotCompareDifferentTypes(string notes) {
|
void SyntaxError::cannotCompareDifferentTypes(string notes) {
|
||||||
cerr << "ComparisonError: cannot compare two different types" << endl;
|
cerr << "ComparisonError: cannot compare two different types" << endl;
|
||||||
if (!notes.empty()) cerr << "Notes: " << notes << 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;
|
||||||
}
|
}
|
|
@ -11,5 +11,6 @@ public:
|
||||||
void mathTooFewArgs(string notes = "");
|
void mathTooFewArgs(string notes = "");
|
||||||
void mathCannotDoOperationOnType(string operatorUsed, string type, string notes = "");
|
void mathCannotDoOperationOnType(string operatorUsed, string type, string notes = "");
|
||||||
void cannotCompareDifferentTypes(string notes = "");
|
void cannotCompareDifferentTypes(string notes = "");
|
||||||
|
void comparisonTypeError(string notes = "");
|
||||||
void generalError(string notes = "");
|
void generalError(string notes = "");
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user