regular to string

This commit is contained in:
MaxanRus 2021-10-05 18:13:31 +03:00
parent 0947eeac5d
commit 124a6c17b1
6 changed files with 274 additions and 2 deletions

View file

@ -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})

View file

@ -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_;

View file

@ -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*");

View file

@ -12,4 +12,8 @@ const RegularTree::Node& RegularTree::GetNode() const {
void RegularTree::Print() const {
node_.Print();
}
std::string RegularTree::ToString() const {
return node_.ToString();
}
}

View file

@ -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;
}

View file

@ -0,0 +1,209 @@
#include <gtest/gtest.h>
#include <random>
#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<char> 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<char> 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<char> 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<char> 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));
}
}