229 lines
6.9 KiB
C++
229 lines
6.9 KiB
C++
#include "defs.h"
|
|
#include "../error/error.h"
|
|
#include <vector>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <utility>
|
|
#include "../datatypes/lists.h"
|
|
|
|
InstructionType strToInstructionType(std::string in) {
|
|
if (in == "println") return InstructionType::Println;
|
|
else if (in == "print") return InstructionType::Print;
|
|
else if (in == "math") return InstructionType::Math;
|
|
else if (in == "let") return InstructionType::Let;
|
|
else if (in == "exit") return InstructionType::Exit;
|
|
else if (in == "if") return InstructionType::If;
|
|
else if (in == "while") return InstructionType::While;
|
|
else if (in == "compare") return InstructionType::Compare;
|
|
else if (in == "input") return InstructionType::Input;
|
|
else if (in == "return") return InstructionType::Return;
|
|
else if (in == "concat") return InstructionType::Concat;
|
|
else return InstructionType::Variable;
|
|
}
|
|
|
|
Instruction::Instruction(std::vector<std::string> toks) {
|
|
if (!toks.empty()) {
|
|
// Get type of instruction from first token
|
|
instruction = strToInstructionType(toks[0]);
|
|
if (instruction == InstructionType::Variable) {
|
|
for (std::string tok : toks) {
|
|
args.push_back(Value(tok));
|
|
}
|
|
} else {
|
|
// The rest are the args, convert them to values first
|
|
for (size_t i = 1; i < toks.size(); i++) {
|
|
args.push_back(Value(toks[i]));
|
|
}
|
|
}
|
|
} else {
|
|
error("Empty tokens!");
|
|
}
|
|
}
|
|
|
|
Instruction::Instruction(std::vector<Value> toks) {
|
|
if (!toks.empty()) {
|
|
// Check type of value in first token, then compute token
|
|
if (toks[0].valtype == ValueType::Real) {
|
|
instruction = strToInstructionType(toks[0].real);
|
|
} else {
|
|
error("Instruction should be a real");
|
|
}
|
|
if (instruction == InstructionType::Variable) {
|
|
for (const auto& tok : toks) {
|
|
args.push_back(tok);
|
|
}
|
|
} else {
|
|
// The rest are the args
|
|
for (size_t i = 1; i < toks.size(); i++) {
|
|
args.push_back(toks[i]);
|
|
}
|
|
}
|
|
} else {
|
|
error("Empty tokens!");
|
|
}
|
|
}
|
|
|
|
Value::Value(std::string stringval) : valtype(ValueType::Real), real(stringval) {}
|
|
|
|
Value::Value(Instruction instval) : valtype(ValueType::Processed), processed(std::make_unique<Instruction>(std::move(instval))) {}
|
|
|
|
Value::Value() : valtype(ValueType::Real) {}
|
|
|
|
Value::Value(InstructionGroup instgroup) : valtype(ValueType::InstructionGroup), instructionGroup(instgroup) {};
|
|
|
|
Value::Value(std::vector<Value> listval) : valtype(ValueType::List), list(std::move(listval)) {}
|
|
|
|
Value::Value(const Value& other) : valtype(other.valtype), real(other.real), varName(other.varName), instructionGroup(other.instructionGroup), list(other.list) {
|
|
if (other.processed) {
|
|
processed = std::make_unique<Instruction>(*other.processed);
|
|
}
|
|
}
|
|
|
|
Value::Value(Varname varname) : valtype(ValueType::Variable), varName(varname) {}
|
|
|
|
Varname::Varname(std::string in) : key(in.substr(1)) {}
|
|
Varname::Varname() : key("") {}
|
|
|
|
Value& Value::operator=(const Value& other) {
|
|
if (this != &other) {
|
|
valtype = other.valtype;
|
|
real = other.real;
|
|
varName = other.varName;
|
|
instructionGroup = other.instructionGroup;
|
|
list = other.list;
|
|
if (other.processed) {
|
|
processed = std::make_unique<Instruction>(*other.processed);
|
|
} else {
|
|
processed.reset();
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
std::string Value::toString() const {
|
|
std::string out = "Value(type: ";
|
|
switch (valtype) {
|
|
case ValueType::Real:
|
|
out += "Real, value: " + real + ")";
|
|
break;
|
|
case ValueType::Processed:
|
|
out += "Processed, value: ";
|
|
if (processed) {
|
|
out += processed->toString();
|
|
} else {
|
|
out += "null";
|
|
}
|
|
out += ")";
|
|
break;
|
|
case ValueType::InstructionGroup:
|
|
out += "InstructionGroup, contains " + std::to_string(instructionGroup.size()) + " instructions)";
|
|
break;
|
|
case ValueType::List: {
|
|
out += "List, items: [";
|
|
for (const auto& item : list) {
|
|
out += item.toString() + ", ";
|
|
}
|
|
out += "])";
|
|
break;
|
|
}
|
|
default:
|
|
out += "FIXME)";
|
|
break;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
std::string Instruction::toString() const {
|
|
std::string out = "Instruction(type: ";
|
|
switch (instruction) {
|
|
case InstructionType::None:
|
|
out += "None";
|
|
break;
|
|
case InstructionType::Println:
|
|
out += "Println";
|
|
break;
|
|
case InstructionType::Math:
|
|
out += "Math";
|
|
break;
|
|
case InstructionType::Let:
|
|
out += "Let";
|
|
break;
|
|
case InstructionType::If:
|
|
out += "If";
|
|
break;
|
|
case InstructionType::Compare:
|
|
out += "Compare";
|
|
break;
|
|
case InstructionType::Input:
|
|
out += "Input";
|
|
break;
|
|
default:
|
|
out += "FIXME";
|
|
break;
|
|
}
|
|
out += ", args: [";
|
|
for (const auto& val : args) {
|
|
out += val.toString() + ", ";
|
|
}
|
|
out += "])";
|
|
return out;
|
|
}
|
|
|
|
std::vector<Value> split(std::string line) {
|
|
std::vector<Value> splitvals;
|
|
std::string buf;
|
|
bool instring = false;
|
|
int brackets = 0;
|
|
char bracket_type = 0;
|
|
|
|
for (char chr : line) {
|
|
if (chr == ' ' && !instring && brackets == 0 && !buf.empty()) {
|
|
if (buf[0] == '$') {
|
|
splitvals.push_back(Value(Varname(buf)));
|
|
} else {
|
|
splitvals.push_back(Value(buf));
|
|
}
|
|
buf = "";
|
|
} else if (chr == '(' || chr == '[') {
|
|
if (brackets == 0) {
|
|
bracket_type = chr;
|
|
if (!buf.empty()) {
|
|
splitvals.push_back(Value(buf));
|
|
buf = "";
|
|
}
|
|
} else {
|
|
buf += chr;
|
|
}
|
|
brackets++;
|
|
} else if (chr == ')' || chr == ']') {
|
|
brackets--;
|
|
if (brackets == 0) {
|
|
if (!buf.empty()) {
|
|
if (bracket_type == '(') {
|
|
splitvals.push_back(Value(Instruction(split(buf))));
|
|
} else {
|
|
splitvals.push_back(Value(parse_list_content(buf)));
|
|
}
|
|
buf = "";
|
|
}
|
|
} else {
|
|
buf += chr;
|
|
}
|
|
} else if (chr == '"') {
|
|
instring = !instring;
|
|
} else {
|
|
buf += chr;
|
|
}
|
|
}
|
|
if (!buf.empty()) {
|
|
if (buf[0] == '$') {
|
|
splitvals.push_back(Value(Varname(buf)));
|
|
} else {
|
|
splitvals.push_back(Value(buf));
|
|
}
|
|
}
|
|
return splitvals;
|
|
}
|
|
|
|
bool inReplMode = false;
|