regular to string
This commit is contained in:
parent
0947eeac5d
commit
124a6c17b1
|
@ -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})
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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*");
|
||||
|
|
|
@ -12,4 +12,8 @@ const RegularTree::Node& RegularTree::GetNode() const {
|
|||
void RegularTree::Print() const {
|
||||
node_.Print();
|
||||
}
|
||||
|
||||
std::string RegularTree::ToString() const {
|
||||
return node_.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
209
tests/DFAToRegular/DFAToRegular2.cpp
Normal file
209
tests/DFAToRegular/DFAToRegular2.cpp
Normal 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));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue