This commit is contained in:
MaxanRus 2021-09-27 23:12:42 +03:00
parent 8e014193cc
commit 65fffffe8e
3 changed files with 186 additions and 184 deletions

View file

@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES
src/regular/RegularTree.cpp
src/regular/RegularTreeNode.cpp
)
set(TEST_FILES

View file

@ -1,190 +1,6 @@
#include "regular/RegularTree.hpp"
#include <iostream>
#include <exception>
namespace regular {
RegularTree::Node::Node() {}
RegularTree::Node::Node(Type type) : type(type) {}
void RegularTree::Node::Parse(const std::string& regular) {
type = Type::Addition;
ParseCurrentType(std::string_view(regular.c_str(), regular.size()));
Compression();
}
void RegularTree::Node::Print() const {
Print(0);
}
void RegularTree::Node::ParseCurrentType(const std::string_view regular) {
const size_t n = regular.size();
children.clear();
word.clear();
auto AddChild = [this](const std::string_view regular) {
this->children.push_back(std::make_unique<Node>(Type::Addition));
this->children.back()->ParseCurrentType(regular);
};
if (n == 1) {
type = Type::Word;
}
if (type == Type::Addition) {
int balance = 0;
int begin_child = 0;
bool wrapped_brackets = (regular[0] == '(');
for (size_t i = 0; i < n; ++i) {
if (regular[i] == '(') {
++balance;
} else if (regular[i] == ')') {
--balance;
}
if (regular[i] == '|') {
if (balance == 0) {
AddChild(regular.substr(begin_child + wrapped_brackets, i -
begin_child - 2 *
wrapped_brackets));
begin_child = i + 1;
if (i + 1 < n)
wrapped_brackets = (regular[i + 1] == '(');
}
} else {
if (i + 1 == n) {
if (children.size() == 0) {
type = Type::Concatenation;
break;
} else {
AddChild(regular.substr(begin_child + wrapped_brackets, i -
begin_child + 1 - 2 *
wrapped_brackets));
begin_child = i + 1;
if (i + 1 < n)
wrapped_brackets = (regular[i + 1] == '(');
}
} else if (balance == 0) {
wrapped_brackets = false;
}
}
}
}
if (type == Type::Concatenation) {
int balance = 0;
int begin_child = 0;
for (size_t i = 0; i < n; ++i) {
if (regular[i] == '(') {
++balance;
if (balance == 1) {
if (begin_child < i) {
AddChild(regular.substr(begin_child, i - begin_child));
begin_child = i + 1;
}
}
} else if (regular[i] == ')') {
--balance;
if (balance == 0) {
AddChild(regular.substr(begin_child + 1, i - begin_child - 1));
begin_child = i + 1;
}
} else if (i + 1 == n) {
if (balance != 0) {
throw std::logic_error("invalid regular");
}
if (children.size() == 0) {
type = Type::Word;
break;
} else {
AddChild(regular.substr(begin_child, i - begin_child + 1));
begin_child = i + 1;
}
} else if (balance == 0) {
if (regular[i] == '+') {
if (begin_child < i) {
AddChild(regular.substr(begin_child, i - begin_child));
}
children.back()->modifier = Modifier::Plus;
begin_child = i + 1;
} else if (regular[i] == '*') {
if (begin_child < i) {
AddChild(regular.substr(begin_child, i - begin_child));
}
children.back()->modifier = Modifier::Star;
begin_child = i + 1;
}
}
}
}
if (type == Type::Word) {
bool exist_modifire = regular.back() == '+' || regular.back() == '*';
if (regular.back() == '+') {
modifier = Modifier::Plus;
} else if (regular.back() == '*') {
modifier = Modifier::Star;
}
for (size_t i = 0; i < n - exist_modifire; ++i) {
if (regular[i] == '|' || regular[i] == '(' || regular[i] == ')') {
throw std::logic_error("invalid regular");
}
word += regular[i];
}
}
}
void RegularTree::Node::Compression() {
for (auto& i: children) {
i->Compression();
}
if (children.size() == 1 && modifier == Modifier::None) {
auto tmp = std::move(*children[0]);
*this = std::move(tmp);
}
}
void RegularTree::Node::Print(int nesting_level) const {
auto PrintNesingLevel = [](int nesting_level) {
for (int i = 0; i < nesting_level; ++i) {
std::cout << " ";
}
};
PrintNesingLevel(nesting_level);
if (type == Type::Addition) {
std::cout << "Addition";
if (modifier == Modifier::Plus) {
std::cout << "+";
} else if (modifier == Modifier::Star) {
std::cout << "*";
}
std::cout << " " << std::to_string(children.size()) << ":" << std::endl;
} else if (type == Type::Concatenation) {
std::cout << "Concatenation";
if (modifier == Modifier::Plus) {
std::cout << "+";
} else if (modifier == Modifier::Star) {
std::cout << "*";
}
std::cout << " " << children.size() << ":" << std::endl;
} else if (type == Type::Word) {
std::cout << "Word";
if (modifier == Modifier::Plus) {
std::cout << "+";
} else if (modifier == Modifier::Star) {
std::cout << "*";
}
std::cout << ": " << word << std::endl;
}
for (const auto& i: children) {
i->Print(nesting_level + 1);
}
}
RegularTree::RegularTree(const std::string& regular) {
node_.Parse(regular);
}

View file

@ -0,0 +1,185 @@
#include "regular/RegularTree.hpp"
#include <iostream>
using Node = regular::RegularTree::Node;
Node::Node() {}
Node::Node(Type type) : type(type) {}
void Node::Parse(const std::string& regular) {
type = Type::Addition;
ParseCurrentType(std::string_view(regular.c_str(), regular.size()));
Compression();
}
void Node::Print() const {
Print(0);
}
void Node::ParseCurrentType(const std::string_view regular) {
const size_t n = regular.size();
children.clear();
word.clear();
auto AddChild = [this](const std::string_view regular) {
this->children.push_back(std::make_unique<Node>(Type::Addition));
this->children.back()->ParseCurrentType(regular);
};
if (n == 1) {
type = Type::Word;
}
if (type == Type::Addition) {
int balance = 0;
int begin_child = 0;
bool wrapped_brackets = (regular[0] == '(');
for (size_t i = 0; i < n; ++i) {
if (regular[i] == '(') {
++balance;
} else if (regular[i] == ')') {
--balance;
}
if (regular[i] == '|') {
if (balance == 0) {
AddChild(regular.substr(begin_child + wrapped_brackets, i -
begin_child - 2 *
wrapped_brackets));
begin_child = i + 1;
if (i + 1 < n)
wrapped_brackets = (regular[i + 1] == '(');
}
} else {
if (i + 1 == n) {
if (children.size() == 0) {
type = Type::Concatenation;
break;
} else {
AddChild(regular.substr(begin_child + wrapped_brackets, i -
begin_child + 1 - 2 *
wrapped_brackets));
begin_child = i + 1;
if (i + 1 < n)
wrapped_brackets = (regular[i + 1] == '(');
}
} else if (balance == 0) {
wrapped_brackets = false;
}
}
}
}
if (type == Type::Concatenation) {
int balance = 0;
int begin_child = 0;
for (size_t i = 0; i < n; ++i) {
if (regular[i] == '(') {
++balance;
if (balance == 1) {
if (begin_child < i) {
AddChild(regular.substr(begin_child, i - begin_child));
begin_child = i + 1;
}
}
} else if (regular[i] == ')') {
--balance;
if (balance == 0) {
AddChild(regular.substr(begin_child + 1, i - begin_child - 1));
begin_child = i + 1;
}
} else if (i + 1 == n) {
if (balance != 0) {
throw std::logic_error("invalid regular");
}
if (children.size() == 0) {
type = Type::Word;
break;
} else {
AddChild(regular.substr(begin_child, i - begin_child + 1));
begin_child = i + 1;
}
} else if (balance == 0) {
if (regular[i] == '+') {
if (begin_child < i) {
AddChild(regular.substr(begin_child, i - begin_child));
}
children.back()->modifier = Modifier::Plus;
begin_child = i + 1;
} else if (regular[i] == '*') {
if (begin_child < i) {
AddChild(regular.substr(begin_child, i - begin_child));
}
children.back()->modifier = Modifier::Star;
begin_child = i + 1;
}
}
}
}
if (type == Type::Word) {
bool exist_modifire = regular.back() == '+' || regular.back() == '*';
if (regular.back() == '+') {
modifier = Modifier::Plus;
} else if (regular.back() == '*') {
modifier = Modifier::Star;
}
for (size_t i = 0; i < n - exist_modifire; ++i) {
if (regular[i] == '|' || regular[i] == '(' || regular[i] == ')') {
throw std::logic_error("invalid regular");
}
word += regular[i];
}
}
}
void Node::Compression() {
for (auto& i: children) {
i->Compression();
}
if (children.size() == 1 && modifier == Modifier::None) {
auto tmp = std::move(*children[0]);
*this = std::move(tmp);
}
}
void Node::Print(int nesting_level) const {
auto PrintNesingLevel = [](int nesting_level) {
for (int i = 0; i < nesting_level; ++i) {
std::cout << " ";
}
};
PrintNesingLevel(nesting_level);
if (type == Type::Addition) {
std::cout << "Addition";
if (modifier == Modifier::Plus) {
std::cout << "+";
} else if (modifier == Modifier::Star) {
std::cout << "*";
}
std::cout << " " << std::to_string(children.size()) << ":" << std::endl;
} else if (type == Type::Concatenation) {
std::cout << "Concatenation";
if (modifier == Modifier::Plus) {
std::cout << "+";
} else if (modifier == Modifier::Star) {
std::cout << "*";
}
std::cout << " " << children.size() << ":" << std::endl;
} else if (type == Type::Word) {
std::cout << "Word";
if (modifier == Modifier::Plus) {
std::cout << "+";
} else if (modifier == Modifier::Star) {
std::cout << "*";
}
std::cout << ": " << word << std::endl;
}
for (const auto& i: children) {
i->Print(nesting_level + 1);
}
}