diff --git a/CMakeLists.txt b/CMakeLists.txt index 527b984..ed99c37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCE_FILES src/regular/RegularTree.cpp + src/regular/RegularTreeNode.cpp ) set(TEST_FILES diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp index 712c3d2..3cde403 100644 --- a/src/regular/RegularTree.cpp +++ b/src/regular/RegularTree.cpp @@ -1,190 +1,6 @@ #include "regular/RegularTree.hpp" -#include -#include 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(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); } diff --git a/src/regular/RegularTreeNode.cpp b/src/regular/RegularTreeNode.cpp new file mode 100644 index 0000000..7b4637b --- /dev/null +++ b/src/regular/RegularTreeNode.cpp @@ -0,0 +1,185 @@ +#include "regular/RegularTree.hpp" +#include + +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(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); + } +}