From 124a6c17b1d3399874f87a6f76b2ee03d8d6bb19 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 18:13:31 +0300 Subject: [PATCH] regular to string --- CMakeLists.txt | 1 + include/regular/RegularTree.hpp | 3 + src/main.cpp | 3 +- src/regular/RegularTree.cpp | 4 + src/regular/RegularTreeNode.cpp | 56 ++++++- tests/DFAToRegular/DFAToRegular2.cpp | 209 +++++++++++++++++++++++++++ 6 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 tests/DFAToRegular/DFAToRegular2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bd98941..6395d82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(TEST_FILES tests/regularToDFA/RegularToDFA.cpp tests/DFAToRegular/DFAToRegular.cpp tests/invertFDFA/InvertFDFA.cpp + tests/DFAToRegular/DFAToRegular2.cpp ) add_executable(Formalang src/main.cpp ${SOURCE_FILES}) diff --git a/include/regular/RegularTree.hpp b/include/regular/RegularTree.hpp index a564142..3863b3d 100644 --- a/include/regular/RegularTree.hpp +++ b/include/regular/RegularTree.hpp @@ -25,15 +25,18 @@ class RegularTree { std::string word; Type type; Modifier modifier = Modifier::None; + std::string ToString() const; private: void ParseCurrentType(const std::string_view); void Compression(); + void Compression2(); void Print(int nesting_level) const; }; RegularTree(const std::string&); const Node& GetNode() const; void Print() const; + std::string ToString() const; private: Node node_; diff --git a/src/main.cpp b/src/main.cpp index 47887ed..d4946b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,8 @@ int main() { auto s = DFAGraphToRegular(std::move(DFA_graph)); std::cout << s << std::endl; r = RegularTree(s); - r.Print(); + // r.Print(); + std::cout << r.ToString() << std::endl; } return 0; RegularTree r("a*"); diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp index 3cde403..70285b7 100644 --- a/src/regular/RegularTree.cpp +++ b/src/regular/RegularTree.cpp @@ -12,4 +12,8 @@ const RegularTree::Node& RegularTree::GetNode() const { void RegularTree::Print() const { node_.Print(); } + +std::string RegularTree::ToString() const { + return node_.ToString(); +} } diff --git a/src/regular/RegularTreeNode.cpp b/src/regular/RegularTreeNode.cpp index f103293..ac297ae 100644 --- a/src/regular/RegularTreeNode.cpp +++ b/src/regular/RegularTreeNode.cpp @@ -8,7 +8,10 @@ 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(); + for (int i = 0; i < 10; ++i) { + Compression(); + Compression2(); + } } void Node::Print() const { @@ -160,6 +163,25 @@ void Node::Compression() { } } +void Node::Compression2() { + for (auto& i: children) { + i->Compression2(); + } + bool f = type == Type::Concatenation; + for (auto& i: children) { + f &= i->modifier == Modifier::None; + f &= i->type == Type::Word; + } + if (f) { + auto tmp = std::move(*children[0]); + tmp.modifier = modifier; + for (int i = 1; i < children.size(); ++i) { + tmp.word += children[i]->word; + } + *this = std::move(tmp); + } +} + void Node::Print(int nesting_level) const { auto PrintNesingLevel = [](int nesting_level) { for (int i = 0; i < nesting_level; ++i) { @@ -198,3 +220,35 @@ void Node::Print(int nesting_level) const { i->Print(nesting_level + 1); } } + +std::string regular::RegularTree::Node::ToString() const { + std::string res; + if (type == Type::Word) { + res = word; + if (modifier == Modifier::Plus) + res = "(" + res + ")+"; + else if (modifier == Modifier::Star) + res = "(" + res + ")*"; + } else if (type == Type::Concatenation) { + for (auto& i: children) { + res += i->ToString(); + } + if (modifier == Modifier::Plus) + res = "(" + res + ")+"; + else if (modifier == Modifier::Star) + res = "(" + res + ")*"; + } else if (type == Type::Addition) { + for (auto& i: children) { + res += i->ToString(); + res += "|"; + } + if (res.size()) + res.pop_back(); + res = "(" + res + ")"; + if (modifier == Modifier::Plus) + res += "+"; + else if (modifier == Modifier::Star) + res += "*"; + } + return res; +} diff --git a/tests/DFAToRegular/DFAToRegular2.cpp b/tests/DFAToRegular/DFAToRegular2.cpp new file mode 100644 index 0000000..17603ab --- /dev/null +++ b/tests/DFAToRegular/DFAToRegular2.cpp @@ -0,0 +1,209 @@ +#include +#include +#include "regular/RegularTree.hpp" +#include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToMinDFA.hpp" +#include "converters/DFAToRegular.hpp" + +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; + +extern std::mt19937 rnd; + +extern std::string GenerateRandomString(std::vector alphabet, size_t len); + +TEST(DFA_to_regular2, a_star) { + RegularTree r("a*"); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + + std::string s = ""; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } +} + +TEST(DFA_to_regular2, a_plus) { + std::string regulars[] = {"a+", "(a)+", "(a+)"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string s = ""; + ASSERT_EQ(DFA_graph.Accepted(s), false); + s += "a"; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } + } +} + +TEST(DFA_to_regular2, abc) { + std::string regulars[] = {"abc"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("abc"), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + if (s == "abc") continue; + ASSERT_EQ(DFA_graph.Accepted(s), false); + } + } +} + +TEST(DFA_to_regular2, a_or_b_or_c) { + std::string regulars[] = {}; + for (const auto& regular: regulars) { + RegularTree r("a|b|c"); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("a"), true); + ASSERT_EQ(DFA_graph.Accepted("b"), true); + ASSERT_EQ(DFA_graph.Accepted("c"), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + if (s == "a") continue; + if (s == "b") continue; + if (s == "c") continue; + ASSERT_EQ(DFA_graph.Accepted(s), false); + } + } +} + +TEST(DFA_to_regular2, a_star_or_b_star_or_c_star) { + std::string regulars[] = {"a*|b*|c*", "(a*)|(b*|c*)", "(a*|b*|c*)", "((a*)|(b*)|(c*))"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + if (s.size() == 0) + return true; + else { + if (s.size() == 1) + return *s.begin() != 'd'; + else + return false; + } + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + + ASSERT_EQ(DFA_graph.Accepted(s), check(s)); + } + } +} + +TEST(DFA_to_regular2, _a_star_or_b_star_or_c_star_plus) { + RegularTree r("(a*|b*|c*)+"); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + + ASSERT_EQ(DFA_graph.Accepted(s), check(s)); + } +} + +TEST(DFA_to_regular2, _a_or_b_or_c_star_plus) { + RegularTree r("(a|b|c*)+"); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + + ASSERT_EQ(DFA_graph.Accepted(s), check(s)); + } +}