refactor
This commit is contained in:
parent
ba2bf4b404
commit
88ca215573
|
@ -18,6 +18,7 @@ struct Node {
|
||||||
void Insert(Node*);
|
void Insert(Node*);
|
||||||
void InsertBefore(Node*);
|
void InsertBefore(Node*);
|
||||||
virtual void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) = 0;
|
virtual void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) = 0;
|
||||||
|
|
||||||
virtual ~Node() {}
|
virtual ~Node() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,241 +55,62 @@ struct TypeVariable {
|
||||||
};
|
};
|
||||||
|
|
||||||
TypeVariable() {}
|
TypeVariable() {}
|
||||||
|
|
||||||
TypeVariable(ID id) : id(id) {}
|
TypeVariable(ID id) : id(id) {}
|
||||||
|
|
||||||
ID id = ID::none;
|
ID id = ID::none;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeallocateStack : public Node {
|
struct DeallocateStack : public Node {
|
||||||
DeallocateStack(size_t count) : count(count) {}
|
DeallocateStack(size_t count) : count(count) {}
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
stack.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HiddenDeallocateStack : public Node {
|
struct HiddenDeallocateStack : public Node {
|
||||||
HiddenDeallocateStack(size_t count) : count(count) {}
|
HiddenDeallocateStack(size_t count) : count(count) {}
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
stack.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VariableInStack {
|
struct VariableInStack {
|
||||||
VariableInStack(TypeVariable type_variable) : type_variable(type_variable) {}
|
VariableInStack(TypeVariable type_variable) : type_variable(type_variable) {}
|
||||||
void CallOperator(std::shared_ptr<VariableInStack>& another, std::shared_ptr<VariableInStack>& result, Operation op) {
|
|
||||||
if (op == Operation::Equal || op == Operation::PlusEqual || op == Operation::MinusEqual || op == Operation::StarEqual || op == Operation::SlashEqual) {
|
|
||||||
if (type_variable.id != TypeVariable::ID::none && type_variable.id != another->type_variable.id) {
|
|
||||||
throw std::logic_error("error variable convert");
|
|
||||||
}
|
|
||||||
if (result->type_variable.id != TypeVariable::ID::none && result->type_variable.id != another->type_variable.id) {
|
|
||||||
throw std::logic_error("error variable convert");
|
|
||||||
}
|
|
||||||
result->Clear();
|
|
||||||
result->type_variable.id = another->type_variable.id;
|
|
||||||
result->Allocate();
|
|
||||||
if (op == Operation::Equal) {
|
|
||||||
Clear();
|
|
||||||
type_variable.id = another->type_variable.id;
|
|
||||||
Allocate();
|
|
||||||
}
|
|
||||||
if (another->type_variable.id == TypeVariable::ID::type_int) {
|
|
||||||
int& x = *static_cast<int*>(memory);
|
|
||||||
int& y = *static_cast<int*>(another->memory);
|
|
||||||
int& res = *static_cast<int*>(result->memory);
|
|
||||||
if (op == Operation::Equal) {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res = x;
|
|
||||||
} else {
|
|
||||||
res = x = y;
|
|
||||||
}
|
|
||||||
} else if (op == Operation::PlusEqual) {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res += x;
|
|
||||||
} else {
|
|
||||||
res = x += y;
|
|
||||||
}
|
|
||||||
} else if (op == Operation::MinusEqual) {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res -= x;
|
|
||||||
} else {
|
|
||||||
res = x -= y;
|
|
||||||
}
|
|
||||||
} else if (op == Operation::StarEqual) {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res *= x;
|
|
||||||
} else {
|
|
||||||
res = x *= y;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res /= x;
|
|
||||||
} else {
|
|
||||||
res = x /= y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (another->type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
std::string& x = *static_cast<std::string*>(memory);
|
|
||||||
std::string& y = *static_cast<std::string*>(another->memory);
|
|
||||||
std::string& res = *static_cast<std::string*>(result->memory);
|
|
||||||
if (op == Operation::Equal) {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res = x;
|
|
||||||
} else {
|
|
||||||
res = x = y;
|
|
||||||
}
|
|
||||||
} else if (op == Operation::PlusEqual) {
|
|
||||||
if (this == another.get()) {
|
|
||||||
res += x;
|
|
||||||
} else {
|
|
||||||
res = x += y;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("invalid operation string");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (op == Operation::EqualEqual || op == Operation::ExclamationMarkEqual || op == Operation::LAngle || op == Operation::RAngle || op == Operation::LAngleEqual || op == Operation::RAngleEqual) {
|
|
||||||
result->Clear();
|
|
||||||
result->type_variable.id = TypeVariable::ID::type_int;
|
|
||||||
result->Allocate();
|
|
||||||
int& res = *static_cast<int*>(result->memory);
|
|
||||||
|
|
||||||
if (another->type_variable.id == TypeVariable::ID::type_int && type_variable.id == TypeVariable::ID::type_int) {
|
void CallOperator(std::shared_ptr<VariableInStack>& another, std::shared_ptr<VariableInStack>& result, Operation op);
|
||||||
auto& x = *static_cast<int*>(memory);
|
|
||||||
auto& y = *static_cast<int*>(another->memory);
|
|
||||||
if (op == Operation::EqualEqual) {
|
|
||||||
res = (x == y);
|
|
||||||
} else if (op == Operation::ExclamationMarkEqual) {
|
|
||||||
res = (x != y);
|
|
||||||
} else if (op == Operation::LAngle) {
|
|
||||||
res = (x < y);
|
|
||||||
} else if (op == Operation::RAngle) {
|
|
||||||
res = (x > y);
|
|
||||||
} else if (op == Operation::LAngleEqual) {
|
|
||||||
res = (x <= y);
|
|
||||||
} else if (op == Operation::RAngleEqual) {
|
|
||||||
res = (x >= y);
|
|
||||||
}
|
|
||||||
} else if (another->type_variable.id == TypeVariable::ID::type_string && type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
auto& x = *static_cast<std::string*>(memory);
|
|
||||||
auto& y = *static_cast<std::string*>(another->memory);
|
|
||||||
if (op == Operation::EqualEqual) {
|
|
||||||
res = (x == y);
|
|
||||||
} else if (op == Operation::ExclamationMarkEqual) {
|
|
||||||
res = (x != y);
|
|
||||||
} else if (op == Operation::LAngle) {
|
|
||||||
res = (x < y);
|
|
||||||
} else if (op == Operation::RAngle) {
|
|
||||||
res = (x > y);
|
|
||||||
} else if (op == Operation::LAngleEqual) {
|
|
||||||
res = (x <= y);
|
|
||||||
} else if (op == Operation::RAngleEqual) {
|
|
||||||
res = (x >= y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (op == Operation::Plus || op == Operation::Minus || op == Operation::Star || op == Operation::Slash) {
|
|
||||||
result->Clear();
|
|
||||||
result->type_variable.id = another->type_variable.id;
|
|
||||||
result->Allocate();
|
|
||||||
if (another->type_variable.id == TypeVariable::ID::type_int && type_variable.id == TypeVariable::ID::type_int) {
|
|
||||||
int& x = *static_cast<int*>(memory);
|
|
||||||
int& y = *static_cast<int*>(another->memory);
|
|
||||||
int& res = *static_cast<int*>(result->memory);
|
|
||||||
if (op == Operation::Plus) {
|
|
||||||
res = (x + y);
|
|
||||||
} else if (op == Operation::Minus) {
|
|
||||||
res = (x - y);
|
|
||||||
} else if (op == Operation::Star) {
|
|
||||||
res = (x * y);
|
|
||||||
} else if (op == Operation::Slash) {
|
|
||||||
res = (x / y);
|
|
||||||
}
|
|
||||||
} else if (another->type_variable.id == TypeVariable::ID::type_string && type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
std::string& x = *static_cast<std::string*>(memory);
|
|
||||||
std::string& y = *static_cast<std::string*>(another->memory);
|
|
||||||
std::string& res = *static_cast<std::string*>(result->memory);
|
|
||||||
if (op == Operation::Plus) {
|
|
||||||
res = (x + y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
void Allocate();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (type_variable.id == TypeVariable::ID::type_int) {
|
|
||||||
int& x = *static_cast<int*>(memory);
|
|
||||||
if (another->type_variable.id == TypeVariable::ID::type_int) {
|
|
||||||
int& y = *static_cast<int*>(another->memory);
|
|
||||||
result->type_variable.id = TypeVariable::ID::type_int;
|
|
||||||
result->Clear();
|
|
||||||
result->Allocate();
|
|
||||||
int& res = *static_cast<int*>(result->memory);
|
|
||||||
if (op == Operation::Equal) {
|
|
||||||
/*
|
|
||||||
if (this == &another)
|
|
||||||
res = y;
|
|
||||||
else
|
|
||||||
x = res = y;
|
|
||||||
*/
|
|
||||||
} else if (op == Operation::Plus) {
|
|
||||||
res = x + y;
|
|
||||||
} else if (op == Operation::Star) {
|
|
||||||
res = x * y;
|
|
||||||
} else if (op == Operation::LAngle) {
|
|
||||||
res = x < y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
using std::string;
|
|
||||||
string& x = *static_cast<string*>(memory);
|
|
||||||
if (another->type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
string& y = *static_cast<string*>(another->memory);
|
|
||||||
result->type_variable.id = TypeVariable::ID::type_string;
|
|
||||||
result->Clear();
|
|
||||||
result->Allocate();
|
|
||||||
string& res = *static_cast<string*>(result->memory);
|
|
||||||
if (op == Operation::Equal) {
|
|
||||||
if (this == another.get())
|
|
||||||
res = y;
|
|
||||||
else
|
|
||||||
x = res = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Clear() {
|
|
||||||
if (memory) {
|
|
||||||
if (type_variable.id == TypeVariable::ID::type_int) {
|
|
||||||
delete static_cast<int*>(memory);
|
|
||||||
} else if (type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
delete static_cast<std::string*>(memory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memory = nullptr;
|
|
||||||
}
|
|
||||||
void Allocate() {
|
|
||||||
if (type_variable.id == TypeVariable::ID::type_int) {
|
|
||||||
memory = new int(15);
|
|
||||||
} else if (type_variable.id == TypeVariable::ID::type_string) {
|
|
||||||
memory = new std::string("lkajsdf");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TypeVariable type_variable;
|
TypeVariable type_variable;
|
||||||
void* memory = nullptr;
|
void* memory = nullptr;
|
||||||
|
private:
|
||||||
|
|
||||||
|
void CallEqualOperator(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op);
|
||||||
|
void CallComparisonOperator(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const;
|
||||||
|
void CallArithmeticOperator(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const;
|
||||||
|
void CallEqualOperatorInt(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
const std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const;
|
||||||
|
void CallEqualOperatorString(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
const std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Variable : public Node {
|
struct Variable : public Node {
|
||||||
Variable(std::string type, std::string name) : type(std::move(type)), name(std::move(name)) {}
|
Variable(std::string type, std::string name) : type(std::move(type)), name(std::move(name)) {}
|
||||||
|
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -299,13 +121,8 @@ struct Variable : public Node {
|
||||||
|
|
||||||
struct Container : public Node {
|
struct Container : public Node {
|
||||||
void AddChildren(Node*);
|
void AddChildren(Node*);
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
|
||||||
Node* cur = children_begin;
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
while (cur) {
|
|
||||||
cur->Run(stack);
|
|
||||||
cur = cur->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* children_begin = nullptr;
|
Node* children_begin = nullptr;
|
||||||
Node* children_end = nullptr;
|
Node* children_end = nullptr;
|
||||||
|
@ -313,26 +130,17 @@ struct Container : public Node {
|
||||||
|
|
||||||
struct CodeBlock : public Container {};
|
struct CodeBlock : public Container {};
|
||||||
|
|
||||||
struct Function : public Node {
|
|
||||||
Function(const std::string& name) : name(name), code(new CodeBlock()) {}
|
|
||||||
Function(std::string&& name) : name(name) {}
|
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
|
||||||
code->Run(stack);
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
std::string name;
|
|
||||||
CodeBlock* code;
|
|
||||||
// RETURN VALUE
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CreateVariables : Node {
|
struct CreateVariables : Node {
|
||||||
CreateVariables(size_t count) : count(count) {}
|
CreateVariables(size_t count) : count(count) {}
|
||||||
|
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {}
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {}
|
||||||
|
|
||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CallFunction : public Node {
|
struct CallFunction : public Node {
|
||||||
CallFunction(std::string name_function) : name_function(std::move(name_function)) {}
|
CallFunction(std::string name_function) : name_function(std::move(name_function)) {}
|
||||||
|
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
std::string name_function;
|
std::string name_function;
|
||||||
std::vector<Expression*> parameters;
|
std::vector<Expression*> parameters;
|
||||||
|
@ -342,52 +150,15 @@ using stack_pointer = size_t;
|
||||||
|
|
||||||
struct Expression : public Node {
|
struct Expression : public Node {
|
||||||
using Types = std::variant<std::string, Expression*, stack_pointer>;
|
using Types = std::variant<std::string, Expression*, stack_pointer>;
|
||||||
Expression() {}
|
|
||||||
Expression(Types type1, Types type2, Operation op) : type1(std::move(type1)), type2(std::move(type2)), op(op) {
|
|
||||||
if (op == Operation::Value) {
|
|
||||||
count = 1;
|
|
||||||
} else {
|
|
||||||
count = 1;
|
|
||||||
auto e_type1 = std::get<Expression*>(type1);
|
|
||||||
auto e_type2 = std::get<Expression*>(type2);
|
|
||||||
count += e_type1->count;
|
|
||||||
count += e_type2->count;
|
|
||||||
|
|
||||||
position_result = count;
|
Expression() {}
|
||||||
e_type2->AddStackPointer(e_type1->count);
|
|
||||||
}
|
Expression(Types type1, Types type2, Operation op);
|
||||||
}
|
|
||||||
void AddStackPointer(stack_pointer d) {
|
void AddStackPointer(stack_pointer d);
|
||||||
position_result += d;
|
|
||||||
}
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
|
||||||
if (op == Operation::Value) {
|
|
||||||
if (std::holds_alternative<size_t>(type1)) {
|
|
||||||
stack.push_back(*(stack.end() - std::get<size_t>(type1)));
|
|
||||||
} else {
|
|
||||||
stack.push_back(std::make_shared<VariableInStack>(TypeVariable()));
|
|
||||||
if (std::get<std::string>(type1)[0] == '\"') {
|
|
||||||
stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_string);
|
|
||||||
stack.back()->Allocate();
|
|
||||||
(*(std::string*) stack.back()->memory) =
|
|
||||||
std::get<std::string>(type1).substr(1, std::get<std::string>(type1).size() - 2);
|
|
||||||
} else {
|
|
||||||
stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_int);
|
|
||||||
stack.back()->Allocate();
|
|
||||||
(*(int*) stack.back()->memory) = std::atoi(std::get<std::string>(type1).c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::get<Expression*>(type1)->Run(stack);
|
|
||||||
std::shared_ptr<VariableInStack> x = std::move(stack.back());
|
|
||||||
stack.pop_back();
|
|
||||||
std::get<Expression*>(type2)->Run(stack);
|
|
||||||
std::shared_ptr<VariableInStack> y = std::move(stack.back());
|
|
||||||
stack.pop_back();
|
|
||||||
stack.push_back(std::make_shared<VariableInStack>(TypeVariable()));
|
|
||||||
x->CallOperator(y, stack.back(), op);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static size_t GetPriority(Operation);
|
static size_t GetPriority(Operation);
|
||||||
static PriorityType GetPriorityType(Operation);
|
static PriorityType GetPriorityType(Operation);
|
||||||
static Operation Convert(Lexer::LexerToken::Type);
|
static Operation Convert(Lexer::LexerToken::Type);
|
||||||
|
@ -397,59 +168,25 @@ struct Expression : public Node {
|
||||||
size_t count;
|
size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FOR : public Node {
|
struct BlockFor : public Node {
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
while (true) {
|
|
||||||
check->Run(stack);
|
|
||||||
auto res = *((int*) stack.back()->memory);
|
|
||||||
stack.pop_back();
|
|
||||||
if (!res) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
code->Run(stack);
|
|
||||||
size_t sz = stack.size();
|
|
||||||
tick->Run(stack);
|
|
||||||
while (stack.size() != sz) {
|
|
||||||
stack.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Variable* var = nullptr;
|
Variable* var = nullptr;
|
||||||
Expression* check = nullptr;
|
Expression* check = nullptr;
|
||||||
Expression* tick = nullptr;
|
Expression* tick = nullptr;
|
||||||
CodeBlock* code = nullptr;
|
CodeBlock* code = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IF : public Node {
|
struct BlockIf : public Node {
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
if (check) {
|
|
||||||
check->Run(stack);
|
|
||||||
auto res = *((int*) stack.back()->memory);
|
|
||||||
stack.pop_back();
|
|
||||||
if (res) {
|
|
||||||
code->Run(stack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expression* check = nullptr;
|
Expression* check = nullptr;
|
||||||
CodeBlock* code = nullptr;
|
CodeBlock* code = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WHILE : public Node {
|
struct BlockWhile : public Node {
|
||||||
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
|
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
|
||||||
if (check) {
|
|
||||||
while (true) {
|
|
||||||
check->Run(stack);
|
|
||||||
auto res = *((int*) stack.back()->memory);
|
|
||||||
stack.pop_back();
|
|
||||||
if (res) {
|
|
||||||
code->Run(stack);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expression* check = nullptr;
|
Expression* check = nullptr;
|
||||||
CodeBlock* code = nullptr;
|
CodeBlock* code = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -457,6 +194,7 @@ struct WHILE : public Node {
|
||||||
class SyntaxTree {
|
class SyntaxTree {
|
||||||
public:
|
public:
|
||||||
SyntaxTree() {}
|
SyntaxTree() {}
|
||||||
|
|
||||||
void PushLexerTokenList(const LexerTokenList&);
|
void PushLexerTokenList(const LexerTokenList&);
|
||||||
void Compile();
|
void Compile();
|
||||||
void Run();
|
void Run();
|
||||||
|
@ -474,12 +212,12 @@ class SyntaxTree {
|
||||||
void PushExpression(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushExpression(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
||||||
void PushParametersFunction(CallFunction*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushParametersFunction(CallFunction*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
||||||
void PushCallFunction(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushCallFunction(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
||||||
void PushFOR(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushBlockFor(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it);
|
||||||
void PushSignatureFOR(FOR*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushSignatureBlockFor(BlockFor* node_for, const LexerTokenList& list, LexerTokenList::const_iterator& it);
|
||||||
void PushIF(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushBlockIf(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it);
|
||||||
void PushSignatureIF(IF*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushSignatureBlockIf(BlockIf* node_if, const LexerTokenList& list, LexerTokenList::const_iterator& it);
|
||||||
void PushWHILE(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushBlockWhile(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it);
|
||||||
void PushSignatureWHILE(WHILE*, const LexerTokenList&, LexerTokenList::const_iterator&);
|
void PushSignatureBlockWhile(BlockWhile* node_if, const LexerTokenList& list, LexerTokenList::const_iterator& it);
|
||||||
Expression* ParseExpression(LexerTokenList::const_iterator, LexerTokenList::const_iterator);
|
Expression* ParseExpression(LexerTokenList::const_iterator, LexerTokenList::const_iterator);
|
||||||
Expression* ParseExpression(const LexerTokenList&, LexerTokenList::const_iterator&);
|
Expression* ParseExpression(const LexerTokenList&, LexerTokenList::const_iterator&);
|
||||||
void PushDeallocateStack(Node*, size_t);
|
void PushDeallocateStack(Node*, size_t);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include "preprocessor.hpp"
|
#include "preprocessor.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <iostream> // TODO
|
|
||||||
|
|
||||||
std::string DeleteComments(std::string&& text) {
|
std::string DeleteComments(std::string&& text) {
|
||||||
std::vector<std::pair<int, int>> text_without_comments;
|
std::vector<std::pair<int, int>> text_without_comments;
|
||||||
size_t n = text.size();
|
size_t n = text.size();
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
using Type = Lexer::LexerToken::Type;
|
using Type = Lexer::LexerToken::Type;
|
||||||
|
|
||||||
std::unordered_set<std::string> special_words = {"def"};
|
|
||||||
|
|
||||||
bool IsOperation(Type type) {
|
bool IsOperation(Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Equal:
|
case Type::Equal:
|
||||||
|
@ -72,6 +70,14 @@ void Container::AddChildren(Node* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Container::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
Node* current = children_begin;
|
||||||
|
while (current) {
|
||||||
|
current->Run(stack);
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t Expression::GetPriority(Operation op) {
|
size_t Expression::GetPriority(Operation op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Operation::Equal:
|
case Operation::Equal:
|
||||||
|
@ -147,6 +153,54 @@ PriorityType Expression::GetPriorityType(Operation op) {
|
||||||
throw std::logic_error("unsupported operator");
|
throw std::logic_error("unsupported operator");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Expression::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
if (op == Operation::Value) {
|
||||||
|
if (std::holds_alternative<size_t>(type1)) {
|
||||||
|
stack.push_back(*(stack.end() - std::get<size_t>(type1)));
|
||||||
|
} else {
|
||||||
|
stack.push_back(std::make_shared<VariableInStack>(TypeVariable()));
|
||||||
|
if (std::get<std::string>(type1)[0] == '\"') {
|
||||||
|
stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_string);
|
||||||
|
stack.back()->Allocate();
|
||||||
|
(*(std::string*) stack.back()->memory) =
|
||||||
|
std::get<std::string>(type1).substr(1, std::get<std::string>(type1).size() - 2);
|
||||||
|
} else {
|
||||||
|
stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_int);
|
||||||
|
stack.back()->Allocate();
|
||||||
|
(*(int*) stack.back()->memory) = std::atoi(std::get<std::string>(type1).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::get<Expression*>(type1)->Run(stack);
|
||||||
|
std::shared_ptr<VariableInStack> x = std::move(stack.back());
|
||||||
|
stack.pop_back();
|
||||||
|
std::get<Expression*>(type2)->Run(stack);
|
||||||
|
std::shared_ptr<VariableInStack> y = std::move(stack.back());
|
||||||
|
stack.pop_back();
|
||||||
|
stack.push_back(std::make_shared<VariableInStack>(TypeVariable()));
|
||||||
|
x->CallOperator(y, stack.back(), op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expression::AddStackPointer(stack_pointer d) {
|
||||||
|
position_result += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression::Expression(Expression::Types type1, Expression::Types type2, Operation op) : type1(std::move(type1)), type2(std::move(type2)), op(op) {
|
||||||
|
if (op == Operation::Value) {
|
||||||
|
count = 1;
|
||||||
|
} else {
|
||||||
|
count = 1;
|
||||||
|
auto e_type1 = std::get<Expression*>(type1);
|
||||||
|
auto e_type2 = std::get<Expression*>(type2);
|
||||||
|
count += e_type1->count;
|
||||||
|
count += e_type2->count;
|
||||||
|
|
||||||
|
position_result = count;
|
||||||
|
e_type2->AddStackPointer(e_type1->count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SyntaxTree::IsTypeName(Node* node, const std::string& str) {
|
bool SyntaxTree::IsTypeName(Node* node, const std::string& str) {
|
||||||
return str == "int" || str == "string";
|
return str == "int" || str == "string";
|
||||||
}
|
}
|
||||||
|
@ -198,78 +252,18 @@ void SyntaxTree::PushCurlyBrackets(Container* container, const LexerTokenList& l
|
||||||
container->AddChildren(ParseCurlyBrackets(container, list, it));
|
container->AddChildren(ParseCurlyBrackets(container, list, it));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void SyntaxTree::PushRoundBrackets(Container* container, const LexerTokenList& list,
|
|
||||||
LexerTokenList::const_iterator& it) {
|
|
||||||
RoundBrackets* current = new RoundBrackets();
|
|
||||||
container->AddChildren(current);
|
|
||||||
|
|
||||||
for (; it->type != Type::RoundCloseBracket; ++it) {
|
|
||||||
if (it->type == Type::Word) {
|
|
||||||
if (IsTypeName(container->children_end, it->info)) {
|
|
||||||
std::string type = it->info;
|
|
||||||
++it;
|
|
||||||
if (it->type == Type::Word) {
|
|
||||||
container->AddChildren(new Variable(std::move(type), it->info));
|
|
||||||
}
|
|
||||||
} else if (IsVariableName(container->children_end, it->info)) {
|
|
||||||
++it;
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("I expected type or name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
void SyntaxTree::PushFunction(Container* container, const LexerTokenList& list,
|
|
||||||
LexerTokenList::const_iterator& it) {
|
|
||||||
if (it->type == Type::Word && !IsSpecialWord(it->info)) {
|
|
||||||
auto func = new Function(it->info);
|
|
||||||
++it;
|
|
||||||
if (it->type == Type::RoundOpenBracket) {
|
|
||||||
PushRoundBrackets(func->parameters, list, ++it);
|
|
||||||
++it;
|
|
||||||
if (it->type == Type::RArrow) {
|
|
||||||
++it;
|
|
||||||
if (it->type == Type::Word && IsTypeName(container->children_end, it->info)) {
|
|
||||||
++it;
|
|
||||||
if (it->type == Type::CurlyOpenBracket) {
|
|
||||||
PushCurlyBrackets(func->code, list, ++it);
|
|
||||||
container->AddChildren(func);
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Invalid function body");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Invalit return type");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Missing -> in function");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Invalid function parameters");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw std::logic_error("Invalid function name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void SyntaxTree::PushLine(Container* container, const LexerTokenList& list,
|
void SyntaxTree::PushLine(Container* container, const LexerTokenList& list,
|
||||||
LexerTokenList::const_iterator& it) {
|
LexerTokenList::const_iterator& it) {
|
||||||
if (it->type == Type::CurlyOpenBracket) {
|
if (it->type == Type::CurlyOpenBracket) {
|
||||||
PushCurlyBrackets(container, list, ++it);
|
PushCurlyBrackets(container, list, ++it);
|
||||||
} else if (it->type == Type::RoundOpenBracket) {
|
} else if (it->type == Type::RoundOpenBracket) {
|
||||||
PushExpression(container, list, it);
|
PushExpression(container, list, it);
|
||||||
// PushRoundBrackets(container, list, ++it);
|
|
||||||
} else if (it->type == Type::IF) {
|
} else if (it->type == Type::IF) {
|
||||||
PushIF(container, list, it);
|
PushBlockIf(container, list, it);
|
||||||
} else if (it->type == Type::FOR) {
|
} else if (it->type == Type::FOR) {
|
||||||
PushFOR(container, list, it);
|
PushBlockFor(container, list, it);
|
||||||
} else if (it->type == Type::WHILE) {
|
} else if (it->type == Type::WHILE) {
|
||||||
PushWHILE(container, list, it);
|
PushBlockWhile(container, list, it);
|
||||||
} else if (it->type == Type::Word) {
|
} else if (it->type == Type::Word) {
|
||||||
auto place = container->children_end;
|
auto place = container->children_end;
|
||||||
if (!place)
|
if (!place)
|
||||||
|
@ -350,13 +344,13 @@ void SyntaxTree::PushCallFunction(Container* container,
|
||||||
container->AddChildren(new HiddenDeallocateStack(function->parameters.size()));
|
container->AddChildren(new HiddenDeallocateStack(function->parameters.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxTree::PushFOR(Container* container,
|
void SyntaxTree::PushBlockFor(Container* container,
|
||||||
const LexerTokenList& list,
|
const LexerTokenList& list,
|
||||||
std::list<Lexer::LexerToken>::const_iterator& it) {
|
std::list<Lexer::LexerToken>::const_iterator& it) {
|
||||||
auto c = new Container;
|
auto c = new Container;
|
||||||
auto f = new FOR();
|
auto f = new BlockFor();
|
||||||
container->AddChildren(c);
|
container->AddChildren(c);
|
||||||
PushSignatureFOR(f, list, ++it);
|
PushSignatureBlockFor(f, list, ++it);
|
||||||
c->AddChildren(f->var);
|
c->AddChildren(f->var);
|
||||||
c->AddChildren(f);
|
c->AddChildren(f);
|
||||||
if (it->type != Type::CurlyOpenBracket) {
|
if (it->type != Type::CurlyOpenBracket) {
|
||||||
|
@ -367,9 +361,9 @@ void SyntaxTree::PushFOR(Container* container,
|
||||||
f->code->previous = nullptr;
|
f->code->previous = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxTree::PushSignatureFOR(FOR* node_for,
|
void SyntaxTree::PushSignatureBlockFor(BlockFor* node_for,
|
||||||
const LexerTokenList& list,
|
const LexerTokenList& list,
|
||||||
std::list<Lexer::LexerToken>::const_iterator& it) {
|
std::list<Lexer::LexerToken>::const_iterator& it) {
|
||||||
if (it->type != Type::RoundOpenBracket)
|
if (it->type != Type::RoundOpenBracket)
|
||||||
throw std::logic_error("expected ( after for");
|
throw std::logic_error("expected ( after for");
|
||||||
++it;
|
++it;
|
||||||
|
@ -408,12 +402,12 @@ void SyntaxTree::PushSignatureFOR(FOR* node_for,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxTree::PushIF(Container* container,
|
void SyntaxTree::PushBlockIf(Container* container,
|
||||||
const LexerTokenList& list,
|
const LexerTokenList& list,
|
||||||
std::list<Lexer::LexerToken>::const_iterator& it) {
|
std::list<Lexer::LexerToken>::const_iterator& it) {
|
||||||
auto f = new IF();
|
auto f = new BlockIf();
|
||||||
container->AddChildren(f);
|
container->AddChildren(f);
|
||||||
PushSignatureIF(f, list, ++it);
|
PushSignatureBlockIf(f, list, ++it);
|
||||||
f->check->parent = f;
|
f->check->parent = f;
|
||||||
if (it->type != Type::CurlyOpenBracket) {
|
if (it->type != Type::CurlyOpenBracket) {
|
||||||
throw std::logic_error("expected { after if (...)");
|
throw std::logic_error("expected { after if (...)");
|
||||||
|
@ -422,9 +416,9 @@ void SyntaxTree::PushIF(Container* container,
|
||||||
f->code->parent = f;
|
f->code->parent = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxTree::PushSignatureIF(IF* node_if,
|
void SyntaxTree::PushSignatureBlockIf(BlockIf* node_if,
|
||||||
const LexerTokenList& list,
|
const LexerTokenList& list,
|
||||||
std::list<Lexer::LexerToken>::const_iterator& it) {
|
std::list<Lexer::LexerToken>::const_iterator& it) {
|
||||||
if (it->type != Type::RoundOpenBracket)
|
if (it->type != Type::RoundOpenBracket)
|
||||||
throw std::logic_error("expected ( after if");
|
throw std::logic_error("expected ( after if");
|
||||||
++it;
|
++it;
|
||||||
|
@ -436,21 +430,21 @@ void SyntaxTree::PushSignatureIF(IF* node_if,
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxTree::PushWHILE(Container* container,
|
void SyntaxTree::PushBlockWhile(Container* container,
|
||||||
const LexerTokenList& list,
|
const LexerTokenList& list,
|
||||||
std::list<Lexer::LexerToken>::const_iterator& it) {
|
std::list<Lexer::LexerToken>::const_iterator& it) {
|
||||||
auto f = new WHILE();
|
auto f = new BlockWhile();
|
||||||
container->AddChildren(f);
|
container->AddChildren(f);
|
||||||
PushSignatureWHILE(f, list, ++it);
|
PushSignatureBlockWhile(f, list, ++it);
|
||||||
if (it->type != Type::CurlyOpenBracket) {
|
if (it->type != Type::CurlyOpenBracket) {
|
||||||
throw std::logic_error("expected { after while (...)");
|
throw std::logic_error("expected { after while (...)");
|
||||||
}
|
}
|
||||||
f->code = ParseCurlyBrackets(container, list, ++it);
|
f->code = ParseCurlyBrackets(container, list, ++it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxTree::PushSignatureWHILE(WHILE* node_if,
|
void SyntaxTree::PushSignatureBlockWhile(BlockWhile* node_if,
|
||||||
const LexerTokenList& list,
|
const LexerTokenList& list,
|
||||||
std::list<Lexer::LexerToken>::const_iterator& it) {
|
std::list<Lexer::LexerToken>::const_iterator& it) {
|
||||||
if (it->type != Type::RoundOpenBracket)
|
if (it->type != Type::RoundOpenBracket)
|
||||||
throw std::logic_error("expected ( after while");
|
throw std::logic_error("expected ( after while");
|
||||||
++it;
|
++it;
|
||||||
|
@ -539,10 +533,10 @@ void SyntaxTree::PushDeallocateStack(Node* node, size_t count_variables = 0) {
|
||||||
PushDeallocateStack(code_block->children_begin);
|
PushDeallocateStack(code_block->children_begin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto if_ = dynamic_cast<IF*>(node)) {
|
if (auto if_ = dynamic_cast<BlockIf*>(node)) {
|
||||||
PushDeallocateStack(if_->code);
|
PushDeallocateStack(if_->code);
|
||||||
}
|
}
|
||||||
if (auto for_ = dynamic_cast<FOR*>(node)) {
|
if (auto for_ = dynamic_cast<BlockFor*>(node)) {
|
||||||
PushDeallocateStack(for_->code);
|
PushDeallocateStack(for_->code);
|
||||||
}
|
}
|
||||||
if (dynamic_cast<Variable*>(node)) {
|
if (dynamic_cast<Variable*>(node)) {
|
||||||
|
@ -580,15 +574,15 @@ void SyntaxTree::LinkVariables(Node* node) {
|
||||||
LinkVariablesInExpression(var->default_value, node);
|
LinkVariablesInExpression(var->default_value, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto if_ = dynamic_cast<IF*>(node)) {
|
if (auto if_ = dynamic_cast<BlockIf*>(node)) {
|
||||||
LinkVariablesInExpression(if_->check, node);
|
LinkVariablesInExpression(if_->check, node);
|
||||||
LinkVariables(if_->code->children_begin);
|
LinkVariables(if_->code->children_begin);
|
||||||
}
|
}
|
||||||
if (auto while_ = dynamic_cast<WHILE*>(node)) {
|
if (auto while_ = dynamic_cast<BlockWhile*>(node)) {
|
||||||
LinkVariablesInExpression(while_->check, node);
|
LinkVariablesInExpression(while_->check, node);
|
||||||
LinkVariables(while_->code->children_begin);
|
LinkVariables(while_->code->children_begin);
|
||||||
}
|
}
|
||||||
if (auto for_ = dynamic_cast<FOR*>(node)) {
|
if (auto for_ = dynamic_cast<BlockFor*>(node)) {
|
||||||
LinkVariablesInExpression(for_->check, node);
|
LinkVariablesInExpression(for_->check, node);
|
||||||
LinkVariablesInExpression(for_->tick, node);
|
LinkVariablesInExpression(for_->tick, node);
|
||||||
LinkVariables(for_->code->children_begin);
|
LinkVariables(for_->code->children_begin);
|
||||||
|
@ -678,3 +672,256 @@ void Variable::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VariableInStack::CallOperator(std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
Operation op) {
|
||||||
|
if (op == Operation::Equal || op == Operation::PlusEqual || op == Operation::MinusEqual
|
||||||
|
|| op == Operation::StarEqual || op == Operation::SlashEqual) {
|
||||||
|
CallEqualOperator(another, result, op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (op == Operation::EqualEqual || op == Operation::ExclamationMarkEqual || op == Operation::LAngle
|
||||||
|
|| op == Operation::RAngle || op == Operation::LAngleEqual || op == Operation::RAngleEqual) {
|
||||||
|
CallComparisonOperator(another, result, op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (op == Operation::Plus || op == Operation::Minus || op == Operation::Star || op == Operation::Slash) {
|
||||||
|
CallArithmeticOperator(another, result, op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::CallArithmeticOperator(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const {
|
||||||
|
result->Clear();
|
||||||
|
result->type_variable.id = another->type_variable.id;
|
||||||
|
result->Allocate();
|
||||||
|
if (another->type_variable.id == TypeVariable::type_int && type_variable.id == TypeVariable::type_int) {
|
||||||
|
int& x = *static_cast<int*>(memory);
|
||||||
|
int& y = *static_cast<int*>(another->memory);
|
||||||
|
int& res = *static_cast<int*>(result->memory);
|
||||||
|
if (op == Operation::Plus) {
|
||||||
|
res = (x + y);
|
||||||
|
} else if (op == Operation::Minus) {
|
||||||
|
res = (x - y);
|
||||||
|
} else if (op == Operation::Star) {
|
||||||
|
res = (x * y);
|
||||||
|
} else if (op == Operation::Slash) {
|
||||||
|
res = (x / y);
|
||||||
|
}
|
||||||
|
} else if (another->type_variable.id == TypeVariable::type_string
|
||||||
|
&& type_variable.id == TypeVariable::type_string) {
|
||||||
|
std::string& x = *static_cast<std::string*>(memory);
|
||||||
|
std::string& y = *static_cast<std::string*>(another->memory);
|
||||||
|
std::string& res = *static_cast<std::string*>(result->memory);
|
||||||
|
if (op == Operation::Plus) {
|
||||||
|
res = (x + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::CallComparisonOperator(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const {
|
||||||
|
result->Clear();
|
||||||
|
result->type_variable.id = TypeVariable::type_int;
|
||||||
|
result->Allocate();
|
||||||
|
int& res = *static_cast<int*>(result->memory);
|
||||||
|
|
||||||
|
if (another->type_variable.id == TypeVariable::type_int && type_variable.id == TypeVariable::type_int) {
|
||||||
|
auto& x = *static_cast<int*>(memory);
|
||||||
|
auto& y = *static_cast<int*>(another->memory);
|
||||||
|
if (op == Operation::EqualEqual) {
|
||||||
|
res = (x == y);
|
||||||
|
} else if (op == Operation::ExclamationMarkEqual) {
|
||||||
|
res = (x != y);
|
||||||
|
} else if (op == Operation::LAngle) {
|
||||||
|
res = (x < y);
|
||||||
|
} else if (op == Operation::RAngle) {
|
||||||
|
res = (x > y);
|
||||||
|
} else if (op == Operation::LAngleEqual) {
|
||||||
|
res = (x <= y);
|
||||||
|
} else if (op == Operation::RAngleEqual) {
|
||||||
|
res = (x >= y);
|
||||||
|
}
|
||||||
|
} else if (another->type_variable.id == TypeVariable::type_string
|
||||||
|
&& type_variable.id == TypeVariable::type_string) {
|
||||||
|
auto& x = *static_cast<std::string*>(memory);
|
||||||
|
auto& y = *static_cast<std::string*>(another->memory);
|
||||||
|
if (op == Operation::EqualEqual) {
|
||||||
|
res = (x == y);
|
||||||
|
} else if (op == Operation::ExclamationMarkEqual) {
|
||||||
|
res = (x != y);
|
||||||
|
} else if (op == Operation::LAngle) {
|
||||||
|
res = (x < y);
|
||||||
|
} else if (op == Operation::RAngle) {
|
||||||
|
res = (x > y);
|
||||||
|
} else if (op == Operation::LAngleEqual) {
|
||||||
|
res = (x <= y);
|
||||||
|
} else if (op == Operation::RAngleEqual) {
|
||||||
|
res = (x >= y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::CallEqualOperator(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) {
|
||||||
|
if (type_variable.id != TypeVariable::none && type_variable.id != another->type_variable.id) {
|
||||||
|
throw std::logic_error("error variable convert");
|
||||||
|
}
|
||||||
|
if (result->type_variable.id != TypeVariable::none && result->type_variable.id != another->type_variable.id) {
|
||||||
|
throw std::logic_error("error variable convert");
|
||||||
|
}
|
||||||
|
result->Clear();
|
||||||
|
result->type_variable.id = another->type_variable.id;
|
||||||
|
result->Allocate();
|
||||||
|
if (op == Operation::Equal) {
|
||||||
|
Clear();
|
||||||
|
type_variable.id = another->type_variable.id;
|
||||||
|
Allocate();
|
||||||
|
}
|
||||||
|
if (another->type_variable.id == TypeVariable::type_int) {
|
||||||
|
CallEqualOperatorInt(another, result, op);
|
||||||
|
} else if (another->type_variable.id == TypeVariable::type_string) {
|
||||||
|
CallEqualOperatorString(another, result, op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::CallEqualOperatorString(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
const std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const {
|
||||||
|
std::string& x = *static_cast<std::string*>(memory);
|
||||||
|
std::string& y = *static_cast<std::string*>(another->memory);
|
||||||
|
std::string& res = *static_cast<std::string*>(result->memory);
|
||||||
|
if (op == Operation::Equal) {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res = x;
|
||||||
|
} else {
|
||||||
|
res = x = y;
|
||||||
|
}
|
||||||
|
} else if (op == Operation::PlusEqual) {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res += x;
|
||||||
|
} else {
|
||||||
|
res = x += y;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::logic_error("invalid operation string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::CallEqualOperatorInt(const std::shared_ptr<VariableInStack>& another,
|
||||||
|
const std::shared_ptr<VariableInStack>& result,
|
||||||
|
const Operation& op) const {
|
||||||
|
int& x = *static_cast<int*>(memory);
|
||||||
|
int& y = *static_cast<int*>(another->memory);
|
||||||
|
int& res = *static_cast<int*>(result->memory);
|
||||||
|
if (op == Operation::Equal) {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res = x;
|
||||||
|
} else {
|
||||||
|
res = x = y;
|
||||||
|
}
|
||||||
|
} else if (op == Operation::PlusEqual) {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res += x;
|
||||||
|
} else {
|
||||||
|
res = x += y;
|
||||||
|
}
|
||||||
|
} else if (op == Operation::MinusEqual) {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res -= x;
|
||||||
|
} else {
|
||||||
|
res = x -= y;
|
||||||
|
}
|
||||||
|
} else if (op == Operation::StarEqual) {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res *= x;
|
||||||
|
} else {
|
||||||
|
res = x *= y;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this == another.get()) {
|
||||||
|
res /= x;
|
||||||
|
} else {
|
||||||
|
res = x /= y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::Clear() {
|
||||||
|
if (memory) {
|
||||||
|
if (type_variable.id == TypeVariable::ID::type_int) {
|
||||||
|
delete static_cast<int*>(memory);
|
||||||
|
} else if (type_variable.id == TypeVariable::ID::type_string) {
|
||||||
|
delete static_cast<std::string*>(memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VariableInStack::Allocate() {
|
||||||
|
if (type_variable.id == TypeVariable::ID::type_int) {
|
||||||
|
memory = new int();
|
||||||
|
} else if (type_variable.id == TypeVariable::ID::type_string) {
|
||||||
|
memory = new std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockWhile::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
if (check) {
|
||||||
|
while (true) {
|
||||||
|
check->Run(stack);
|
||||||
|
auto res = *((int*) stack.back()->memory);
|
||||||
|
stack.pop_back();
|
||||||
|
if (res) {
|
||||||
|
code->Run(stack);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockIf::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
if (check) {
|
||||||
|
check->Run(stack);
|
||||||
|
auto res = *((int*) stack.back()->memory);
|
||||||
|
stack.pop_back();
|
||||||
|
if (res) {
|
||||||
|
code->Run(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockFor::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
while (true) {
|
||||||
|
check->Run(stack);
|
||||||
|
auto res = *((int*) stack.back()->memory);
|
||||||
|
stack.pop_back();
|
||||||
|
if (!res) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code->Run(stack);
|
||||||
|
size_t sz = stack.size();
|
||||||
|
tick->Run(stack);
|
||||||
|
while (stack.size() != sz) {
|
||||||
|
stack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HiddenDeallocateStack::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
stack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeallocateStack::Run(std::vector<std::shared_ptr<VariableInStack>>& stack) {
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
stack.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue