This commit is contained in:
MaxanRus 2021-12-27 15:50:56 +03:00
parent ba2bf4b404
commit 88ca215573
3 changed files with 400 additions and 417 deletions

View file

@ -18,6 +18,7 @@ struct Node {
void Insert(Node*);
void InsertBefore(Node*);
virtual void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) = 0;
virtual ~Node() {}
};
@ -54,241 +55,62 @@ struct TypeVariable {
};
TypeVariable() {}
TypeVariable(ID id) : id(id) {}
ID id = ID::none;
size_t size;
};
struct DeallocateStack : public Node {
DeallocateStack(size_t count) : count(count) {}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
for (size_t i = 0; i < count; ++i) {
stack.pop_back();
}
}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
size_t count;
};
struct HiddenDeallocateStack : public Node {
HiddenDeallocateStack(size_t count) : count(count) {}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
for (size_t i = 0; i < count; ++i) {
stack.pop_back();
}
}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
size_t count;
};
struct VariableInStack {
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) {
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 CallOperator(std::shared_ptr<VariableInStack>& another, std::shared_ptr<VariableInStack>& result, Operation op);
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;
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 {
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;
std::string type;
std::string name;
@ -299,13 +121,8 @@ struct Variable : public Node {
struct Container : public Node {
void AddChildren(Node*);
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {
Node* cur = children_begin;
while (cur) {
cur->Run(stack);
cur = cur->next;
}
}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
Node* children_begin = nullptr;
Node* children_end = nullptr;
@ -313,26 +130,17 @@ struct Container : public Node {
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 {
CreateVariables(size_t count) : count(count) {}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override {}
size_t count;
};
struct CallFunction : public Node {
CallFunction(std::string name_function) : name_function(std::move(name_function)) {}
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
std::string name_function;
std::vector<Expression*> parameters;
@ -342,52 +150,15 @@ using stack_pointer = size_t;
struct Expression : public Node {
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;
e_type2->AddStackPointer(e_type1->count);
}
}
void AddStackPointer(stack_pointer d) {
position_result += d;
}
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);
}
}
Expression() {}
Expression(Types type1, Types type2, Operation op);
void AddStackPointer(stack_pointer d);
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
static size_t GetPriority(Operation);
static PriorityType GetPriorityType(Operation);
static Operation Convert(Lexer::LexerToken::Type);
@ -397,59 +168,25 @@ struct Expression : public Node {
size_t count;
};
struct FOR : public Node {
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();
}
}
}
struct BlockFor : public Node {
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
Variable* var = nullptr;
Expression* check = nullptr;
Expression* tick = nullptr;
CodeBlock* code = nullptr;
};
struct IF : public Node {
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);
}
}
}
struct BlockIf : public Node {
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
Expression* check = nullptr;
CodeBlock* code = nullptr;
};
struct WHILE : public Node {
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;
}
}
}
}
struct BlockWhile : public Node {
void Run(std::vector<std::shared_ptr<VariableInStack>>& stack) override;
Expression* check = nullptr;
CodeBlock* code = nullptr;
};
@ -457,6 +194,7 @@ struct WHILE : public Node {
class SyntaxTree {
public:
SyntaxTree() {}
void PushLexerTokenList(const LexerTokenList&);
void Compile();
void Run();
@ -474,12 +212,12 @@ class SyntaxTree {
void PushExpression(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushParametersFunction(CallFunction*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushCallFunction(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushFOR(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushSignatureFOR(FOR*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushIF(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushSignatureIF(IF*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushWHILE(Container*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushSignatureWHILE(WHILE*, const LexerTokenList&, LexerTokenList::const_iterator&);
void PushBlockFor(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it);
void PushSignatureBlockFor(BlockFor* node_for, const LexerTokenList& list, LexerTokenList::const_iterator& it);
void PushBlockIf(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it);
void PushSignatureBlockIf(BlockIf* node_if, const LexerTokenList& list, LexerTokenList::const_iterator& it);
void PushBlockWhile(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it);
void PushSignatureBlockWhile(BlockWhile* node_if, const LexerTokenList& list, LexerTokenList::const_iterator& it);
Expression* ParseExpression(LexerTokenList::const_iterator, LexerTokenList::const_iterator);
Expression* ParseExpression(const LexerTokenList&, LexerTokenList::const_iterator&);
void PushDeallocateStack(Node*, size_t);