regular to string
This commit is contained in:
parent
0947eeac5d
commit
124a6c17b1
|
@ -36,6 +36,7 @@ set(TEST_FILES
|
||||||
tests/regularToDFA/RegularToDFA.cpp
|
tests/regularToDFA/RegularToDFA.cpp
|
||||||
tests/DFAToRegular/DFAToRegular.cpp
|
tests/DFAToRegular/DFAToRegular.cpp
|
||||||
tests/invertFDFA/InvertFDFA.cpp
|
tests/invertFDFA/InvertFDFA.cpp
|
||||||
|
tests/DFAToRegular/DFAToRegular2.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(Formalang src/main.cpp ${SOURCE_FILES})
|
add_executable(Formalang src/main.cpp ${SOURCE_FILES})
|
||||||
|
|
|
@ -25,15 +25,18 @@ class RegularTree {
|
||||||
std::string word;
|
std::string word;
|
||||||
Type type;
|
Type type;
|
||||||
Modifier modifier = Modifier::None;
|
Modifier modifier = Modifier::None;
|
||||||
|
std::string ToString() const;
|
||||||
private:
|
private:
|
||||||
void ParseCurrentType(const std::string_view);
|
void ParseCurrentType(const std::string_view);
|
||||||
void Compression();
|
void Compression();
|
||||||
|
void Compression2();
|
||||||
void Print(int nesting_level) const;
|
void Print(int nesting_level) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
RegularTree(const std::string&);
|
RegularTree(const std::string&);
|
||||||
const Node& GetNode() const;
|
const Node& GetNode() const;
|
||||||
void Print() const;
|
void Print() const;
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Node node_;
|
Node node_;
|
||||||
|
|
|
@ -64,7 +64,8 @@ int main() {
|
||||||
auto s = DFAGraphToRegular(std::move(DFA_graph));
|
auto s = DFAGraphToRegular(std::move(DFA_graph));
|
||||||
std::cout << s << std::endl;
|
std::cout << s << std::endl;
|
||||||
r = RegularTree(s);
|
r = RegularTree(s);
|
||||||
r.Print();
|
// r.Print();
|
||||||
|
std::cout << r.ToString() << std::endl;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
RegularTree r("a*");
|
RegularTree r("a*");
|
||||||
|
|
|
@ -12,4 +12,8 @@ const RegularTree::Node& RegularTree::GetNode() const {
|
||||||
void RegularTree::Print() const {
|
void RegularTree::Print() const {
|
||||||
node_.Print();
|
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) {
|
void Node::Parse(const std::string& regular) {
|
||||||
type = Type::Addition;
|
type = Type::Addition;
|
||||||
ParseCurrentType(std::string_view(regular.c_str(), regular.size()));
|
ParseCurrentType(std::string_view(regular.c_str(), regular.size()));
|
||||||
Compression();
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
Compression();
|
||||||
|
Compression2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::Print() const {
|
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 {
|
void Node::Print(int nesting_level) const {
|
||||||
auto PrintNesingLevel = [](int nesting_level) {
|
auto PrintNesingLevel = [](int nesting_level) {
|
||||||
for (int i = 0; i < nesting_level; ++i) {
|
for (int i = 0; i < nesting_level; ++i) {
|
||||||
|
@ -198,3 +220,35 @@ void Node::Print(int nesting_level) const {
|
||||||
i->Print(nesting_level + 1);
|
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