diff --git a/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp b/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp
index a20c8c8c01aa5fa90570bddb0f1cff2a78f4b6e5..8949dfb5b9824399e3e19687c526f0a5e2892204 100644
--- a/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp
+++ b/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp
@@ -7,8 +7,6 @@
 
 #include "ToRegExpStateElimination.h"
 
-#include <regexp/unbounded/UnboundedRegExp.h>
-
 #include "../../regexp/simplify/RegExpOptimize.h"
 #include "../../regexp/transform/RegExpAlternate.h"
 #include "../../regexp/transform/RegExpConcatenate.h"
@@ -23,9 +21,9 @@ regexp::RegExp ToRegExpStateElimination::convert(const automaton::Automaton& aut
 }
 
 template<class T>
-regexp::RegExp ToRegExpStateElimination::convert(const T& automaton) {
+regexp::UnboundedRegExp ToRegExpStateElimination::convert(const T& automaton) {
 	if(automaton.getFinalStates().size() == 0)
-		return regexp::RegExp(regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpEmpty())));
+		return regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpEmpty()));
 
 	// steps 1 + 2
 	automaton::ExtendedNFA extendedAutomaton(automaton);
@@ -41,17 +39,17 @@ regexp::RegExp ToRegExpStateElimination::convert(const T& automaton) {
 		extendedAutomaton = eliminateState(extendedAutomaton, state);
 
 	// step 4
-	return regexp::simplify::RegExpOptimize::optimize(regexp::RegExpConcatenate::concatenate(
-				transition(extendedAutomaton, extendedAutomaton.getInitialState(), *extendedAutomaton.getFinalStates().begin()),
-				regexp::RegExpIterate::iterate(transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin()))));
+	regexp::UnboundedRegExpStructure finalStateLoop = regexp::RegExpIterate::iterate ( transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin()));
+	regexp::UnboundedRegExpStructure initialToFinalState = regexp::RegExpConcatenate::concatenate ( transition(extendedAutomaton, extendedAutomaton.getInitialState(), *extendedAutomaton.getFinalStates().begin()),finalStateLoop );
+	return regexp::UnboundedRegExp(regexp::simplify::RegExpOptimize::optimize(initialToFinalState));
 }
 
-auto ToRegExpStateEliminationEpsilonNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::EpsilonNFA < > >(ToRegExpStateElimination::convert);
-auto ToRegExpStateEliminationMultiInitialStateNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::MultiInitialStateNFA < > >(ToRegExpStateElimination::convert);
-auto ToRegExpStateEliminationNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::NFA < > >(ToRegExpStateElimination::convert);
-auto ToRegExpStateEliminationDFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::DFA<>>(ToRegExpStateElimination::convert);
-auto ToRegExpStateEliminationExtendedNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::ExtendedNFA>(ToRegExpStateElimination::convert);
-auto ToRegExpStateEliminationCompactNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::CompactNFA < > >(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationEpsilonNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::UnboundedRegExp, automaton::EpsilonNFA < > >(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationMultiInitialStateNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::UnboundedRegExp, automaton::MultiInitialStateNFA < > >(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::UnboundedRegExp, automaton::NFA < > >(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationDFA = ToRegExpStateElimination::RegistratorWrapper<regexp::UnboundedRegExp, automaton::DFA<>>(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationExtendedNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::UnboundedRegExp, automaton::ExtendedNFA>(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationCompactNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::UnboundedRegExp, automaton::CompactNFA < > >(ToRegExpStateElimination::convert);
 
 
 automaton::ExtendedNFA ToRegExpStateElimination::eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const label::Label& q) {
@@ -65,11 +63,11 @@ automaton::ExtendedNFA ToRegExpStateElimination::eliminateState(const automaton:
 	{
 		for(const auto& r : newAutomaton.getStates())
 		{
-			regexp::RegExp concat = transition(extendedAutomaton, p, q);
+			regexp::UnboundedRegExpStructure concat = transition(extendedAutomaton, p, q);
 			concat = regexp::RegExpConcatenate::concatenate(concat, regexp::RegExpIterate::iterate(transition(extendedAutomaton, q, q)));
 			concat = regexp::RegExpConcatenate::concatenate(concat, transition(extendedAutomaton, q, r));
 
-			regexp::RegExp alt = regexp::RegExpAlternate::alternate(concat, transition(extendedAutomaton, p, r));
+			regexp::UnboundedRegExpStructure alt = regexp::RegExpAlternate::alternate(concat, transition(extendedAutomaton, p, r));
 
 			newAutomaton.addTransition(p, regexp::simplify::RegExpOptimize::optimize(alt), r);
 		}
@@ -78,8 +76,8 @@ automaton::ExtendedNFA ToRegExpStateElimination::eliminateState(const automaton:
 	return newAutomaton;
 }
 
-const regexp::RegExp ToRegExpStateElimination::transition(const automaton::ExtendedNFA& automaton, const label::Label& from, const label::Label& to) {
-	regexp::RegExp ret(regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpEmpty { })));
+const regexp::UnboundedRegExpStructure ToRegExpStateElimination::transition(const automaton::ExtendedNFA& automaton, const label::Label& from, const label::Label& to) {
+	regexp::UnboundedRegExpStructure ret(regexp::UnboundedRegExpEmpty { });
 
 	for(const auto& transition: automaton.getTransitionsFromState(from))
 		if(transition.second.count(to) > 0)
@@ -95,8 +93,8 @@ void ToRegExpStateElimination::extendExtendedNFA(automaton::ExtendedNFA& automat
 		label::Label q0 = label::createUniqueLabel(initState, automaton.getStates());
 		automaton.addState(q0);
 
-		regexp::UnboundedRegExp regexp { regexp::UnboundedRegExpStructure ( regexp::UnboundedRegExpEpsilon() ) };
-		automaton.addTransition(q0, regexp::RegExp{regexp}, initState);
+		regexp::UnboundedRegExpStructure regexp { regexp::UnboundedRegExpEpsilon() };
+		automaton.addTransition(q0, regexp, initState);
 
 		automaton.setInitialState(q0);
 	}
@@ -107,8 +105,8 @@ void ToRegExpStateElimination::extendExtendedNFA(automaton::ExtendedNFA& automat
 		automaton.addState(f);
 
 		for(const auto &state : automaton.getFinalStates() ) {
-			regexp::UnboundedRegExp regexp { regexp::UnboundedRegExpStructure ( regexp::UnboundedRegExpEpsilon() ) };
-			automaton.addTransition(state, regexp::RegExp{regexp}, f);
+			regexp::UnboundedRegExpStructure regexp { regexp::UnboundedRegExpEpsilon() };
+			automaton.addTransition(state, regexp, f);
 
 			automaton.removeFinalState(state);
 		}
diff --git a/alib2algo/src/automaton/convert/ToRegExpStateElimination.h b/alib2algo/src/automaton/convert/ToRegExpStateElimination.h
index eea72db830ebcd5ecb22987b2059409a90477082..8f3593aae4cbd33cfd3a682d5701e3b327049c4a 100644
--- a/alib2algo/src/automaton/convert/ToRegExpStateElimination.h
+++ b/alib2algo/src/automaton/convert/ToRegExpStateElimination.h
@@ -11,6 +11,7 @@
 #include <core/multipleDispatch.hpp>
 
 #include <regexp/RegExp.h>
+#include <regexp/unbounded/UnboundedRegExp.h>
 
 #include <automaton/Automaton.h>
 #include <automaton/FSM/DFA.h>
@@ -37,12 +38,12 @@ public:
 	static regexp::RegExp convert(const automaton::Automaton& automaton);
 
 	template<class T>
-	static regexp::RegExp convert(const T& automaton);
+	static regexp::UnboundedRegExp convert(const T& automaton);
 
 private:
 	static void extendExtendedNFA(automaton::ExtendedNFA& automaton);
 
-	static const regexp::RegExp transition(const automaton::ExtendedNFA& automaton, const label::Label& from, const label::Label& to);
+	static const regexp::UnboundedRegExpStructure transition(const automaton::ExtendedNFA& automaton, const label::Label& from, const label::Label& to);
 
 	static automaton::ExtendedNFA eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const label::Label& state);
 };
diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
index cbd5eee23536bb5afd44376825c950aad4ef01cd..cf2350b8d94399529c89fe22e4b61465779708d9 100644
--- a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
+++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
@@ -85,7 +85,7 @@ std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClos
 	std::map<label::Label, std::set<label::Label>> res;
 	std::map<label::Label, std::set<label::Label>> step;
 
-	for(const std::pair<const std::pair<label::Label, regexp::RegExp>, std::set<label::Label> >& transition : fsm.getTransitions() )
+	for(const std::pair<const std::pair<label::Label, regexp::UnboundedRegExpStructure>, std::set<label::Label> >& transition : fsm.getTransitions() )
 		if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) )
 			step[transition.first.first].insert(transition.second.begin(), transition.second.end());
 
diff --git a/alib2algo/src/equations/LeftRegularEquationSolver.cpp b/alib2algo/src/equations/LeftRegularEquationSolver.cpp
index 41c517e5e7bcd1a871a22c7adc869d072251ba9c..9e335c901669eb0c6f07c69368be234c77cfa848 100644
--- a/alib2algo/src/equations/LeftRegularEquationSolver.cpp
+++ b/alib2algo/src/equations/LeftRegularEquationSolver.cpp
@@ -74,7 +74,7 @@ regexp::UnboundedRegExp LeftRegularEquationSolver::eliminate(void) {
 		}
 	}
 
-	return regexp::simplify::RegExpOptimize::optimize(regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(std::move( equationFinal.find(*nonterminalSymbolsByDepth.begin())->second))));
+	return regexp::UnboundedRegExp(regexp::simplify::RegExpOptimize::optimize(regexp::UnboundedRegExpStructure(std::move( equationFinal.find(*nonterminalSymbolsByDepth.begin())->second))));
 }
 
 } /* namespace equations */
diff --git a/alib2algo/src/equations/RightRegularEquationSolver.cpp b/alib2algo/src/equations/RightRegularEquationSolver.cpp
index 05756e16f24b8051688bd6fd2d46d4f2b6d370ae..ba020d4c87bc2e76e9d8bec1b71902ba478d43ff 100644
--- a/alib2algo/src/equations/RightRegularEquationSolver.cpp
+++ b/alib2algo/src/equations/RightRegularEquationSolver.cpp
@@ -74,7 +74,7 @@ regexp::UnboundedRegExp RightRegularEquationSolver::eliminate(void) {
 		}
 	}
 
-	return regexp::simplify::RegExpOptimize::optimize(regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(std::move( equationFinal.find(*nonterminalSymbolsByDepth.begin())->second))));
+	return regexp::UnboundedRegExp(regexp::simplify::RegExpOptimize::optimize(regexp::UnboundedRegExpStructure(std::move( equationFinal.find(*nonterminalSymbolsByDepth.begin())->second))));
 }
 
 } /* namespace equations */
diff --git a/alib2algo/src/regexp/properties/RegExpEmpty.cpp b/alib2algo/src/regexp/properties/RegExpEmpty.cpp
index 3d3155936ff6aa27726154043fe287440b276f63..e1da9e26d5f7bbfdfb7fe275887c1dbca86c6c98 100644
--- a/alib2algo/src/regexp/properties/RegExpEmpty.cpp
+++ b/alib2algo/src/regexp/properties/RegExpEmpty.cpp
@@ -23,8 +23,12 @@ bool RegExpEmpty::languageIsEmpty(const regexp::FormalRegExpElement& regexp) {
 	return out;
 }
 
+bool RegExpEmpty::languageIsEmpty(const regexp::FormalRegExpStructure& regexp) {
+	return languageIsEmpty(regexp.getStructure());
+}
+
 bool RegExpEmpty::languageIsEmpty(const regexp::FormalRegExp& regexp) {
-	return languageIsEmpty(regexp.getRegExp().getStructure());
+	return languageIsEmpty(regexp.getRegExp());
 }
 
 auto RegExpEmptyFormalRegExp = RegExpEmpty::RegistratorWrapper<bool, regexp::FormalRegExp>( RegExpEmpty::languageIsEmpty);
@@ -35,8 +39,12 @@ bool RegExpEmpty::languageIsEmpty(const regexp::UnboundedRegExpElement& regexp)
 	return out;
 }
 
+bool RegExpEmpty::languageIsEmpty(const regexp::UnboundedRegExpStructure& regexp) {
+	return languageIsEmpty(regexp.getStructure());
+}
+
 bool RegExpEmpty::languageIsEmpty(const regexp::UnboundedRegExp& regexp) {
-	return languageIsEmpty(regexp.getRegExp().getStructure());
+	return languageIsEmpty(regexp.getRegExp());
 }
 
 auto RegExpEmptyUnboundedRegExp = RegExpEmpty::RegistratorWrapper<bool, regexp::UnboundedRegExp>( RegExpEmpty::languageIsEmpty);
diff --git a/alib2algo/src/regexp/properties/RegExpEmpty.h b/alib2algo/src/regexp/properties/RegExpEmpty.h
index 945096ba328f9b5b139cbf4e398f7c3f0448d4bb..2551bccad7fb147afcaa5e626d5fd89a5832d962 100644
--- a/alib2algo/src/regexp/properties/RegExpEmpty.h
+++ b/alib2algo/src/regexp/properties/RegExpEmpty.h
@@ -29,10 +29,12 @@ public:
 	static bool languageIsEmpty(const regexp::RegExp& regexp);
 
 	static bool languageIsEmpty(const regexp::FormalRegExpElement& regexp);
+	static bool languageIsEmpty(const regexp::FormalRegExpStructure& regexp);
 	static bool languageIsEmpty(const regexp::FormalRegExp& regexp);
 
-	static bool languageIsEmpty(const regexp::UnboundedRegExp& regexp);
 	static bool languageIsEmpty(const regexp::UnboundedRegExpElement& regexp);
+	static bool languageIsEmpty(const regexp::UnboundedRegExpStructure& regexp);
+	static bool languageIsEmpty(const regexp::UnboundedRegExp& regexp);
 
 	class Unbounded : public regexp::UnboundedRegExpElement::Visitor {
 	public:
diff --git a/alib2algo/src/regexp/properties/RegExpEpsilon.cpp b/alib2algo/src/regexp/properties/RegExpEpsilon.cpp
index 94fc179be8ba818cb80d941db995f497828d348c..bf0714503b74b9547fa0e0e96e2e295c71368e8c 100644
--- a/alib2algo/src/regexp/properties/RegExpEpsilon.cpp
+++ b/alib2algo/src/regexp/properties/RegExpEpsilon.cpp
@@ -23,8 +23,12 @@ bool RegExpEpsilon::languageContainsEpsilon(const regexp::FormalRegExpElement& r
 	return out;
 }
 
+bool RegExpEpsilon::languageContainsEpsilon(const regexp::FormalRegExpStructure& regexp) {
+	return languageContainsEpsilon(regexp.getStructure());
+}
+
 bool RegExpEpsilon::languageContainsEpsilon(const regexp::FormalRegExp& regexp) {
-	return languageContainsEpsilon(regexp.getRegExp().getStructure());
+	return languageContainsEpsilon(regexp.getRegExp());
 }
 
 auto RegExpEpsilonFormalRegExp = RegExpEpsilon::RegistratorWrapper<bool, regexp::FormalRegExp>( RegExpEpsilon::languageContainsEpsilon);
@@ -35,8 +39,12 @@ bool RegExpEpsilon::languageContainsEpsilon(const regexp::UnboundedRegExpElement
 	return out;
 }
 
+bool RegExpEpsilon::languageContainsEpsilon(const regexp::UnboundedRegExpStructure& regexp) {
+	return languageContainsEpsilon(regexp.getStructure());
+}
+
 bool RegExpEpsilon::languageContainsEpsilon(const regexp::UnboundedRegExp& regexp) {
-	return languageContainsEpsilon(regexp.getRegExp().getStructure());
+	return languageContainsEpsilon(regexp.getRegExp());
 }
 
 auto RegExpEpsilonUnboundedRegExp = RegExpEpsilon::RegistratorWrapper<bool, regexp::UnboundedRegExp>( RegExpEpsilon::languageContainsEpsilon);
diff --git a/alib2algo/src/regexp/properties/RegExpEpsilon.h b/alib2algo/src/regexp/properties/RegExpEpsilon.h
index 8485e273f46b9f16b5eb7c9f36a87e84393e9ee7..4ce6bb7349e94e71ace22779d97a11f8a5c42ef5 100644
--- a/alib2algo/src/regexp/properties/RegExpEpsilon.h
+++ b/alib2algo/src/regexp/properties/RegExpEpsilon.h
@@ -31,10 +31,12 @@ public:
 	static bool languageContainsEpsilon(const regexp::RegExp& regexp);
 
 	static bool languageContainsEpsilon(const regexp::FormalRegExpElement& regexp);
+	static bool languageContainsEpsilon(const regexp::FormalRegExpStructure& regexp);
 	static bool languageContainsEpsilon(const regexp::FormalRegExp& regexp);
 
-	static bool languageContainsEpsilon(const regexp::UnboundedRegExp& regexp);
 	static bool languageContainsEpsilon(const regexp::UnboundedRegExpElement& regexp);
+	static bool languageContainsEpsilon(const regexp::UnboundedRegExpStructure& regexp);
+	static bool languageContainsEpsilon(const regexp::UnboundedRegExp& regexp);
 
 private:
 	void Visit(void* data, const regexp::UnboundedRegExpAlternation& alternation) const;
diff --git a/alib2algo/src/regexp/simplify/RegExpOptimize.cpp b/alib2algo/src/regexp/simplify/RegExpOptimize.cpp
index c11146e6bea794c54522fc99dd24a669d807f22b..9c23d659fbf7c3628e55eef37a65627410993456 100644
--- a/alib2algo/src/regexp/simplify/RegExpOptimize.cpp
+++ b/alib2algo/src/regexp/simplify/RegExpOptimize.cpp
@@ -22,22 +22,30 @@ regexp::RegExp RegExpOptimize::optimize(const regexp::RegExp& regexp) {
 	return dispatch(regexp.getData());
 }
 
-FormalRegExp RegExpOptimize::optimize( FormalRegExp const & regexp ) {
-	FormalRegExpElement* optimized = optimizeInner( regexp.getRegExp( ).getStructure ( ) );
-
-	return FormalRegExp ( regexp::FormalRegExpStructure ( std::manage_move ( optimized ) ) );
+FormalRegExp RegExpOptimize::optimize( const FormalRegExp & regexp ) {
+	return regexp::FormalRegExp ( RegExpOptimize::optimize ( regexp.getRegExp ( ) ) );
 }
 
 auto RegExpOptimizeFormalRegEpx = RegExpOptimize::RegistratorWrapper<FormalRegExp, FormalRegExp>(RegExpOptimize::optimize);
 
-UnboundedRegExp RegExpOptimize::optimize( UnboundedRegExp const & regexp ) {
-	UnboundedRegExpElement* optimized = optimizeInner( regexp.getRegExp( ).getStructure( ) );
+FormalRegExpStructure RegExpOptimize::optimize( const FormalRegExpStructure & regexp ) {
+	FormalRegExpElement* optimized = optimizeInner( regexp.getStructure ( ) );
+
+	return regexp::FormalRegExpStructure ( std::manage_move ( optimized ) );
+}
 
-	return UnboundedRegExp ( regexp::UnboundedRegExpStructure ( std::manage_move ( optimized ) ) );
+UnboundedRegExp RegExpOptimize::optimize( const UnboundedRegExp & regexp ) {
+	return regexp::UnboundedRegExp ( RegExpOptimize::optimize ( regexp.getRegExp ( ) ) );
 }
 
 auto RegExpOptimizeUnboundedRegEpx = RegExpOptimize::RegistratorWrapper<UnboundedRegExp, UnboundedRegExp>(RegExpOptimize::optimize);
 
+UnboundedRegExpStructure RegExpOptimize::optimize( const UnboundedRegExpStructure & regexp ) {
+	UnboundedRegExpElement* optimized = optimizeInner( regexp.getStructure( ) );
+
+	return regexp::UnboundedRegExpStructure ( std::manage_move ( optimized ) );
+}
+
 } /* namespace regexp */
 
 } /* namespace simplify */
diff --git a/alib2algo/src/regexp/simplify/RegExpOptimize.h b/alib2algo/src/regexp/simplify/RegExpOptimize.h
index 71e7d6b3b7512fa6e7e964f2a4ad572d948beb15..af93db38e919c47b87622ed362dc9e81b62f14cd 100644
--- a/alib2algo/src/regexp/simplify/RegExpOptimize.h
+++ b/alib2algo/src/regexp/simplify/RegExpOptimize.h
@@ -66,11 +66,13 @@ public:
 	static regexp::RegExp optimize( const regexp::RegExp & regexp );
 
 	static regexp::UnboundedRegExp optimize( const regexp::UnboundedRegExp & regexp );
+	static regexp::UnboundedRegExpStructure optimize( const regexp::UnboundedRegExpStructure & regexp );
 	static void optimize( regexp::UnboundedRegExpAlternation & regexp );
 	static void optimize( regexp::UnboundedRegExpConcatenation & regexp );
 	static void optimize( regexp::UnboundedRegExpIteration & regexp );
 
 	static regexp::FormalRegExp optimize( const regexp::FormalRegExp & regexp );
+	static regexp::FormalRegExpStructure optimize( const regexp::FormalRegExpStructure & regexp );
 	static void optimize( regexp::FormalRegExpElement & regexp );
 private:
 	static regexp::FormalRegExpElement * optimizeInner( const regexp::FormalRegExpElement & node );
diff --git a/alib2algo/src/regexp/transform/RegExpAlternate.cpp b/alib2algo/src/regexp/transform/RegExpAlternate.cpp
index c522c39e42fc1df41758ab45f318ab7699a0cab4..2590e99c81f834794b31f844f5cc9bccacb07224 100644
--- a/alib2algo/src/regexp/transform/RegExpAlternate.cpp
+++ b/alib2algo/src/regexp/transform/RegExpAlternate.cpp
@@ -17,18 +17,26 @@ regexp::RegExp RegExpAlternate::alternate(const regexp::RegExp& first, const reg
 }
 
 regexp::FormalRegExp RegExpAlternate::alternate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second) {
-	return regexp::FormalRegExp(regexp::FormalRegExpStructure(regexp::FormalRegExpAlternation(first.getRegExp().getStructure(), second.getRegExp().getStructure())));
+	return regexp::FormalRegExp(RegExpAlternate::alternate(first.getRegExp(), second.getRegExp()));
 }
 
 auto RegExpAlternateFormalRegExp = RegExpAlternate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp>(RegExpAlternate::alternate);
 
+regexp::FormalRegExpStructure RegExpAlternate::alternate(const regexp::FormalRegExpStructure& first, const regexp::FormalRegExpStructure& second) {
+	return regexp::FormalRegExpStructure(regexp::FormalRegExpAlternation(first.getStructure(), second.getStructure()));
+}
+
 regexp::UnboundedRegExp RegExpAlternate::alternate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) {
-	regexp::UnboundedRegExpAlternation con;
-	con.appendElement(first.getRegExp().getStructure());
-	con.appendElement(second.getRegExp().getStructure());
-	return regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(con));
+	return regexp::UnboundedRegExp(RegExpAlternate::alternate(first.getRegExp(), second.getRegExp()));
 }
 
 auto RegExpAlternateUnboundedRegExp = RegExpAlternate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpAlternate::alternate);
 
+regexp::UnboundedRegExpStructure RegExpAlternate::alternate(const regexp::UnboundedRegExpStructure& first, const regexp::UnboundedRegExpStructure& second) {
+	regexp::UnboundedRegExpAlternation con;
+	con.appendElement(first.getStructure());
+	con.appendElement(second.getStructure());
+	return regexp::UnboundedRegExpStructure(con);
+}
+
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpAlternate.h b/alib2algo/src/regexp/transform/RegExpAlternate.h
index 5a8d8898a6646ce728d11f887ed6f00cdc609540..7a5ad2f978ff3e15cccd81e57bf57e4409027798 100644
--- a/alib2algo/src/regexp/transform/RegExpAlternate.h
+++ b/alib2algo/src/regexp/transform/RegExpAlternate.h
@@ -25,7 +25,9 @@ public:
 	static regexp::RegExp alternate(const regexp::RegExp& first, const regexp::RegExp& second);
 
 	static regexp::FormalRegExp alternate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second);
+	static regexp::FormalRegExpStructure alternate(const regexp::FormalRegExpStructure& first, const regexp::FormalRegExpStructure& second);
 	static regexp::UnboundedRegExp alternate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second);
+	static regexp::UnboundedRegExpStructure alternate(const regexp::UnboundedRegExpStructure& first, const regexp::UnboundedRegExpStructure& second);
 };
 
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpConcatenate.cpp b/alib2algo/src/regexp/transform/RegExpConcatenate.cpp
index a04990afa2b737b08e2f73ab9e36928801ea8be8..a9e3a6590688f12ddca39f32a4d85fbc479c830b 100644
--- a/alib2algo/src/regexp/transform/RegExpConcatenate.cpp
+++ b/alib2algo/src/regexp/transform/RegExpConcatenate.cpp
@@ -17,18 +17,26 @@ regexp::RegExp RegExpConcatenate::concatenate(const regexp::RegExp& first, const
 }
 
 regexp::FormalRegExp RegExpConcatenate::concatenate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second) {
-	return regexp::FormalRegExp(regexp::FormalRegExpStructure(regexp::FormalRegExpConcatenation(first.getRegExp().getStructure(), second.getRegExp().getStructure())));
+	return regexp::FormalRegExp(RegExpConcatenate::concatenate(first.getRegExp(), second.getRegExp()));
 }
 
 auto RegExpConcatenateFormalRegExp = RegExpConcatenate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp>(RegExpConcatenate::concatenate);
 
+regexp::FormalRegExpStructure RegExpConcatenate::concatenate(const regexp::FormalRegExpStructure& first, const regexp::FormalRegExpStructure& second) {
+	return regexp::FormalRegExpStructure(regexp::FormalRegExpConcatenation(first.getStructure(), second.getStructure()));
+}
+
 regexp::UnboundedRegExp RegExpConcatenate::concatenate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) {
-	regexp::UnboundedRegExpConcatenation con;
-	con.appendElement(first.getRegExp().getStructure());
-	con.appendElement(second.getRegExp().getStructure());
-	return regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(con));
+	return regexp::UnboundedRegExp(RegExpConcatenate::concatenate(first.getRegExp(), second.getRegExp()));
 }
 
 auto RegExpConcatenateUnboundedRegExp = RegExpConcatenate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpConcatenate::concatenate);
 
+regexp::UnboundedRegExpStructure RegExpConcatenate::concatenate(const regexp::UnboundedRegExpStructure& first, const regexp::UnboundedRegExpStructure& second) {
+	regexp::UnboundedRegExpConcatenation con;
+	con.appendElement(first.getStructure());
+	con.appendElement(second.getStructure());
+	return regexp::UnboundedRegExpStructure(con);
+}
+
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpConcatenate.h b/alib2algo/src/regexp/transform/RegExpConcatenate.h
index b34c81bc2f325762803700aa9eb9625e2ecfe479..f1b8c1ecee8a018c936dc9ac2d6986f5d51a1b86 100644
--- a/alib2algo/src/regexp/transform/RegExpConcatenate.h
+++ b/alib2algo/src/regexp/transform/RegExpConcatenate.h
@@ -25,7 +25,9 @@ public:
 	static regexp::RegExp concatenate(const regexp::RegExp& first, const regexp::RegExp& second);
 
 	static regexp::FormalRegExp concatenate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second);
+	static regexp::FormalRegExpStructure concatenate(const regexp::FormalRegExpStructure& first, const regexp::FormalRegExpStructure& second);
 	static regexp::UnboundedRegExp concatenate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second);
+	static regexp::UnboundedRegExpStructure concatenate(const regexp::UnboundedRegExpStructure& first, const regexp::UnboundedRegExpStructure& second);
 };
 
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpDerivation.h b/alib2algo/src/regexp/transform/RegExpDerivation.h
index fc5230ff1e1b6a04a6b73483e470038211482a88..1c24962014aa18376cf8d450d6a3542c67bb2fe0 100644
--- a/alib2algo/src/regexp/transform/RegExpDerivation.h
+++ b/alib2algo/src/regexp/transform/RegExpDerivation.h
@@ -29,8 +29,6 @@ namespace regexp {
  */
 class RegExpDerivation : public std::SingleDispatch < RegExpDerivation, regexp::RegExp, const regexp::RegExpBase &, const string::LinearString < >&> {
 public:
-	RegExpDerivation() {}
-
 	/**
 	 * @param regexp RegExp to derivate
 	 * @param string String to derivate given RegExp over
diff --git a/alib2algo/src/regexp/transform/RegExpIterate.cpp b/alib2algo/src/regexp/transform/RegExpIterate.cpp
index 3728e4d8702417e45bd9fc2a4740f63e1e1fe547..4a41497054bbed2e331fc70fcc7e1fc6da8a0611 100644
--- a/alib2algo/src/regexp/transform/RegExpIterate.cpp
+++ b/alib2algo/src/regexp/transform/RegExpIterate.cpp
@@ -16,15 +16,23 @@ regexp::RegExp RegExpIterate::iterate(const regexp::RegExp& regexp) {
 }
 
 regexp::FormalRegExp RegExpIterate::iterate(const regexp::FormalRegExp& regexp) {
-	return regexp::FormalRegExp(regexp::FormalRegExpStructure(regexp::FormalRegExpIteration(regexp.getRegExp().getStructure())));
+	return regexp::FormalRegExp(RegExpIterate::iterate(regexp.getRegExp()));
 }
 
 auto RegExpIterateFormalRegExpFormalRegExp = RegExpIterate::RegistratorWrapper<regexp::FormalRegExp, regexp::FormalRegExp>(RegExpIterate::iterate);
 
+regexp::FormalRegExpStructure RegExpIterate::iterate(const regexp::FormalRegExpStructure& regexp) {
+	return regexp::FormalRegExpStructure(regexp::FormalRegExpIteration(regexp.getStructure()));
+}
+
 regexp::UnboundedRegExp RegExpIterate::iterate(const regexp::UnboundedRegExp& regexp) {
-	return regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpIteration(regexp.getRegExp().getStructure())));
+	return regexp::UnboundedRegExp(RegExpIterate::iterate(regexp.getRegExp()));
 }
 
 auto RegExpIterateUnboundedRegExpUnboundedRegExp = RegExpIterate::RegistratorWrapper<regexp::UnboundedRegExp, regexp::UnboundedRegExp>(RegExpIterate::iterate);
 
+regexp::UnboundedRegExpStructure RegExpIterate::iterate(const regexp::UnboundedRegExpStructure& regexp) {
+	return regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpIteration(regexp.getStructure()));
+}
+
 } /* namespace regexp */
diff --git a/alib2algo/src/regexp/transform/RegExpIterate.h b/alib2algo/src/regexp/transform/RegExpIterate.h
index b95cd846f6b7a6f7693485f1f4c9c6ee3d2187d7..8ffd9fc2425d3d90e5f018ca4e44cf618bc270d3 100644
--- a/alib2algo/src/regexp/transform/RegExpIterate.h
+++ b/alib2algo/src/regexp/transform/RegExpIterate.h
@@ -25,7 +25,9 @@ public:
 	static regexp::RegExp iterate(const regexp::RegExp& regexp);
 
 	static regexp::FormalRegExp iterate(const regexp::FormalRegExp& regexp);
+	static regexp::FormalRegExpStructure iterate(const regexp::FormalRegExpStructure& regexp);
 	static regexp::UnboundedRegExp iterate(const regexp::UnboundedRegExp& regexp);
+	static regexp::UnboundedRegExpStructure iterate(const regexp::UnboundedRegExpStructure& regexp);
 };
 
 } /* namespace regexp */
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index f30b92bd7b5a6a59b43ff48e9c1c89ea6b1f225d..bcf67af0b443b43b764590e1063e17ecfb1c1415 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -11,7 +11,9 @@
 #include "MultiInitialStateNFA.h"
 #include "NFA.h"
 #include "DFA.h"
-#include "../../regexp/RegExp.h"
+#include "../../regexp/unbounded/UnboundedRegExpStructure.h"
+#include "../../regexp/unbounded/UnboundedRegExpConcatenation.h"
+#include "../../regexp/unbounded/UnboundedRegExpSymbol.h"
 #include <ostream>
 #include <algorithm>
 #include <sstream>
@@ -35,7 +37,12 @@ ExtendedNFA::ExtendedNFA ( label::Label initialState ) : ExtendedNFA ( std::set
 
 ExtendedNFA::ExtendedNFA ( const CompactNFA < > & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( transition.first.second ) ) );
+		regexp::UnboundedRegExpConcatenation con;
+
+		for ( auto & symbol : transition.first.second )
+			con.appendElement ( regexp::UnboundedRegExpSymbol ( symbol ) );
+
+		std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure ( std::move ( con ) ) );
 		transitions[key] = transition.second;
 	}
 }
@@ -43,10 +50,10 @@ ExtendedNFA::ExtendedNFA ( const CompactNFA < > & other ) : ExtendedNFA ( other.
 ExtendedNFA::ExtendedNFA ( const EpsilonNFA < > & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
 		if ( transition.first.second.is < string::Epsilon < > > ( ) ) {
-			std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( ) ) );
+			std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure ( ) );
 			transitions[key] = transition.second;
 		} else {
-			std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( transition.first.second.get < alphabet::Symbol > ( ) ) ) );
+			std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure ( regexp::UnboundedRegExpSymbol ( transition.first.second.get < alphabet::Symbol > ( ) ) ) );
 			transitions[key] = transition.second;
 		}
 	}
@@ -54,24 +61,24 @@ ExtendedNFA::ExtendedNFA ( const EpsilonNFA < > & other ) : ExtendedNFA ( other.
 
 ExtendedNFA::ExtendedNFA ( const MultiInitialStateNFA < > & other ) : ExtendedNFA ( other.getStates ( ) + std::set < label::Label > { label::createUniqueLabel ( label::InitialStateLabel::INITIAL_STATE_LABEL, other.getStates ( ) ) }, other.getInputAlphabet ( ), label::createUniqueLabel ( label::InitialStateLabel::INITIAL_STATE_LABEL, other.getStates ( ) ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( transition.first.second ) ) );
+		std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure ( regexp::UnboundedRegExpSymbol ( transition.first.second ) ) );
 		transitions[key] = transition.second;
 	}
 
-	std::pair < label::Label, regexp::RegExp > key = std::make_pair ( this->getInitialState ( ), regexp::RegExp ( regexp::regexpFrom ( ) ) );
+	std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( this->getInitialState ( ), regexp::UnboundedRegExpStructure ( ) );
 	transitions[key] = other.getInitialStates ( );
 }
 
 ExtendedNFA::ExtendedNFA ( const NFA <> & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( transition.first.second ) ) );
+		std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure ( regexp::UnboundedRegExpSymbol ( transition.first.second ) ) );
 		transitions[key] = transition.second;
 	}
 }
 
 ExtendedNFA::ExtendedNFA ( const DFA<> & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( transition.first.second ) ) );
+		std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure ( regexp::UnboundedRegExpSymbol ( transition.first.second ) ) );
 		transitions[key].insert ( transition.second );
 	}
 }
@@ -84,11 +91,11 @@ AutomatonBase * ExtendedNFA::plunder ( ) && {
 	return new ExtendedNFA ( std::move ( * this ) );
 }
 
-bool ExtendedNFA::addTransition ( label::Label from, regexp::RegExp input, label::Label to ) {
+bool ExtendedNFA::addTransition ( label::Label from, regexp::UnboundedRegExpStructure input, label::Label to ) {
 	if ( !getStates ( ).count ( from ) )
 		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist." );
 
-	const std::set < alphabet::Symbol > & inputRegExpAlphabet = input.getAlphabet ( );
+	std::set < alphabet::Symbol > inputRegExpAlphabet = input.getStructure ( ).computeMinimalAlphabet ( );
 
 	 // Transition regexp's alphabet must be subset of automaton's alphabet
 	if ( !std::includes ( getInputAlphabet ( ).begin ( ), getInputAlphabet ( ).end ( ), inputRegExpAlphabet.begin ( ), inputRegExpAlphabet.end ( ) ) )
@@ -97,41 +104,41 @@ bool ExtendedNFA::addTransition ( label::Label from, regexp::RegExp input, label
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist." );
 
-	std::pair < label::Label, regexp::RegExp > key = std::make_pair ( std::move ( from ), std::move ( input ) );
+	std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( std::move ( from ), std::move ( input ) );
 
 	return transitions[std::move ( key )].insert ( std::move ( to ) ).second;
 }
 
-bool ExtendedNFA::removeTransition ( const label::Label & from, const regexp::RegExp & input, const label::Label & to ) {
-	std::pair < label::Label, regexp::RegExp > key = std::make_pair ( from, input );
+bool ExtendedNFA::removeTransition ( const label::Label & from, const regexp::UnboundedRegExpStructure & input, const label::Label & to ) {
+	std::pair < label::Label, regexp::UnboundedRegExpStructure > key = std::make_pair ( from, input );
 
 	return transitions[key].erase ( to );
 }
 
-const std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > & ExtendedNFA::getTransitions ( ) const {
+const std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > & ExtendedNFA::getTransitions ( ) const {
 	return transitions;
 }
 
-std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > ExtendedNFA::getTransitionsFromState ( const label::Label & from ) const {
+std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > ExtendedNFA::getTransitionsFromState ( const label::Label & from ) const {
 	if ( !getStates ( ).count ( from ) )
 		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
 
-	std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > transitionsFromState;
+	std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > transitionsFromState;
 
-	for ( const std::pair < const std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > & transition : transitions )
+	for ( const std::pair < const std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > & transition : transitions )
 		if ( transition.first.first == from )
 			transitionsFromState.insert ( make_pair ( transition.first, transition.second ) );
 
 	return transitionsFromState;
 }
 
-std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > ExtendedNFA::getTransitionsToState ( const label::Label & to ) const {
+std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > ExtendedNFA::getTransitionsToState ( const label::Label & to ) const {
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
 
-	std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > transitionsToState;
+	std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > transitionsToState;
 
-	for ( const std::pair < const std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > & transition : transitions )
+	for ( const std::pair < const std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > & transition : transitions )
 		if ( transition.second.find ( to ) != transition.second.end ( ) )
 			transitionsToState.insert ( make_pair ( transition.first, transition.second ) );
 
@@ -186,7 +193,7 @@ ExtendedNFA ExtendedNFA::parse ( std::deque < sax::Token >::iterator & input ) {
 void ExtendedNFA::parseTransition ( std::deque < sax::Token >::iterator & input, ExtendedNFA & automaton ) {
 	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "transition" );
 	label::Label from = AutomatonFromXMLParser::parseTransitionFrom < label::Label > ( input );
-	regexp::RegExp inputRegexp = AutomatonFromXMLParser::parseTransitionInputRegexp ( input );
+	regexp::UnboundedRegExpStructure inputRegexp = AutomatonFromXMLParser::parseTransitionInputRegexp ( input );
 	label::Label to = AutomatonFromXMLParser::parseTransitionTo < label::Label > ( input );
 	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "transition" );
 
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h
index 8cf10ca94196739a7212b3e1c83305fba9393704..04317cbc7b69451388ea5d2617bd40a6d864bc72 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.h
@@ -33,7 +33,7 @@ class InitialState;
 
 class ExtendedNFA : public AutomatonBase, public std::Components < ExtendedNFA, alphabet::Symbol, std::tuple < InputAlphabet >, std::tuple < >, label::Label, std::tuple < States, FinalStates >, std::tuple < InitialState > > {
 protected:
-	std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > transitions;
+	std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > transitions;
 
 public:
 	explicit ExtendedNFA ( label::Label initialState );
@@ -115,29 +115,29 @@ public:
 	 * @param next next state
 	 * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton
 	 */
-	bool addTransition ( label::Label current, regexp::RegExp input, label::Label next );
+	bool addTransition ( label::Label current, regexp::UnboundedRegExpStructure input, label::Label next );
 
 	/**
 	 * Removes transition from the automaton.
 	 * @param transition transition to remove
 	 * @throws AutomatonException when transition doesn't exists.
 	 */
-	bool removeTransition ( const label::Label & current, const regexp::RegExp & input, const label::Label & next );
+	bool removeTransition ( const label::Label & current, const regexp::UnboundedRegExpStructure & input, const label::Label & next );
 
 	/**
 	 * @return automaton transitions
 	 */
-	const std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > & getTransitions ( ) const;
+	const std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > & getTransitions ( ) const;
 
 	/**
 	 * @return automaton transitions from state
 	 */
-	std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > getTransitionsFromState ( const label::Label & from ) const;
+	std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > getTransitionsFromState ( const label::Label & from ) const;
 
 	/**
 	 * @return automaton transitions to state
 	 */
-	std::map < std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > getTransitionsToState ( const label::Label & from ) const;
+	std::map < std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > getTransitionsToState ( const label::Label & from ) const;
 
 	virtual int compare ( const ObjectBase & other ) const {
 		if ( std::type_index ( typeid ( * this ) ) == std::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other );
@@ -172,9 +172,11 @@ template < >
 class ComponentConstraint< automaton::ExtendedNFA, alphabet::Symbol, automaton::InputAlphabet > {
 public:
 	static bool used ( const automaton::ExtendedNFA & automaton, const alphabet::Symbol & symbol ) {
-		for ( const std::pair < const std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > & transition : automaton.getTransitions ( ) )
-			if ( transition.first.second.getAlphabet ( ).count ( symbol ) == 1 )
+		for ( const std::pair < const std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > & transition : automaton.getTransitions ( ) ) {
+			std::set < alphabet::Symbol > alphabet = transition.first.second.getStructure ( ).computeMinimalAlphabet ( );
+			if ( alphabet.count ( symbol ) )
 				return true;
+		}
 
 		return false;
 	}
@@ -197,7 +199,7 @@ public:
 		if ( automaton.getFinalStates ( ).count ( state ) )
 			return true;
 
-		for ( const std::pair < const std::pair < label::Label, regexp::RegExp >, std::set < label::Label > > & transition : automaton.getTransitions ( ) )
+		for ( const std::pair < const std::pair < label::Label, regexp::UnboundedRegExpStructure >, std::set < label::Label > > & transition : automaton.getTransitions ( ) )
 			if ( ( transition.first.first == state ) || ( transition.second.find ( state ) != transition.second.end ( ) ) )
 				return true;
 
diff --git a/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp b/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp
index 09f12d1e503875d3f3890b86f73fb8d3b3f7d47f..f7447626c82f6afc2609c6512cf40e774cd999a0 100644
--- a/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp
+++ b/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp
@@ -32,9 +32,9 @@ Shift AutomatonFromXMLParser::parseTransitionShift ( std::deque < sax::Token >::
 	return shift;
 }
 
-regexp::RegExp AutomatonFromXMLParser::parseTransitionInputRegexp ( std::deque < sax::Token >::iterator & input ) {
+regexp::UnboundedRegExpStructure AutomatonFromXMLParser::parseTransitionInputRegexp ( std::deque < sax::Token >::iterator & input ) {
 	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "input" );
-	regexp::RegExp result ( alib::xmlApi < regexp::RegExp >::parse ( input ) );
+	regexp::UnboundedRegExpStructure result ( alib::xmlApi < regexp::UnboundedRegExpStructure >::parse ( input ) );
 	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "input" );
 
 	return result;
diff --git a/alib2data/src/automaton/common/AutomatonFromXMLParser.h b/alib2data/src/automaton/common/AutomatonFromXMLParser.h
index 779148d498556b7c7a7764e014f0016459788a74..8ed3829487f2884c39155afc1cbff6ca8edc019f 100644
--- a/alib2data/src/automaton/common/AutomatonFromXMLParser.h
+++ b/alib2data/src/automaton/common/AutomatonFromXMLParser.h
@@ -15,7 +15,7 @@
 #include <map>
 #include "Shift.h"
 #include <core/xmlApi.hpp>
-#include "../../regexp/RegExpFeatures.h"
+#include "../../regexp/unbounded/UnboundedRegExpStructure.h"
 #include <alphabet/RankedSymbol.h>
 
 namespace automaton {
@@ -93,7 +93,7 @@ public:
 	static std::vector<SymbolType> parseTransitionOutputSymbolMultiple(std::deque<sax::Token>::iterator& input);
 
 	static Shift parseTransitionShift(std::deque<sax::Token>::iterator& input);
-	static regexp::RegExp parseTransitionInputRegexp(std::deque<sax::Token>::iterator& input);
+	static regexp::UnboundedRegExpStructure parseTransitionInputRegexp(std::deque<sax::Token>::iterator& input);
 };
 
 template<class T>
diff --git a/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp b/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp
index 29bceacce05bb8adb42549a4f0216629fad70833..0a1d8516950cd67ec52ce51668b9e38a92a11be6 100644
--- a/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp
+++ b/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp
@@ -12,9 +12,9 @@
 
 namespace automaton {
 
-void AutomatonToXMLComposer::composeTransitionInputRegexp(std::deque<sax::Token>& out, const regexp::RegExp& regexp) {
+void AutomatonToXMLComposer::composeTransitionInputRegexp(std::deque<sax::Token>& out, const regexp::UnboundedRegExpStructure& regexp) {
 	out.emplace_back("input", sax::Token::TokenType::START_ELEMENT);
-	alib::xmlApi<regexp::RegExp>::compose(out, regexp);
+	alib::xmlApi<regexp::UnboundedRegExpStructure>::compose(out, regexp);
 	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
 }
 
diff --git a/alib2data/src/automaton/common/AutomatonToXMLComposer.h b/alib2data/src/automaton/common/AutomatonToXMLComposer.h
index c6b551ceea722f970fa101a10d0f16ba14eeb0b5..f6f30a85041bc6c4527d38f3db79ccefaeed32eb 100644
--- a/alib2data/src/automaton/common/AutomatonToXMLComposer.h
+++ b/alib2data/src/automaton/common/AutomatonToXMLComposer.h
@@ -16,7 +16,7 @@
 #include "Shift.h"
 #include <sax/Token.h>
 #include <core/xmlApi.hpp>
-#include "../../regexp/RegExpFeatures.h"
+#include "../../regexp/unbounded/UnboundedRegExpStructure.h"
 #include <alphabet/RankedSymbol.h>
 
 namespace automaton {
@@ -88,7 +88,7 @@ public:
 	template<class SymbolType>
 	static void composeTransitionOutputSymbolMultiple(std::deque<sax::Token>&, const std::vector<SymbolType>& symbols);
 
-	static void composeTransitionInputRegexp(std::deque<sax::Token>&, const regexp::RegExp& regexp);
+	static void composeTransitionInputRegexp(std::deque<sax::Token>&, const regexp::UnboundedRegExpStructure& regexp);
 
 	static void composeTransitionShift(std::deque<sax::Token>&, Shift shift);
 };
diff --git a/alib2data/test-src/automaton/AutomatonTest.cpp b/alib2data/test-src/automaton/AutomatonTest.cpp
index 566a7f9fb7b4e7ae5bae10cf2f51ea11845f0eb7..98081d720de50110231efc4a2f5315fbc208a419 100644
--- a/alib2data/test-src/automaton/AutomatonTest.cpp
+++ b/alib2data/test-src/automaton/AutomatonTest.cpp
@@ -173,10 +173,10 @@ void AutomatonTest::testExtendedNFAAlphabet() {
 	badConcat.appendElement(regexp::UnboundedRegExpSymbol(alphabet::symbolFrom('b')));
 	badConcat.appendElement(regexp::UnboundedRegExpSymbol(alphabet::symbolFrom('d')));
 
-	CPPUNIT_ASSERT_THROW(automaton.addTransition(s0, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(badConcat))}, s1), automaton::AutomatonException);
-	CPPUNIT_ASSERT_NO_THROW(automaton.addTransition(s0, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(goodConcat1))}, s1));
-	CPPUNIT_ASSERT_NO_THROW(automaton.addTransition(s0, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(goodConcat2))}, s1));
-	CPPUNIT_ASSERT_NO_THROW(automaton.addTransition(s0, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpEpsilon()))}, s1));
+	CPPUNIT_ASSERT_THROW(automaton.addTransition(s0, regexp::UnboundedRegExpStructure(badConcat), s1), automaton::AutomatonException);
+	CPPUNIT_ASSERT_NO_THROW(automaton.addTransition(s0, regexp::UnboundedRegExpStructure(goodConcat1), s1));
+	CPPUNIT_ASSERT_NO_THROW(automaton.addTransition(s0, regexp::UnboundedRegExpStructure(goodConcat2), s1));
+	CPPUNIT_ASSERT_NO_THROW(automaton.addTransition(s0, regexp::UnboundedRegExpStructure(regexp::UnboundedRegExpEpsilon()), s1));
 }
 
 void AutomatonTest::testNPDATransitions() {
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
index 299216e099530b21da20550a74e1a5ced653dd93..0f3e53bfac15bcfaf779e5c90183a073a43a172a 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
@@ -104,7 +104,7 @@ std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClos
 	std::set<label::Label> nonvisited = fsm.getStates();
 
 	std::map<label::Label, std::set<label::Label>> epsilonTransitions;
-	for(const std::pair<const std::pair<label::Label, regexp::RegExp>, std::set<label::Label> >& transition : fsm.getTransitions() )
+	for(const std::pair<const std::pair<label::Label, regexp::UnboundedRegExpStructure>, std::set<label::Label> >& transition : fsm.getTransitions() )
 		if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) )
 			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
 
diff --git a/alib2str/src/regexp/RegExpFromStringParser.cpp b/alib2str/src/regexp/RegExpFromStringParser.cpp
index 576182712b8bb4689e797167e62e6ab4dc33e537..9bd787e0d8357ac4c91f9d29dfa0a2b88feeab83 100644
--- a/alib2str/src/regexp/RegExpFromStringParser.cpp
+++ b/alib2str/src/regexp/RegExpFromStringParser.cpp
@@ -21,13 +21,17 @@ RegExp RegExpFromStringParser::parseRegExp(std::istream& input) {
 	return parseRegExp(input, std::set<FEATURES>({FEATURES::FORMAL, FEATURES::UNBOUNDED}));
 }
 
-RegExp RegExpFromStringParser::parseRegExp(std::istream& input, const std::set<FEATURES>& features) {
+UnboundedRegExpStructure RegExpFromStringParser::parseUnboundedRegExpStructure(std::istream& input) {
 	std::rvalue_ref < UnboundedRegExpElement > element = alternation(input);
-	UnboundedRegExp regexp(regexp::UnboundedRegExpStructure(std::move(element)));
+	return regexp::UnboundedRegExpStructure(std::move(element));
+}
+
+RegExp RegExpFromStringParser::parseRegExp(std::istream& input, const std::set<FEATURES>& features) {
+	UnboundedRegExp regexp { RegExpFromStringParser::parseUnboundedRegExpStructure ( input ) };
 
-	if(features.count(FEATURES::UNBOUNDED)) return RegExp{regexp};
+	if(features.count(FEATURES::UNBOUNDED)) return RegExp { std::move ( regexp ) };
 
-	if(features.count(FEATURES::FORMAL)) return RegExp{FormalRegExp{regexp}};
+	if(features.count(FEATURES::FORMAL)) return RegExp { FormalRegExp { std::move ( regexp ) } };
 
 	throw exception::CommonException("Invalid input");
 }
diff --git a/alib2str/src/regexp/RegExpFromStringParser.h b/alib2str/src/regexp/RegExpFromStringParser.h
index 38d50abe63b4b7e39a3c418072c76d0bff9cf62f..4a2a0b67a9cf24c22014d8767f78c6a87b9993f8 100644
--- a/alib2str/src/regexp/RegExpFromStringParser.h
+++ b/alib2str/src/regexp/RegExpFromStringParser.h
@@ -29,6 +29,7 @@ class RegExpFromStringParser {
 	static std::rvalue_ref < UnboundedRegExpElement > star(std::istream& input, UnboundedRegExpElement && elem);
 
 public:
+	static UnboundedRegExpStructure parseUnboundedRegExpStructure(std::istream& input);
 	static RegExp parseRegExp(std::istream& input);
 	static RegExp parseRegExp(std::istream& input, const std::set<FEATURES>& features);
 };
diff --git a/alib2str/src/regexp/RegExpStringApi.cpp b/alib2str/src/regexp/RegExpStringApi.cpp
index 72f2e805b09917eb3a282ca3bd3bfac13b36f3e2..d53bdc3d51dffa2c0a742aa2fbb79a2e432b3b33 100644
--- a/alib2str/src/regexp/RegExpStringApi.cpp
+++ b/alib2str/src/regexp/RegExpStringApi.cpp
@@ -19,4 +19,12 @@ void stringApi < regexp::RegExp >::compose ( std::ostream & output, const regexp
 	return regexp::RegExpToStringComposer::compose ( output, data );
 }
 
+regexp::UnboundedRegExpStructure stringApi < regexp::UnboundedRegExpStructure >::parse ( std::istream & input ) {
+	return regexp::RegExpFromStringParser::parseUnboundedRegExpStructure ( input );
+}
+
+void stringApi < regexp::UnboundedRegExpStructure >::compose ( std::ostream & output, const regexp::UnboundedRegExpStructure & data ) {
+	return regexp::RegExpToStringComposer::compose ( output, data );
+}
+
 } /* namespace alib */
diff --git a/alib2str/src/regexp/RegExpStringApi.hpp b/alib2str/src/regexp/RegExpStringApi.hpp
index 39c9a8502150f7567598a47f7ee355e91fffd98e..807e3a90cab06b8cf32fb0c4b95d01984c9ca53a 100644
--- a/alib2str/src/regexp/RegExpStringApi.hpp
+++ b/alib2str/src/regexp/RegExpStringApi.hpp
@@ -10,6 +10,7 @@
 
 #include "../StringApi.hpp"
 #include <regexp/RegExp.h>
+#include <regexp/unbounded/UnboundedRegExpStructure.h>
 
 namespace alib {
 
@@ -19,6 +20,12 @@ struct stringApi < regexp::RegExp > {
 	static void compose ( std::ostream & output, const regexp::RegExp & data );
 };
 
+template < >
+struct stringApi < regexp::UnboundedRegExpStructure > {
+	static regexp::UnboundedRegExpStructure parse ( std::istream & input );
+	static void compose ( std::ostream & output, const regexp::UnboundedRegExpStructure & data );
+};
+
 } /* namespace alib */
 
 #endif /* STRING_API_HPP_ */
diff --git a/alib2str/src/regexp/RegExpToStringComposer.cpp b/alib2str/src/regexp/RegExpToStringComposer.cpp
index 1d126ee7fb13d74bd600b9a265c8ffd528195615..a0ac860672204663b12c47b00534789e4026c974 100644
--- a/alib2str/src/regexp/RegExpToStringComposer.cpp
+++ b/alib2str/src/regexp/RegExpToStringComposer.cpp
@@ -16,23 +16,31 @@
 namespace regexp {
 
 void RegExpToStringComposer::compose(std::ostream& output, const UnboundedRegExp& regexp) {
-	Priority tmp = Priority::ALTERNATION;
-	std::tuple<Priority&, std::ostream&> out = std::tie(tmp, output);
-	RegExpToStringComposer composer;
-	regexp.getRegExp().getStructure().Accept((void*) &out, composer);
+	RegExpToStringComposer::compose ( output, regexp.getRegExp ( ) );
 }
 
 RegExpToStringComposer::RegistratorWrapper<void, UnboundedRegExp> RegExpToStringComposerUnboundedRegExp = RegExpToStringComposer::RegistratorWrapper<void, UnboundedRegExp>(RegExpToStringComposer::compose);
 
-void RegExpToStringComposer::compose(std::ostream& output, const FormalRegExp& regexp) {
+void RegExpToStringComposer::compose(std::ostream& output, const UnboundedRegExpStructure& regexp) {
 	Priority tmp = Priority::ALTERNATION;
 	std::tuple<Priority&, std::ostream&> out = std::tie(tmp, output);
 	RegExpToStringComposer composer;
-	regexp.getRegExp().getStructure().Accept((void*) &out, composer);
+	regexp.getStructure().Accept((void*) &out, composer);
+}
+
+void RegExpToStringComposer::compose(std::ostream& output, const FormalRegExp& regexp) {
+	RegExpToStringComposer::compose ( output, regexp.getRegExp ( ) );
 }
 
 RegExpToStringComposer::RegistratorWrapper<void, FormalRegExp> RegExpToStringComposerFormalRegExp = RegExpToStringComposer::RegistratorWrapper<void, FormalRegExp>(RegExpToStringComposer::compose);
 
+void RegExpToStringComposer::compose(std::ostream& output, const FormalRegExpStructure& regexp) {
+	Priority tmp = Priority::ALTERNATION;
+	std::tuple<Priority&, std::ostream&> out = std::tie(tmp, output);
+	RegExpToStringComposer composer;
+	regexp.getStructure().Accept((void*) &out, composer);
+}
+
 void RegExpToStringComposer::Visit(void* userData, const UnboundedRegExpAlternation& alternation) const {
 	std::tuple<Priority&, std::ostream&> &out = *((std::tuple<Priority&, std::ostream&>*) userData);
 
diff --git a/alib2str/src/regexp/RegExpToStringComposer.h b/alib2str/src/regexp/RegExpToStringComposer.h
index 7fa74196a6481cbaa0d997b49e55fb01fed87054..4d74dbe4fc2a0e881a0e7223ded64620b040a633 100644
--- a/alib2str/src/regexp/RegExpToStringComposer.h
+++ b/alib2str/src/regexp/RegExpToStringComposer.h
@@ -49,7 +49,9 @@ public:
 	static void compose(std::ostream& out, const RegExp& regexp);
 
 	static void compose(std::ostream& out, const UnboundedRegExp& regexp);
+	static void compose(std::ostream& out, const UnboundedRegExpStructure& regexp);
 	static void compose(std::ostream& out, const FormalRegExp& regexp);
+	static void compose(std::ostream& out, const FormalRegExpStructure& regexp);
 };
 
 } /* namespace regexp */