and now we have variables
This commit is contained in:
parent
da3d9a536b
commit
595aaca18e
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
.idea
|
||||
|
||||
main
|
||||
|
|
98
src/main.cpp
98
src/main.cpp
|
@ -20,8 +20,8 @@ enum class keywords {
|
|||
ADD, SUBTRACT, MULTIPLY, DIVIDE,
|
||||
EQUAL, INEQUAL, LESS, GREATER, EQLESS, EQGREATER,
|
||||
INCREMENT, DECREMENT,
|
||||
PRINT, INPUT, EXIT,
|
||||
VALUE, SEMICOLON
|
||||
PRINT, LET, INPUT, EXIT,
|
||||
VALUE, SEMICOLON, VARIABLE
|
||||
};
|
||||
|
||||
struct Value {
|
||||
|
@ -134,7 +134,7 @@ class Logger {
|
|||
class SyntaxError {
|
||||
private:
|
||||
public:
|
||||
void fnTypeMismatch(string function, vector<string> validTypes, valtype typeGiven) {
|
||||
void fnTypeMismatch(string function, vector<string> validTypes, valtype typeGiven, string notes = "") {
|
||||
cout << "TypeError: function type mismatch" << endl;
|
||||
cout << "Function '" << function << "' expected one of the following types: ";
|
||||
for (int i = 0; i < validTypes.size(); i++) {
|
||||
|
@ -148,6 +148,17 @@ class SyntaxError {
|
|||
else if (typeGiven == valtype::BOOL) cout << "bool";
|
||||
else cout << "unknown";
|
||||
cout << "' instead" << endl;
|
||||
if (!notes.empty()) cout << "Notes: " << notes << endl;
|
||||
exit(1);
|
||||
}
|
||||
void fnNotSufficientArgs(string function, int minArgs, int maxArgs, int argsGiven) {
|
||||
cout << "TypeError: function not sufficient arguments" << endl;
|
||||
cout << "Function '" << function << "' expected between " << minArgs << " and " << maxArgs << " arguments, got " << argsGiven << endl;
|
||||
exit(1);
|
||||
}
|
||||
void unknownFn() {
|
||||
cout << "TypeError: unknown function" << endl;
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -257,10 +268,14 @@ class Parser {
|
|||
if (ct == " ") continue;
|
||||
// Oh boy here we go
|
||||
else if (ct == "fun") token.keyword = keywords::FUN;
|
||||
else if (ct == "let") token.keyword = keywords::LET;
|
||||
else if (ct == "print") token.keyword = keywords::PRINT;
|
||||
else if (ct == "return") token.keyword = keywords::RETURN;
|
||||
else if (ct == "exit") token.keyword = keywords::EXIT;
|
||||
else if (ct == "int") token.keyword = keywords::INT;
|
||||
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 == "{") token.keyword = keywords::OBRAC;
|
||||
else if (ct == "}") token.keyword = keywords::CBRAC;
|
||||
else if (ct == "(") token.keyword = keywords::OPARE;
|
||||
|
@ -314,6 +329,7 @@ class Parser {
|
|||
class Interpreter {
|
||||
private:
|
||||
vector<Token> tokens;
|
||||
map<string, Value> variables;
|
||||
Logger log;
|
||||
int tokenIndex = -1;
|
||||
optional<Token> consume() {
|
||||
|
@ -348,6 +364,22 @@ class Interpreter {
|
|||
consume(); // consume the peeked token
|
||||
currentInstruction.push_back(nextToken.value());
|
||||
}
|
||||
// Apply variables to tokens
|
||||
for (int i = 0; i < currentInstruction.size(); i++) {
|
||||
if (currentInstruction[i].type == valtype::STR) {
|
||||
string potentialVarName = get<string>(currentInstruction[i].value.value);
|
||||
auto varIt = variables.find(potentialVarName);
|
||||
|
||||
if (varIt != variables.end()) {
|
||||
// Replace the token with the variable's value
|
||||
Token newToken;
|
||||
newToken.keyword = keywords::VALUE;
|
||||
newToken.type = varIt->second.type;
|
||||
newToken.value = varIt->second;
|
||||
currentInstruction[i] = newToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Execute the instruction
|
||||
executeCode(currentInstruction);
|
||||
}
|
||||
|
@ -375,10 +407,11 @@ class Interpreter {
|
|||
cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl;
|
||||
break;
|
||||
default:
|
||||
log.error("Unsupported value type");
|
||||
vector<string> validTypes = {"int", "dec", "str", "bool"};
|
||||
syntaxError.fnTypeMismatch("print", validTypes, nextToken.type);
|
||||
}
|
||||
} else {
|
||||
log.error("Expected a value after print statement");
|
||||
syntaxError.fnNotSufficientArgs("print", 1, 1, 0);
|
||||
}
|
||||
} else if (tokens[i].keyword == keywords::EXIT) {
|
||||
i++;
|
||||
|
@ -397,6 +430,61 @@ class Interpreter {
|
|||
syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type);
|
||||
}
|
||||
}
|
||||
} else if (tokens[i].keyword == keywords::LET) {
|
||||
i++;
|
||||
if (tokens.size() <= i + 2) {
|
||||
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;
|
||||
newValue.value = get<int>(valueToken.value.value);
|
||||
}
|
||||
else if (typeToken.keyword == keywords::DEC && valueToken.type == valtype::DEC) {
|
||||
newValue.type = valtype::DEC;
|
||||
newValue.value = get<double>(valueToken.value.value);
|
||||
}
|
||||
else if (typeToken.keyword == keywords::STR && valueToken.type == valtype::STR) {
|
||||
newValue.type = valtype::STR;
|
||||
newValue.value = get<string>(valueToken.value.value);
|
||||
}
|
||||
else if (typeToken.keyword == keywords::BOOL && valueToken.type == valtype::BOOL) {
|
||||
newValue.type = valtype::BOOL;
|
||||
newValue.value = get<bool>(valueToken.value.value);
|
||||
}
|
||||
else {
|
||||
vector<string> validTypes;
|
||||
if (typeToken.keyword == keywords::INT) validTypes = {"int"};
|
||||
else if (typeToken.keyword == keywords::DEC) validTypes = {"dec"};
|
||||
else if (typeToken.keyword == keywords::STR) validTypes = {"str"};
|
||||
else if (typeToken.keyword == keywords::BOOL) validTypes = {"bool"};
|
||||
syntaxError.fnTypeMismatch("let", validTypes, valueToken.type, "Variable name is " + varName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store the variable
|
||||
variables[varName] = newValue;
|
||||
}
|
||||
else {
|
||||
syntaxError.unknownFn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user