119 lines
4.2 KiB
C++
119 lines
4.2 KiB
C++
#include <vector>
|
|
#include <iostream>
|
|
#include <unordered_map>
|
|
#include <string>
|
|
#include "include/parser.h"
|
|
#include "include/interpreter.h"
|
|
using namespace std;
|
|
|
|
unordered_map<string, int> memory;
|
|
|
|
EvalResult eval(Node &ast) {
|
|
if (ast.index() == 0) {
|
|
InnerNode node = get<InnerNode>(ast);
|
|
switch (node.type) {
|
|
case NodeType::Prog:
|
|
eval(node.children[0]);
|
|
return eval(node.children[1]);
|
|
break;
|
|
case NodeType::Epsilon:
|
|
return {};
|
|
break;
|
|
case NodeType::Plus: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
int e2 = get<int>(eval(node.children[1]));
|
|
return e1 + e2;
|
|
} break;
|
|
case NodeType::Minus: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
int e2 = get<int>(eval(node.children[1]));
|
|
return e1 - e2;
|
|
} break;
|
|
case NodeType::Mult: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
int e2 = get<int>(eval(node.children[1]));
|
|
return e1 * e2;
|
|
} break;
|
|
case NodeType::Div: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
int e2 = get<int>(eval(node.children[1]));
|
|
if (e2 == 0) throw RuntimeError("Division by 0");
|
|
return e1 / e2;
|
|
} break;
|
|
case NodeType::Mod: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
int e2 = get<int>(eval(node.children[1]));
|
|
if (e2 == 0) throw RuntimeError("Modulo by 0");
|
|
return e1 % e2;
|
|
} break;
|
|
case NodeType::UnaryPlus: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
return +e1;
|
|
} break;
|
|
case NodeType::UnaryMinus: {
|
|
int e1 = get<int>(eval(node.children[0]));
|
|
return -e1;
|
|
} break;
|
|
case NodeType::Declaration: {
|
|
Token typeTok = get<Token>(node.children[0]);
|
|
Token identifierTok = get<Token>(node.children[1]);
|
|
string identifier = get<string>(identifierTok.data);
|
|
|
|
memory[identifier] = 0;
|
|
|
|
return {};
|
|
} break;
|
|
case NodeType::AssignedDeclaration: {
|
|
Token typeTok = get<Token>(node.children[0]);
|
|
Token identifierTok = get<Token>(node.children[1]);
|
|
string identifier = get<string>(identifierTok.data);
|
|
int expr = get<int>(eval(node.children[2]));
|
|
|
|
memory[identifier] = expr;
|
|
|
|
return expr;
|
|
} break;
|
|
case NodeType::Assignment: {
|
|
Token identifierTok = get<Token>(node.children[0]);
|
|
string identifier = get<string>(identifierTok.data);
|
|
int expr = get<int>(eval(node.children[1]));
|
|
|
|
memory[identifier] = expr;
|
|
|
|
return expr;
|
|
} break;
|
|
case NodeType::LIncr:
|
|
case NodeType::RIncr: {
|
|
Token identifierTok = get<Token>(node.children[0]);
|
|
string identifier = get<string>(identifierTok.data);
|
|
|
|
return node.type == NodeType::LIncr ? ++memory[identifier] : memory[identifier]++;
|
|
}
|
|
case NodeType::LDecr:
|
|
case NodeType::RDecr: {
|
|
Token identifierTok = get<Token>(node.children[0]);
|
|
string identifier = get<string>(identifierTok.data);
|
|
|
|
return node.type == NodeType::LDecr ? --memory[identifier] : memory[identifier]--;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Token token = get<Token>(ast);
|
|
switch (token.type) {
|
|
case TokenType::Int: {
|
|
return get<int>(token.data);
|
|
} break;
|
|
case TokenType::Identifier: {
|
|
string identifier = get<string>(token.data);
|
|
if (!memory.contains(identifier)) throw RuntimeError("Unknown identifier");
|
|
return memory[identifier];
|
|
} break;
|
|
default:
|
|
throw;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return {};
|
|
} |