From 8efa194ae8d573d9ed9e16febb54e0c3e4763815 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <peckato1@fit.cvut.cz>
Date: Mon, 22 Sep 2014 13:22:40 +0200
Subject: [PATCH] algo: fa2re: Algebraic API

---
 alib2algo/src/conversions/fa2re/Algebraic.cpp | 84 +++++++++++++++++--
 alib2algo/src/conversions/fa2re/Algebraic.h   | 28 +++++--
 2 files changed, 100 insertions(+), 12 deletions(-)

diff --git a/alib2algo/src/conversions/fa2re/Algebraic.cpp b/alib2algo/src/conversions/fa2re/Algebraic.cpp
index 16f1492fb3..44d14dc7c6 100644
--- a/alib2algo/src/conversions/fa2re/Algebraic.cpp
+++ b/alib2algo/src/conversions/fa2re/Algebraic.cpp
@@ -6,16 +6,28 @@
  */
 
 #include "Algebraic.h"
-#include "alphabet/Symbol.h"
-#include "automaton/FSM/DFA.h"
-#include "automaton/FSM/NFA.h"
-#include "automaton/FSM/EpsilonNFA.h"
+
+#include <alphabet/Symbol.h>
+#include <automaton/FSM/DFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <exception/AlibException.h>
+
+#include "../../equations/RightRegularEquationSolver.h"
 
 namespace conversions
 {
 
 namespace fa2re {
 
+regexp::RegExp Algebraic::convert(const automaton::Automaton& automaton) {
+	regexp::RegExp* out = NULL;
+	automaton.getData().Accept((void*) &out, Algebraic::ALGEBRAIC);
+	regexp::RegExp res = std::move(*out);
+	delete out;
+	return res;
+}
+
 template<>
 regexp::UnboundedRegExp Algebraic::convert( const automaton::EpsilonNFA & automaton ) {
 	equations::RightRegularEquationSolver solver;
@@ -25,7 +37,7 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::EpsilonNFA & automa
 		solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) );
 
 	for( const auto & q : automaton.getStates( ) ) {
-		if( isInSet( q, automaton.getFinalStates( ) ) )
+		if( automaton.getFinalStates( ).count( q ) > 0 )
 			solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), regexp::UnboundedRegExpEpsilon { } );
 	}
 
@@ -61,7 +73,7 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::NFA & automaton ) {
 		solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) );
 
 	for( const auto & q : automaton.getStates( ) ) {
-		if( isInSet( q, automaton.getFinalStates( ) ) )
+		if( automaton.getFinalStates( ).count( q ) > 0 )
 			solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), regexp::UnboundedRegExpEpsilon { } );
 	}
 
@@ -91,7 +103,7 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::DFA & automaton ) {
 		solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) );
 
 	for( const auto & q : automaton.getStates( ) ) {
-		if( isInSet( q, automaton.getFinalStates( ) ) )
+		if( automaton.getFinalStates( ).count( q ) > 0 )
 			solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), regexp::UnboundedRegExpEpsilon { } );
 	}
 
@@ -102,6 +114,64 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::DFA & automaton ) {
 	return solver.solve( alphabet::Symbol( alphabet::LabeledSymbol (automaton.getInitialState().getName() ) ) );
 }
 
+
+void Algebraic::Visit(void*, const automaton::UnknownAutomaton&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void Algebraic::Visit(void* data, const automaton::EpsilonNFA& automaton) const {
+	regexp::RegExp* & out = *((regexp::RegExp**) data);
+	out = new regexp::RegExp(this->convert(automaton));
+}
+
+void Algebraic::Visit(void* data, const automaton::NFA& automaton) const {
+	regexp::RegExp* & out = *((regexp::RegExp**) data);
+	out = new regexp::RegExp(this->convert(automaton));
+}
+
+void Algebraic::Visit(void* data, const automaton::DFA& automaton) const {
+	regexp::RegExp* & out = *((regexp::RegExp**) data);
+	out = new regexp::RegExp(this->convert(automaton));
+}
+
+void Algebraic::Visit(void*, const automaton::ExtendedNFA& ) const {
+	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
+}
+
+void Algebraic::Visit(void*, const automaton::CompactNFA& ) const {
+	throw exception::AlibException("Unsupported automaton type CompactNFA");
+}
+
+void Algebraic::Visit(void*, const automaton::DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void Algebraic::Visit(void*, const automaton::SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void Algebraic::Visit(void*, const automaton::InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void Algebraic::Visit(void*, const automaton::VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void Algebraic::Visit(void*, const automaton::NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void Algebraic::Visit(void*, const automaton::SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void Algebraic::Visit(void*, const automaton::OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const Algebraic Algebraic::ALGEBRAIC;
+
 } /* namespace fa2re */
 
 } /* namespace conversions */
diff --git a/alib2algo/src/conversions/fa2re/Algebraic.h b/alib2algo/src/conversions/fa2re/Algebraic.h
index 55dbaca7de..a6fbc2471e 100644
--- a/alib2algo/src/conversions/fa2re/Algebraic.h
+++ b/alib2algo/src/conversions/fa2re/Algebraic.h
@@ -12,10 +12,9 @@
 #include <map>
 #include <queue>
 
+#include <regexp/RegExp.h>
 #include <regexp/unbounded/UnboundedRegExpElements.h>
-
-#include "common/macros.h"
-#include "../../equations/RightRegularEquationSolver.h"
+#include <automaton/Automaton.h>
 
 namespace conversions
 {
@@ -30,15 +29,34 @@ namespace fa2re
  * Converts FA to RE using Brzozowski's algebraic method using right regular equations.
  * Source : Melichar 2.122
  */
-class Algebraic
+class Algebraic : public automaton::VisitableAutomatonBase::const_visitor_type
 {
 public:
 	/**
 	 * Performs conversion.
 	 * @return regular expression equivalent to input automaton.
 	 */
+	static regexp::RegExp convert(const automaton::Automaton& automaton);
+
 	template <class T>
-	static regexp::UnboundedRegExp convert( const T & automaton );
+	static regexp::UnboundedRegExp convert(const T& automaton);
+
+private:
+	void Visit(void*, const automaton::UnknownAutomaton&) const;
+	void Visit(void*, const automaton::EpsilonNFA&) const;
+	void Visit(void*, const automaton::NFA&) const;
+	void Visit(void*, const automaton::DFA&) const;
+	void Visit(void*, const automaton::ExtendedNFA&) const;
+	void Visit(void*, const automaton::CompactNFA&) const;
+	void Visit(void*, const automaton::InputDrivenNPDA&) const;
+	void Visit(void*, const automaton::VisiblyPushdownNPDA&) const;
+	void Visit(void*, const automaton::NPDA&) const;
+	void Visit(void*, const automaton::SinglePopNPDA&) const;
+	void Visit(void*, const automaton::DPDA&) const;
+	void Visit(void*, const automaton::SinglePopDPDA&) const;
+	void Visit(void*, const automaton::OneTapeDTM&) const;
+
+	static const Algebraic ALGEBRAIC;
 };
 
 } /* namespace fa2re */
-- 
GitLab