diff --git a/include/Lexesis/automata.h b/include/Lexesis/automata.h new file mode 100644 index 0000000..de8bd5d --- /dev/null +++ b/include/Lexesis/automata.h @@ -0,0 +1,46 @@ +#pragma once +#ifndef AUTOMATA_H +#define AUTOMATA_H + +#include +#include +#include +#include +#include + +namespace lxs { + typedef unsigned long long State; + typedef unsigned long long Priority; + + struct Automaton { + State numStates; + std::set accepting; + std::map priority; + std::map acceptingToken; + State starting; + }; + + struct DFA : public Automaton { + std::map > delta; + }; + + struct NFA : public Automaton { + std::map > > delta; + virtual std::set eClose(State); + }; + + struct ENFA : public NFA { + std::map > epsilonTransitions; + virtual std::set eClose(State); + }; + + std::string toDot(const DFA& d); + std::string toDot(const NFA& n); + std::string toDot(const ENFA& e); + + ENFA merge(const std::vector& enfas); + DFA mssc(const NFA& e); + DFA minimize(const DFA& d); +} //namespace lxs + +#endif //AUTOMATA_H diff --git a/include/Lexesis/re.h b/include/Lexesis/re.h new file mode 100644 index 0000000..9671a30 --- /dev/null +++ b/include/Lexesis/re.h @@ -0,0 +1,90 @@ +#pragma once +#ifndef RE_H +#define RE_H + +#include "Lexesis/automata.h" + +#include + +namespace lxs { + class RE + { + public: + virtual ~RE() {} + virtual int toENFA(ENFA& enfa, int attach) = 0; + virtual std::string toRe() = 0; + }; + + class EmptyRE : public RE + { + public: + EmptyRE() {} + ~EmptyRE() {} + virtual int toENFA(ENFA& enfa, int attach); + virtual std::string toRe(); + }; + + class EpsilonRE : public RE + { + public: + EpsilonRE() {} + ~EpsilonRE() {} + virtual int toENFA(ENFA& enfa, int attach); + virtual std::string toRe(); + }; + + class SingleRE : public RE + { + public: + SingleRE(char c) : c(c) {} + ~SingleRE() {} + virtual int toENFA(ENFA& enfa, int attach); + virtual std::string toRe(); + + char c; + }; + + class ConcatRE : public RE + { + public: + ConcatRE(RE* e, RE* f) : e(e), f(f) {} + ~ConcatRE() {delete e; delete f;} + virtual int toENFA(ENFA& enfa, int attach); + virtual std::string toRe(); + + RE* e, *f; + }; + + class StarRE : public RE + { + public: + StarRE(RE* e) : e(e) {} + ~StarRE() {delete e;} + virtual int toENFA(ENFA& enfa, int attach); + virtual std::string toRe(); + + RE* e; + }; + + class PlusRE : public RE + { + public: + PlusRE(RE* e, RE* f) : e(e), f(f) {} + ~PlusRE() {delete e; delete f;} + virtual int toENFA(ENFA& enfa, int attach); + virtual std::string toRe(); + + RE* e, *f; + }; + + RE* parseRE(std::string& input); + + class SyntaxError : public std::runtime_error + { + public: + SyntaxError(const char* w) : std::runtime_error(w) {} + }; + +} //namespace lxs + +#endif //RE_H diff --git a/src/automata.cpp b/src/automata.cpp new file mode 100644 index 0000000..e79d684 --- /dev/null +++ b/src/automata.cpp @@ -0,0 +1,97 @@ +#include "automata.h" + +#include +#include +#include +#include + +namespace lxs { + std::string toDot(const DFA& d) + { + std::string s = "digraph {\nrankdir=LR\nin [shape=point style=invis]"; + + for (State state = 0; state < d.numStates; state++) + { + s += std::to_string(state) + " [label=\"" + std::to_string(state) + "\""; + if (state == d.starting) + s += " color=yellow"; + if (d.accepting.count(state) > 0) + s += " color=green shape=doublecircle"; + s += "]\n"; + } + + for (const auto& tmp : d.delta) + { + const auto& from = tmp.first; + for (const auto& trans : tmp.second) + { + s += std::to_string(from) + " -> " + std::to_string(trans.second) + " [label=\"" + trans.first + "\"]\n"; + } + } + + s += "in -> " + std::to_string(d.starting) + "\n}\n"; + return s; + } + + std::string toDot(const NFA& n) + { + std::string s = "digraph {\nrankdir=LR\nin [shape=point style=invis]\n"; + + for (State state = 0; state < n.numStates; state++) + { + s += std::to_string(state) + " [label=\"" + std::to_string(state) + "\""; + if (state == n.starting) + s += " color=yellow"; + if (n.accepting.count(state) > 0) + s += " color=green shape=doublecircle"; + s += "]\n"; + } + + for (const auto& tmp : n.delta) + { + const auto& from = tmp.first; + for (const auto& trans : tmp.second) + { + for (const auto& to : trans.second) + s += std::to_string(from) + " -> " + std::to_string(to) + " [label=\"" + trans.first + "\"]\n"; + } + } + + s += "in -> " + std::to_string(n.starting) + "\n}\n"; + return s; + } + + std::string toDot(const ENFA& e) + { + std::string s = "digraph {\nrankdir=LR\nin [shape=point style=invis]\n"; + + for (State state = 0; state < e.numStates; state++) + { + s += std::to_string(state) + " [label=\"" + std::to_string(state) + "\""; + if (state == e.starting) + s += " color=yellow"; + if (e.accepting.count(state) > 0) + s += " color=green shape=doublecircle"; + s += "]\n"; + } + + for (const auto& tmp : e.delta) + { + const auto& from = tmp.first; + for (const auto& trans : tmp.second) + { + for (const auto& to : trans.second) + s += std::to_string(from) + " -> " + std::to_string(to) + " [label=\"" + trans.first + "\"]\n"; + } + } + + for (const auto& etrans : e.epsilonTransitions) + { + for (const auto& dest : etrans.second) + s += std::to_string(etrans.first) + " -> " + std::to_string(dest) + " [label=\"ε\"]\n"; + } + + s += "in -> " + std::to_string(e.starting) + "\n}\n"; + return s; + } +} //namespace lxs