diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp index 2b6e790d95c42b086d7b39d514083fb461bead2a..d523dced31a63f879d3d30bba48e806c072fdb71 100644 --- a/aconversions2/src/ConversionHandler.cpp +++ b/aconversions2/src/ConversionHandler.cpp @@ -204,8 +204,7 @@ void ConversionHandler::convertREtoFSM( void ) switch( m_algorithm ) { case BRZOZOWSKI_DERIVATION: { - conversions::re2fa::BrzozowskiDerivation conv; - alib::DataFactory::toStdout(conv.convert(regexp)); + alib::DataFactory::toStdout(conversions::re2fa::BrzozowskiDerivation::convert(regexp)); break; } case THOMPSON_NFA: { diff --git a/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.cpp b/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.cpp index 961418bfa92dab8af8a87d107a6aaf4549cba7e0..93032524fd1c279cecd82980a4f96d035dace9ac 100644 --- a/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.cpp +++ b/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.cpp @@ -2,7 +2,7 @@ * BrzozowskiDerivation.cpp * * Created on: 11. 1. 2014 - * Author: Tomas Pecka + * Author: Tomas Pecka */ #include "BrzozowskiDerivation.h" @@ -14,10 +14,10 @@ #include <string/LinearString.h> #include <std/hexavigesimal.h> -#include <label/StringLabel.h> #include "../../regexp/RegExpDerivation.h" #include "../../regexp/RegExpOptimize.h" +#include "../../regexp/RegExpEpsilon.h" namespace conversions { @@ -25,110 +25,116 @@ namespace conversions namespace re2fa { -BrzozowskiDerivation::BrzozowskiDerivation(void){} -BrzozowskiDerivation::~BrzozowskiDerivation(void){} - - -void BrzozowskiDerivation::Visit(void* userData, const regexp::FormalRegExp& regexp) +automaton::Automaton BrzozowskiDerivation::convert(const regexp::RegExp& regexp) { - std::pair<std::set<alphabet::Symbol>, bool>& out = *(std::pair<std::set<alphabet::Symbol>, bool>*) userData; - out.first = regexp.getAlphabet(); - out.second = regexp.containsEmptyString(); + automaton::Automaton* out = NULL; + regexp.getData().Accept((void*) &out, BrzozowskiDerivation::BRZOZOWSKI_DERIVATION); + automaton::Automaton res = std::move(*out); + delete out; + return res; } -void BrzozowskiDerivation::Visit(void* userData, const regexp::UnboundedRegExp& regexp) + +template<class T> +automaton::NFA BrzozowskiDerivation::convert(const T& regexp) { - std::pair<std::set<alphabet::Symbol>, bool>& out = *(std::pair<std::set<alphabet::Symbol>, bool>*) userData; - out.first = regexp.getAlphabet(); - out.second = regexp.containsEmptyString(); + // 1. + regexp::RegExpOptimize opt; + regexp::RegExp V = regexp::RegExp{opt.optimize(regexp)}; + + std::set<regexp::RegExp> Q = { V }; + std::deque<std::set<regexp::RegExp>> Qi; + + Qi.push_back(std::set<regexp::RegExp>()); + Qi.at(0).insert(V); + + int i = 1; + + // 2. + while(! Qi.at(i - 1).empty()) + { + Qi.push_back(std::set<regexp::RegExp>()); // initialize set Q_i + + for(const auto& dregexp : Qi.at(i - 1)) + { + regexp::RegExpDerivation deriv; + + for(const auto& a : regexp.getAlphabet()) + { + string::LinearString string(std::vector<alphabet::Symbol>{a}); + regexp::RegExp derived = deriv.derivation(dregexp, string); + derived = opt.optimize(derived); + + // this will also add \emptyset as a regexp (and as FA state) + if(Q.count(derived) == 0) // if this state has already been found, do not add + Qi.at(i).insert(derived); + } + } + + Q.insert(Qi.at(i).begin(), Qi.at(i).end()); + i += 1; + } + + std::map<regexp::RegExp, automaton::State> stateMap; + int stateId = 0; + + for(const auto& r : Q) + { + automaton::State q(std::toBase26(stateId++)); + stateMap.insert(std::make_pair(r, q)); + } + + // ------------------------------------------------------------------------ + // 3. + + automaton::NFA automaton; + + for(const auto& r : stateMap) + { + automaton.addState(r.second); + } + + automaton.addInitialState(stateMap.find(V)->second); + + automaton.setInputSymbols(regexp.getAlphabet()); + + for(const auto& r : Q) + { + regexp::RegExpDerivation deriv; + + for(const auto& a: regexp.getAlphabet()) + { + string::LinearString string(std::vector<alphabet::Symbol>{a}); + regexp::RegExp derived = deriv.derivation(r, string); + derived = opt.optimize(derived); + + automaton.addTransition(stateMap.find(r)->second, a, stateMap.find(derived)->second); + } + } + + for(const auto& r : Q) + { + if(regexp::RegExpEpsilon::languageContainsEpsilon(r)) + automaton.addFinalState(stateMap.find(r)->second); + } + + return automaton; } -automaton::DFA BrzozowskiDerivation::convert(const regexp::RegExp& regexp) +template automaton::NFA BrzozowskiDerivation::convert(const regexp::FormalRegExp& regexp); +template automaton::NFA BrzozowskiDerivation::convert(const regexp::UnboundedRegExp& regexp); + +void BrzozowskiDerivation::Visit(void* userData, const regexp::FormalRegExp& regexp) const { - // 1. - regexp::RegExpOptimize opt; - regexp::RegExp V = opt.optimize(regexp); - - std::pair<std::set<alphabet::Symbol>, bool> out({}, false); - regexp.getData().Accept((void*) &out, *this); - const std::set<alphabet::Symbol>& alphabet = out.first; - - std::set<regexp::RegExp> Q = { V }; - std::deque<std::set<regexp::RegExp>> Qi; - - Qi.push_back(std::set<regexp::RegExp>()); - Qi.at(0).insert(V); - - int i = 1; - - // 2. - while(! Qi.at(i - 1).empty()) - { - Qi.push_back(std::set<regexp::RegExp>()); // initialize set Q_i - - for(const auto& dregexp : Qi.at(i - 1)) - { - regexp::RegExpDerivation deriv; - - for(const auto& a : alphabet) - { - string::LinearString string(std::vector<alphabet::Symbol>{a}); - regexp::RegExp derived = deriv.derivation(dregexp, string); - derived = opt.optimize(derived); - - // this will also add \emptyset as a regexp (and as FA state) - if(Q.count(derived) == 0) // if this state has already been found, do not add - Qi.at(i).insert(derived); - } - } - - Q.insert(Qi.at(i).begin(), Qi.at(i).end()); - i += 1; - } - - std::map<regexp::RegExp, automaton::State> stateMap; - int stateId = 0; - - for(const auto& r : Q) - { - automaton::State q(label::Label(label::StringLabel(std::toBase26(stateId++)))); - stateMap.insert(std::make_pair(r, q)); - } - - // ------------------------------------------------------------------------ - // 3. - - automaton::DFA automaton(stateMap.find(V)->second); - - for(const auto& r : stateMap) - { - automaton.addState(r.second); - } - - automaton.setInputSymbols(alphabet); - - for(const auto& r : Q) - { - regexp::RegExpDerivation deriv; - - for(const auto& a: alphabet) - { - string::LinearString string(std::vector<alphabet::Symbol>{a}); - regexp::RegExp derived = deriv.derivation(r, string); - derived = opt.optimize(derived); - - automaton.addTransition(stateMap.find(r)->second, a, stateMap.find(derived)->second); - } - } - - for(const auto& r : Q) - { - r.getData().Accept((void*) &out, *this); - if(out.second) // if(r.containsEmptyString()) - automaton.addFinalState(stateMap.find(r)->second); - } - - return automaton; + automaton::Automaton* &out = *((automaton::Automaton**) userData); + out = new automaton::Automaton(this->convert(regexp)); } +void BrzozowskiDerivation::Visit(void* userData, const regexp::UnboundedRegExp& regexp) const +{ + automaton::Automaton* &out = *((automaton::Automaton**) userData); + out = new automaton::Automaton(this->convert(regexp)); +} + +const BrzozowskiDerivation BrzozowskiDerivation::BRZOZOWSKI_DERIVATION; } /* namespace re2fa */ diff --git a/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.h b/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.h index 4344d295786b96448ea5729ef890f2a79dc17e52..a3c249dfe7ab5465b2547b4100af12c1139a50f6 100644 --- a/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.h +++ b/alib2algo/src/conversions/re2fa/BrzozowskiDerivation.h @@ -2,7 +2,7 @@ * BrzozowskiDerivation.h * * Created on: 11. 1. 2014 - * Author: Tomas Pecka + * Author: Tomas Pecka */ #ifndef RE2FA_BRZOZOWSKIDERIVATION_H_ @@ -11,7 +11,9 @@ #include <regexp/RegExp.h> #include <regexp/formal/FormalRegExp.h> #include <regexp/unbounded/UnboundedRegExp.h> -#include <automaton/FSM/DFA.h> + +#include <automaton/Automaton.h> +#include <automaton/FSM/NFA.h> namespace conversions { @@ -23,21 +25,23 @@ namespace re2fa * Converts regular expression to finite automaton using BrzozowskiDerivation algorithm (derivations of regular expressions). * Source: Melichar 2.110 */ -class BrzozowskiDerivation : public regexp::VisitableRegExpBase::visitor_type +class BrzozowskiDerivation : public regexp::VisitableRegExpBase::const_visitor_type { public: - BrzozowskiDerivation(void); - ~BrzozowskiDerivation(void); + /** + * Performs conversion. + * @return FSM equivalent to original regular expression. + */ + static automaton::Automaton convert(const regexp::RegExp& regexp); - /** - * Performs conversion. - * @return FSM equivalent to original regular expression. - */ - automaton::DFA convert(const regexp::RegExp& regexp); + template<class T> + static automaton::NFA convert(const T& regexp); private: - void Visit(void* , const regexp::FormalRegExp& regexp); - void Visit(void* , const regexp::UnboundedRegExp& regexp); + void Visit(void* , const regexp::FormalRegExp& regexp) const; + void Visit(void* , const regexp::UnboundedRegExp& regexp) const; + + static const BrzozowskiDerivation BRZOZOWSKI_DERIVATION; }; } /* namespace re2fa */ diff --git a/alib2algo/src/conversions/re2fa/GlushkovNFA.cpp b/alib2algo/src/conversions/re2fa/GlushkovNFA.cpp index 076a7fa30560eb66e3d7f545f591376df8a5625f..ad614b9a75cb07dfc7fd57db87f1901140c45f9d 100644 --- a/alib2algo/src/conversions/re2fa/GlushkovNFA.cpp +++ b/alib2algo/src/conversions/re2fa/GlushkovNFA.cpp @@ -12,6 +12,8 @@ #include "label/IntegerLabel.h" #include "label/LabelPairLabel.h" +#include "../../regexp/RegExpEpsilon.h" + namespace conversions{ namespace re2fa { @@ -80,7 +82,7 @@ automaton::NFA GlushkovNFA::convert( const regexp::UnboundedRegExp & re ) { automaton.addFinalState( q ); } - if( re.containsEmptyString( ) ) + if(regexp::RegExpEpsilon::languageContainsEpsilon(re)) automaton.addFinalState( q0 ); return automaton; diff --git a/alib2algo/src/conversions/re2rg/re2rrg/BrzozowskiDerivation.cpp b/alib2algo/src/conversions/re2rg/re2rrg/BrzozowskiDerivation.cpp index ac979b534a4a742fc8e3bcc159ffa595dd03bc51..9520a2a1f81f8ace45326ab8704068c688afb952 100644 --- a/alib2algo/src/conversions/re2rg/re2rrg/BrzozowskiDerivation.cpp +++ b/alib2algo/src/conversions/re2rg/re2rrg/BrzozowskiDerivation.cpp @@ -17,6 +17,7 @@ #include "../../../regexp/RegExpOptimize.h" #include "../../../regexp/RegExpDerivation.h" +#include "../../../regexp/RegExpEpsilon.h" namespace conversions { @@ -32,13 +33,13 @@ void BrzozowskiDerivation::Visit(void* userData, const regexp::FormalRegExp& reg { std::pair<std::set<alphabet::Symbol>, bool>& out = *(std::pair<std::set<alphabet::Symbol>, bool>*) userData; out.first = regexp.getAlphabet(); - out.second = regexp.containsEmptyString(); + out.second = regexp::RegExpEpsilon::languageContainsEpsilon(regexp); } void BrzozowskiDerivation::Visit(void* userData, const regexp::UnboundedRegExp& regexp) { std::pair<std::set<alphabet::Symbol>, bool>& out = *(std::pair<std::set<alphabet::Symbol>, bool>*) userData; out.first = regexp.getAlphabet(); - out.second = regexp.containsEmptyString(); + out.second = regexp::RegExpEpsilon::languageContainsEpsilon(regexp); } grammar::RightRG BrzozowskiDerivation::convert(const regexp::RegExp& regexp) diff --git a/alib2algo/src/conversions/re2rg/re2rrg/GlushkovNFA.cpp b/alib2algo/src/conversions/re2rg/re2rrg/GlushkovNFA.cpp index 7fa60cb6369cb98d084cb58956409308659ca709..c8dad374dd5dcbf78b6438a384e7fce5deffe3f2 100644 --- a/alib2algo/src/conversions/re2rg/re2rrg/GlushkovNFA.cpp +++ b/alib2algo/src/conversions/re2rg/re2rrg/GlushkovNFA.cpp @@ -20,6 +20,8 @@ #include "../../../regexp/GlushkovPair.h" #include "../../../regexp/GlushkovSymbol.h" +#include "../../../regexp/RegExpEpsilon.h" + namespace conversions { @@ -89,7 +91,7 @@ grammar::RightRG GlushkovNFA::convert(const regexp::UnboundedRegExp& regexp) grammar.addRule(rule.first, rhs.at(0)); } - if(regexp.containsEmptyString( ) ) + if(regexp::RegExpEpsilon::languageContainsEpsilon(regexp)) grammar.setGeneratesEpsilon(true); return grammar; diff --git a/alib2algo/src/regexp/GlushkovTraversal.cpp b/alib2algo/src/regexp/GlushkovTraversal.cpp index 525d8ce9c5722f21a9bde242680c30b9159df91c..0069f0bf75313d1a4e60f1cd90423f3c122ff5de 100644 --- a/alib2algo/src/regexp/GlushkovTraversal.cpp +++ b/alib2algo/src/regexp/GlushkovTraversal.cpp @@ -7,6 +7,8 @@ #include "GlushkovTraversal.h" +#include "RegExpEpsilon.h" + using namespace alib; using namespace regexp; using namespace std; @@ -110,7 +112,7 @@ set<regexp::UnboundedRegExpSymbol const *> GlushkovTraversal::first( regexp::Unb tmp = first( element ); ret.insert( tmp.begin( ), tmp.end( ) ); - if( ! element->containsEmptyString( ) ) // If regexp of this subtree can match epsilon, then we need to add next subtree + if(! regexp::RegExpEpsilon::languageContainsEpsilon(*element)) // If regexp of this subtree can match epsilon, then we need to add next subtree break; } @@ -186,7 +188,7 @@ set<regexp::UnboundedRegExpSymbol const *> GlushkovTraversal::last( regexp::Unbo tmp = last( *it ); ret.insert( tmp.begin( ), tmp.end( ) ); - if( ! ( * it )->containsEmptyString( ) ) + if( ! regexp::RegExpEpsilon::languageContainsEpsilon(**it) ) break; } @@ -274,7 +276,7 @@ set<regexp::UnboundedRegExpSymbol const *> GlushkovTraversal::follow( regexp::Un tmp = first( *f ); ret.insert( tmp.begin( ), tmp.end( ) ); - if( ! ( *f )->containsEmptyString( ) ) + if( ! regexp::RegExpEpsilon::languageContainsEpsilon( **f ) ) break; } } diff --git a/alib2algo/src/regexp/RegExpDerivation.cpp b/alib2algo/src/regexp/RegExpDerivation.cpp index 3c168fcc51eb43e687077a83de539d378446dd7a..2d7c5f0aba710477e1347034f8a3ee5cd45cdf59 100644 --- a/alib2algo/src/regexp/RegExpDerivation.cpp +++ b/alib2algo/src/regexp/RegExpDerivation.cpp @@ -7,6 +7,8 @@ #include "RegExpDerivation.h" +#include "RegExpEpsilon.h" + namespace regexp { @@ -184,7 +186,7 @@ void RegExpDerivation::Visit(void* userData, const regexp::UnboundedRegExpConcat ret->appendElement(std::move(*concat)); delete concat; - if((*child)->containsEmptyString()) + if(regexp::RegExpEpsilon::languageContainsEpsilon(**child)) continue; // this IF construct is intentional "to match algorithm" break; } diff --git a/alib2algo/src/regexp/RegExpEmpty.cpp b/alib2algo/src/regexp/RegExpEmpty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16247f9328df4c77308a87236084275b3f58f622 --- /dev/null +++ b/alib2algo/src/regexp/RegExpEmpty.cpp @@ -0,0 +1,160 @@ +/* + * RegExpEmpty.cpp + * + * Created on: 19. 1. 2014 + * Author: Tomas Pecka + */ + +#include "RegExpEmpty.h" + +namespace regexp +{ + +bool RegExpEmpty::languageIsEmpty(const regexp::RegExp& regexp) +{ + bool out; + regexp.getData().Accept((void*) &out, RegExpEmpty::REG_EXP_EMPTY); + return out; +} + +bool RegExpEmpty::languageIsEmpty(const regexp::FormalRegExp& regexp) +{ + bool out; + regexp.getRegExp().Accept((void*) &out, RegExpEmpty::REG_EXP_EMPTY); + return out; +} + +bool RegExpEmpty::languageIsEmpty(const regexp::UnboundedRegExp& regexp) +{ + bool out; + regexp.getRegExp().Accept((void*) &out, RegExpEmpty::REG_EXP_EMPTY); + return out; +} + +// ---------------------------------------------------------------------------- + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExpAlternation& alternation) const +{ + bool &ret = *(bool*) data; + + for(const auto& element : alternation.getElements()) + { + static_cast<const regexp::UnboundedRegExpElement&>(*element).Accept(data, *this); + if(! ret) + { + ret = false; + return; + } + } + ret = true; +} + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExpConcatenation& concatenation) const +{ + bool &ret = *(bool*) data; + + for(const auto& element : concatenation.getElements()) + { + static_cast<const regexp::UnboundedRegExpElement&>(*element).Accept(data, *this); + if(ret) + { + ret = true; + return; + } + } + ret = false; +} + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExpIteration&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExpSymbol&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExpEmpty&) const +{ + bool &ret = *(bool*) data; + ret = true; +} + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExpEpsilon&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +// ---------------------------------------------------------------------------- + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExpAlternation& alternation) const +{ + bool &ret = *(bool*) data; + + static_cast<const regexp::FormalRegExpElement&>(alternation.getLeftElement()).Accept(data, *this); + bool retLeft = ret; + + static_cast<const regexp::FormalRegExpElement&>(alternation.getRightElement()).Accept(data, *this); + bool retRight = ret; + + ret = retLeft && retRight; +} + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExpConcatenation& concatenation) const +{ + bool &ret = *(bool*) data; + + static_cast<const regexp::FormalRegExpElement&>(concatenation.getLeftElement()).Accept(data, *this); + bool retLeft = ret; + + static_cast<const regexp::FormalRegExpElement&>(concatenation.getRightElement()).Accept(data, *this); + bool retRight = ret; + + ret = retLeft || retRight; +} + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExpIteration&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExpSymbol&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExpEmpty&) const +{ + bool &ret = *(bool*) data; + ret = true; +} + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExpEpsilon&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +// ---------------------------------------------------------------------------- + +void RegExpEmpty::Visit(void* data, const regexp::FormalRegExp& regexp) const +{ + bool &ret = *(bool*) data; + ret = RegExpEmpty::REG_EXP_EMPTY.languageIsEmpty(regexp); +} + +void RegExpEmpty::Visit(void* data, const regexp::UnboundedRegExp& regexp) const +{ + bool &ret = *(bool*) data; + ret = RegExpEmpty::REG_EXP_EMPTY.languageIsEmpty(regexp); +} + +const RegExpEmpty RegExpEmpty::REG_EXP_EMPTY; + +} /* namespace regexp */ diff --git a/alib2algo/src/regexp/RegExpEmpty.h b/alib2algo/src/regexp/RegExpEmpty.h new file mode 100644 index 0000000000000000000000000000000000000000..8b2958e121a1cf60d0ee7035768d100262684711 --- /dev/null +++ b/alib2algo/src/regexp/RegExpEmpty.h @@ -0,0 +1,53 @@ +/* + * RegExpEmpty.h + * + * Created on: 19. 1. 2014 + * Author: Tomas Pecka + */ + +#ifndef REG_EXP_EMPTY_H_ +#define REG_EXP_EMPTY_H_ + +#include <regexp/RegExp.h> +#include <regexp/formal/FormalRegExpElements.h> +#include <regexp/unbounded/UnboundedRegExpElements.h> + +namespace regexp +{ + +/** + * Determines whether regular expression is empty (regexp == \0) + * + */ +class RegExpEmpty : public regexp::VisitableRegExpBase::const_visitor_type, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type +{ +public: + static bool languageIsEmpty(const regexp::RegExp& regexp); + + static bool languageIsEmpty(const regexp::FormalRegExp& regexp); + static bool languageIsEmpty(const regexp::UnboundedRegExp& regexp); + +private: + void Visit(void* data, const regexp::UnboundedRegExp& regexp) const; + void Visit(void* data, const regexp::FormalRegExp& regexp) const; + + void Visit(void* data, const regexp::UnboundedRegExpAlternation& alternation) const; + void Visit(void* data, const regexp::UnboundedRegExpConcatenation& concatenation) const; + void Visit(void* data, const regexp::UnboundedRegExpIteration& iteration) const; + void Visit(void* data, const regexp::UnboundedRegExpSymbol& symbol) const; + void Visit(void* data, const regexp::UnboundedRegExpEmpty& empty) const; + void Visit(void* data, const regexp::UnboundedRegExpEpsilon& epsilon) const; + + void Visit(void* data, const regexp::FormalRegExpAlternation& alternation) const; + void Visit(void* data, const regexp::FormalRegExpConcatenation& concatenation) const; + void Visit(void* data, const regexp::FormalRegExpIteration& iteration) const; + void Visit(void* data, const regexp::FormalRegExpSymbol& symbol) const; + void Visit(void* data, const regexp::FormalRegExpEmpty& empty) const; + void Visit(void* data, const regexp::FormalRegExpEpsilon& epsilon) const; + + static const RegExpEmpty REG_EXP_EMPTY; +}; + +} /* namespace regexp */ + +#endif /* REG_EXP_EMPTY_H_ */ diff --git a/alib2algo/src/regexp/RegExpEpsilon.cpp b/alib2algo/src/regexp/RegExpEpsilon.cpp index 74a832881bc9239c4746c9a55126d86435876429..c697cbbdd16061eb579353d0eec35df5bbb9e96a 100644 --- a/alib2algo/src/regexp/RegExpEpsilon.cpp +++ b/alib2algo/src/regexp/RegExpEpsilon.cpp @@ -19,23 +19,156 @@ bool RegExpEpsilon::languageContainsEpsilon(const regexp::RegExp& regexp) bool RegExpEpsilon::languageContainsEpsilon(const regexp::FormalRegExp& regexp) { - return regexp.containsEmptyString(); + bool out; + regexp.getRegExp().Accept((void*) &out, RegExpEpsilon::REG_EXP_EPSILON); + return out; } bool RegExpEpsilon::languageContainsEpsilon(const regexp::UnboundedRegExp& regexp) { - return regexp.containsEmptyString(); + bool out; + regexp.getRegExp().Accept((void*) &out, RegExpEpsilon::REG_EXP_EPSILON); + return out; } -void RegExpEpsilon::Visit(void* userData, const regexp::FormalRegExp& regexp) const + +bool RegExpEpsilon::languageContainsEpsilon(const regexp::FormalRegExpElement& element) +{ + bool out; + element.Accept((void*) &out, RegExpEpsilon::REG_EXP_EPSILON); + return out; +} + +bool RegExpEpsilon::languageContainsEpsilon(const regexp::UnboundedRegExpElement& element) +{ + bool out; + element.Accept((void*) &out, RegExpEpsilon::REG_EXP_EPSILON); + return out; +} + +// --------------------------------------------------------------------------- + +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExpAlternation& alternation) const +{ + bool &ret = *(bool*) data; + + for(const auto& element : alternation.getElements()) + { + static_cast<const regexp::UnboundedRegExpElement&>(*element).Accept(data, RegExpEpsilon::REG_EXP_EPSILON); + if(ret) + { + ret = true; + return; + } + } + + ret = false; +} + +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExpConcatenation& concatenation) const +{ + bool &ret = *(bool*) data; + + for(const auto& element : concatenation.getElements()) + { + static_cast<const regexp::UnboundedRegExpElement&>(*element).Accept(data, RegExpEpsilon::REG_EXP_EPSILON); + if(!ret) + { + ret = false; + return; + } + } + + ret = true; +} + +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExpIteration&) const +{ + bool &ret = *(bool*) data; + ret = true; +} + +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExpSymbol&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExpEpsilon&) const +{ + bool &ret = *(bool*) data; + ret = true; +} + +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExpEmpty&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +// ---------------------------------------------------------------------------- + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExpAlternation& alternation) const +{ + bool &ret = *(bool*) data; + + static_cast<const regexp::FormalRegExpElement&>(alternation.getLeftElement()).Accept(data, RegExpEpsilon::REG_EXP_EPSILON); + bool retLeft = ret; + + static_cast<const regexp::FormalRegExpElement&>(alternation.getRightElement()).Accept(data, RegExpEpsilon::REG_EXP_EPSILON); + bool retRight = ret; + + ret = retLeft || retRight; +} + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExpConcatenation& concatenation) const +{ + bool &ret = *(bool*) data; + + static_cast<const regexp::FormalRegExpElement&>(concatenation.getLeftElement()).Accept(data, RegExpEpsilon::REG_EXP_EPSILON); + bool retLeft = ret; + + static_cast<const regexp::FormalRegExpElement&>(concatenation.getRightElement()).Accept(data, RegExpEpsilon::REG_EXP_EPSILON); + bool retRight = ret; + + ret = retLeft && retRight; +} + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExpIteration&) const +{ + bool &ret = *(bool*) data; + ret = true; +} + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExpSymbol&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExpEmpty&) const +{ + bool &ret = *(bool*) data; + ret = false; +} + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExpEpsilon&) const +{ + bool &ret = *(bool*) data; + ret = true; +} + +// --------------------------------------------------------------------------- + +void RegExpEpsilon::Visit(void* data, const regexp::FormalRegExp& regexp) const { - bool &ret = *(bool*) userData; + bool &ret = *(bool*) data; ret = RegExpEpsilon::REG_EXP_EPSILON.languageContainsEpsilon(regexp); } -void RegExpEpsilon::Visit(void* userData, const regexp::UnboundedRegExp& regexp) const +void RegExpEpsilon::Visit(void* data, const regexp::UnboundedRegExp& regexp) const { - bool &ret = *(bool*) userData; + bool &ret = *(bool*) data; ret = RegExpEpsilon::REG_EXP_EPSILON.languageContainsEpsilon(regexp); } diff --git a/alib2algo/src/regexp/RegExpEpsilon.h b/alib2algo/src/regexp/RegExpEpsilon.h index 0f2642add7d360290552e8bb0eb3a8fd6e0f5bdd..4472068c2c856e87ecb974eedb962b284915b797 100644 --- a/alib2algo/src/regexp/RegExpEpsilon.h +++ b/alib2algo/src/regexp/RegExpEpsilon.h @@ -16,10 +16,11 @@ namespace regexp { /** - * Calculates languageContainsEpsilon of regular expression. + * Checks, whether regexp (or its subtree) describes epsilon (empty string). + * TODO: Better API? * */ -class RegExpEpsilon : public regexp::VisitableRegExpBase::const_visitor_type +class RegExpEpsilon : public regexp::VisitableRegExpBase::const_visitor_type, regexp::FormalRegExpElement::const_visitor_type, regexp::UnboundedRegExpElement::const_visitor_type { public: static bool languageContainsEpsilon(const regexp::RegExp& regexp); @@ -27,9 +28,27 @@ public: static bool languageContainsEpsilon(const regexp::FormalRegExp& regexp); static bool languageContainsEpsilon(const regexp::UnboundedRegExp& regexp); + static bool languageContainsEpsilon(const regexp::UnboundedRegExpElement& element); + static bool languageContainsEpsilon(const regexp::FormalRegExpElement& element); + private: - void Visit(void* data, const regexp::UnboundedRegExp& regexp) const; - void Visit(void* data, const regexp::FormalRegExp& regexp) const; + void Visit(void* data, const regexp::UnboundedRegExp& regexp) const; + void Visit(void* data, const regexp::FormalRegExp& regexp) const; + + void Visit(void* data, const regexp::UnboundedRegExpAlternation& alternation) const; + void Visit(void* data, const regexp::UnboundedRegExpConcatenation& concatenation) const; + void Visit(void* data, const regexp::UnboundedRegExpIteration& iteration) const; + void Visit(void* data, const regexp::UnboundedRegExpSymbol& symbol) const; + void Visit(void* data, const regexp::UnboundedRegExpEmpty& empty) const; + void Visit(void* data, const regexp::UnboundedRegExpEpsilon& epsilon) const; + + void Visit(void* data, const regexp::FormalRegExpAlternation& alternation) const; + void Visit(void* data, const regexp::FormalRegExpConcatenation& concatenation) const; + void Visit(void* data, const regexp::FormalRegExpIteration& iteration) const; + void Visit(void* data, const regexp::FormalRegExpSymbol& symbol) const; + void Visit(void* data, const regexp::FormalRegExpEmpty& empty) const; + void Visit(void* data, const regexp::FormalRegExpEpsilon& epsilon) const; + static const RegExpEpsilon REG_EXP_EPSILON; }; diff --git a/alib2algo/src/regexp/RegExpOptimize.cpp b/alib2algo/src/regexp/RegExpOptimize.cpp index ca6b5d32b5a8552b1086e1f14ea8bb893ae011da..73a9740a4c1de43bd7116c049011838ab752cdb9 100644 --- a/alib2algo/src/regexp/RegExpOptimize.cpp +++ b/alib2algo/src/regexp/RegExpOptimize.cpp @@ -7,6 +7,8 @@ #include "RegExpOptimize.h" +#include "RegExpEpsilon.h" + #include <cassert> #include <iostream> #include <iostream> @@ -1117,7 +1119,7 @@ bool RegExpOptimize::V8( UnboundedRegExpConcatenation * const & node ) auto it2 = it; advance( it2, - (int)concat->elements.size( ) ); - if( concat->containsEmptyString( ) && + if( regexp::RegExpEpsilon::languageContainsEpsilon(*concat) && distance( concat->elements.begin( ), concat->elements.end( )) == distance ( it2, node->elements.end( ) ) && equal( concat->elements.begin( ), concat->elements.end( ), it2, [] ( UnboundedRegExpElement const * const & a, UnboundedRegExpElement const * const & b ) -> bool { return *a == *b; } ) ) { @@ -1143,7 +1145,7 @@ bool RegExpOptimize::V8( UnboundedRegExpConcatenation * const & node ) auto prev = std::prev( it ); - if( iter->element->containsEmptyString( ) && *( iter->element ) == **prev ) + if( regexp::RegExpEpsilon::languageContainsEpsilon(*(iter->element)) && *( iter->element ) == **prev ) { delete * prev; it = node->elements.erase( prev ); diff --git a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp index 66743585bb7c71522f85149e6aa98abbc40273f0..3e0a368f99de1bd821eb792cb5321d02529733a9 100644 --- a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp +++ b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp @@ -7,12 +7,14 @@ #include "conversions/fa2re/Algebraic.h" #include "determinize/nfa/NFADeterminizer.h" #include "minimize/dfa/MinimizeDFA.h" +#include "normalize/dfa/NormalizeDFA.h" #include "epsilon/fsm/FSMEpsilonRemover.h" #include "regexp/unbounded/UnboundedRegExp.h" #include "regexp/RegExpFromStringParser.h" #include "automaton/FSM/NFA.h" +#include <factory/DataFactory.hpp> CPPUNIT_TEST_SUITE_REGISTRATION( re2faTest ); @@ -80,16 +82,24 @@ void re2faTest::testBrzozowski() { regexp::RegExpFromStringParser parser(inputs); regexp::RegExp regexp1( parser.parseValue() ); - conversions::re2fa::BrzozowskiDerivation brzozowski1; - automaton::DFA dfa1 = brzozowski1.convert(regexp1); + automaton::Automaton nfa1 = conversions::re2fa::BrzozowskiDerivation::convert(regexp1); + alib::DataFactory::toStdout(nfa1); - regexp::RegExp regexp2( conversions::fa2re::Algebraic::convert(dfa1) ); + regexp::RegExp regexp2( conversions::fa2re::Algebraic::convert(static_cast<const automaton::NFA&>(nfa1.getData())) ); + alib::DataFactory::toStdout(regexp2); - conversions::re2fa::BrzozowskiDerivation brzozowski2; - automaton::DFA dfa2 = brzozowski2.convert(regexp2); + automaton::Automaton nfa2 = conversions::re2fa::BrzozowskiDerivation::convert(regexp2); - automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); - automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); + automaton::DFA mdfa1_1 = determinize::NFADeterminizer::determinize(static_cast<const automaton::NFA&>(nfa1.getData())); + automaton::DFA mdfa1_2 = minimize::MinimizeDFA::minimize(mdfa1_1); + automaton::DFA mdfa1_3 = normalize::NormalizeDFA::normalize(mdfa1_2); - CPPUNIT_ASSERT( mdfa1 == mdfa2); + automaton::DFA mdfa2_1 = determinize::NFADeterminizer::determinize(static_cast<const automaton::NFA&>(nfa2.getData())); + automaton::DFA mdfa2_2 = minimize::MinimizeDFA::minimize(mdfa2_1); + automaton::DFA mdfa2_3 = normalize::NormalizeDFA::normalize(mdfa2_2); + + alib::DataFactory::toStdout(mdfa1_3); + alib::DataFactory::toStdout(mdfa2_3); + + CPPUNIT_ASSERT( mdfa1_3 == mdfa2_3); } diff --git a/alib2algo/test-src/regexp/RegExpEmptyTest.cpp b/alib2algo/test-src/regexp/RegExpEmptyTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d451d65689f3eded0b6de2b67ecad26accad47de --- /dev/null +++ b/alib2algo/test-src/regexp/RegExpEmptyTest.cpp @@ -0,0 +1,34 @@ +#include "RegExpEmptyTest.h" + +#include "regexp/RegExpEmpty.h" + +#include <sstream> +#include <regexp/RegExp.h> +#include <regexp/RegExpFromStringParser.h> + +CPPUNIT_TEST_SUITE_REGISTRATION( RegExpEmptyTest ); + +void RegExpEmptyTest::setUp() { +} + +void RegExpEmptyTest::tearDown() { +} + +void RegExpEmptyTest::testRegExpEmpty() { + { + std::string input = "(#E #0 ) + ( #0 a + (b ( #0 (a*) ) ) )"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(regexp::RegExpEmpty::languageIsEmpty(re)); + } + { + std::string input = "(#E + a ) + ( #0 a + (b ( #0 (a*) ) ) )"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(! regexp::RegExpEmpty::languageIsEmpty(re)); + } +} diff --git a/alib2algo/test-src/regexp/RegExpEmptyTest.h b/alib2algo/test-src/regexp/RegExpEmptyTest.h new file mode 100644 index 0000000000000000000000000000000000000000..8b8ad5c43e986349f41e2b844c6428dc70c02b32 --- /dev/null +++ b/alib2algo/test-src/regexp/RegExpEmptyTest.h @@ -0,0 +1,21 @@ +#ifndef REGEXPEMPTY_TEST_H_ +#define REGEXPEMPTY_TEST_H_ + +#include <string> + +#include <cppunit/extensions/HelperMacros.h> + +class RegExpEmptyTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( RegExpEmptyTest ); + CPPUNIT_TEST( testRegExpEmpty ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testRegExpEmpty(); +}; + +#endif /* REGEXPEMPTY_TEST_H_ */ diff --git a/alib2algo/test-src/regexp/RegExpEpsilonTest.cpp b/alib2algo/test-src/regexp/RegExpEpsilonTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86e177beb8af91690b5535d0f35e19bba1604bd3 --- /dev/null +++ b/alib2algo/test-src/regexp/RegExpEpsilonTest.cpp @@ -0,0 +1,73 @@ +#include "RegExpEpsilonTest.h" + +#include "regexp/RegExpEpsilon.h" +#include <sstream> +#include <regexp/RegExpFromStringParser.h> + + +CPPUNIT_TEST_SUITE_REGISTRATION( RegExpEpsilonTest ); + +void RegExpEpsilonTest::setUp() { +} + +void RegExpEpsilonTest::tearDown() { +} + +void RegExpEpsilonTest::testRegExpEpsilon() { + { + std::string input = "#E + ( (a #E) + a*)"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } + { + std::string input = "( a* )( a* )"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } + { + std::string input = "a + #0"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(! regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } + { + std::string input = "#E + a #E + a*"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } + { + std::string input = "a* a*"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } + { + std::string input = "a s d #E + #E #0"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(! regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } + { + std::string input = "a + #0"; + std::stringstream inputs(input); + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp re = parser.parseValue(); + + CPPUNIT_ASSERT(! regexp::RegExpEpsilon::languageContainsEpsilon(re)); + } +} diff --git a/alib2algo/test-src/regexp/RegExpEpsilonTest.h b/alib2algo/test-src/regexp/RegExpEpsilonTest.h new file mode 100644 index 0000000000000000000000000000000000000000..1b8531b6998c42c7a266d888239d1c177bca3834 --- /dev/null +++ b/alib2algo/test-src/regexp/RegExpEpsilonTest.h @@ -0,0 +1,21 @@ +#ifndef REGEXPEPSILON_TEST_H_ +#define REGEXPEPSILON_TEST_H_ + +#include <string> + +#include <cppunit/extensions/HelperMacros.h> + +class RegExpEpsilonTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( RegExpEpsilonTest ); + CPPUNIT_TEST( testRegExpEpsilon ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testRegExpEpsilon(); +}; + +#endif /* REGEXPEPSILON_TEST_H_ */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp index 9e928e57b4679557fd5650d0acd56a96ec287fa0..237f6bb309367e601d050526f3d60aa1e1757d41 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp @@ -138,14 +138,6 @@ bool UnboundedRegExp::removeSymbolFromAlphabet(const alphabet::Symbol & symbol) return alphabet.erase(symbol); } -bool UnboundedRegExp::isEmpty() const { - return regExp->isEmpty(); -} - -bool UnboundedRegExp::containsEmptyString() const { - return regExp->containsEmptyString(); -} - void UnboundedRegExp::operator >>(std::ostream& out) const { out << "(UnboundedRegExp " << *(this->regExp) << ")"; } diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExp.h b/alib2data/src/regexp/unbounded/UnboundedRegExp.h index b89c86269303c8c2341cad6da496779def71eacc..046a6a39f426e5edb7e5986f665a4c07395dd924 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExp.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExp.h @@ -105,16 +105,6 @@ public: */ bool removeSymbolFromAlphabet(const alphabet::Symbol & symbol); - /** - * @return true if regexp represents empty language - */ - bool isEmpty() const; - - /** - * @return true if regexp matches empty string (epsilon) - */ - bool containsEmptyString() const; - /** * Prints XML representation of the RegExp to the output stream. * @param out output stream to which print the RegExp diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp index dad8b817cc0848141243920b5c2f7e473f766879..66656f173c274ee5beace76456381d913377f423 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.cpp @@ -176,20 +176,4 @@ void UnboundedRegExpAlternation::computeMinimalAlphabet( std::set<alphabet::Symb child->computeMinimalAlphabet(alphabet); } -bool UnboundedRegExpAlternation::containsEmptyString() const { - for(const auto& e : elements) - if(e->containsEmptyString()) - return true; - - return false; // alternation of zero regexps is empty so by default it doesn't contain epsilon -} - -bool UnboundedRegExpAlternation::isEmpty() const { - for(const auto& e : elements) - if(!e->isEmpty()) - return false; - - return true; // alternation of zero regexps is empty -} - } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h index 96e9547215af15085a9beda851dc00b595174fd1..b8e0d32c2f7190aabe9f6e149da8fa735f87ac20 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpAlternation.h @@ -94,16 +94,6 @@ public: */ virtual void operator>>(std::ostream& out) const; - /** - * @copydoc UnboundedRegExpElement::containsEmptyString() const - */ - virtual bool containsEmptyString() const; - - /** - * @copydoc UnboundedRegExpElement::isEmpty() const - */ - virtual bool isEmpty() const; - friend class RegExpOptimize; }; diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp index bcbe39ad3f835ae6e6d6ee019c37228ca02d4d38..f932c21a73d0f4a4dc00b64fd8f061032ef75b77 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.cpp @@ -175,20 +175,4 @@ void UnboundedRegExpConcatenation::computeMinimalAlphabet( std::set<alphabet::Sy child->computeMinimalAlphabet(alphabet); } -bool UnboundedRegExpConcatenation::containsEmptyString() const { - for(const auto& e : elements) - if( ! e->containsEmptyString()) - return false; - - return true; // concatenation of zero regexps is epsilon so by default it does contain epsilon -} - -bool UnboundedRegExpConcatenation::isEmpty() const { - for(const auto& e : elements) - if(e->isEmpty()) - return true; - - return false; // concatenation of zero regexps is epsilon -} - } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h index deb28d5af1236d17438c7bb9de98454828673cb4..e23f776cd3a3d4e9fa8b47bc3e3d19c5dfdb8fef 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpConcatenation.h @@ -93,16 +93,6 @@ public: */ virtual void operator>>(std::ostream& out) const; - /** - * @copydoc UnboundedRegExpElement::containsEmptyString() const - */ - virtual bool containsEmptyString() const; - - /** - * @copydoc UnboundedRegExpElement::isEmpty() const - */ - virtual bool isEmpty() const; - friend class RegExpOptimize; }; diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h b/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h index 8874186afe80ff7325a76588a3590be9a0f6bd57..6a2b715dfa7b3699eb3df565165f16ddb3aded8c 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpElement.h @@ -114,16 +114,6 @@ public: */ friend std::ostream& operator<<(std::ostream& out, const UnboundedRegExpElement& regexp); - /** - * @return true if this subtree of regexp matches empty string (epsilon) - */ - virtual bool containsEmptyString() const = 0; - - /** - * @return true if this subtree describes empty language - */ - virtual bool isEmpty() const = 0; - friend class UnboundedRegExp; friend class UnboundedRegExpAlternation; diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp index d5d2c73f6fbb0b2b4b5156fc4017e32ed973d5b3..11226123f39acd3b516691925ea227d85198d544 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.cpp @@ -83,12 +83,4 @@ void UnboundedRegExpEmpty::computeMinimalAlphabet( std::set<alphabet::Symbol>&) } -bool UnboundedRegExpEmpty::containsEmptyString() const { - return false; -} - -bool UnboundedRegExpEmpty::isEmpty() const { - return true; -} - } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h index b940f5c281d1f2453c9dc4e80678a8dd73ca6df0..a1f86bc84a8b14e39cd1ab52927c0eba2a341640 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEmpty.h @@ -66,15 +66,6 @@ public: */ virtual void operator>>(std::ostream& out) const; - /** - * @copydoc UnboundedRegExpElement::containsEmptyString() const - */ - virtual bool containsEmptyString() const; - - /** - * @copydoc UnboundedRegExpElement::isEmpty() const - */ - virtual bool isEmpty() const; }; } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp index 706b4c455a76ca35a62c64f7f33a2276f65b2ecc..565211a136f79fc47b4b1c6a7a5eb841873bc2cf 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.cpp @@ -83,12 +83,4 @@ void UnboundedRegExpEpsilon::computeMinimalAlphabet( std::set<alphabet::Symbol>& } -bool UnboundedRegExpEpsilon::containsEmptyString() const { - return true; -} - -bool UnboundedRegExpEpsilon::isEmpty() const { - return false; -} - } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h index a52138bce28bb0a93021aced09f4e722c615dd23..d13242e3e027ab4dd25c70e4648312030c1fc8ee 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpEpsilon.h @@ -68,15 +68,6 @@ public: */ virtual void operator>>(std::ostream& out) const; - /** - * @copydoc UnboundedRegExpElement::containsEmptyString() const - */ - virtual bool containsEmptyString() const; - - /** - * @copydoc UnboundedRegExpElement::isEmpty() const - */ - virtual bool isEmpty() const; }; } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp index 7788d970ed60370fdf8789dd906914edf4fd354b..78e07bdc101341a3fc85f6af526316adf02af56b 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.cpp @@ -130,13 +130,5 @@ void UnboundedRegExpIteration::computeMinimalAlphabet( std::set<alphabet::Symbol element->computeMinimalAlphabet(alphabet); } -bool UnboundedRegExpIteration::containsEmptyString() const { - return true; -} - -bool UnboundedRegExpIteration::isEmpty() const { - return false; -} - } /* namespace regexp */ diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h index 75cb849ee215b154dfff9e61bdf0a6b396022ce6..afa05a74150006437b7e985da2eb3a91155cf5b8 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpIteration.h @@ -92,16 +92,6 @@ public: */ virtual void operator>>(std::ostream& out) const; - /** - * @copydoc UnboundedRegExpElement::containsEmptyString() const - */ - virtual bool containsEmptyString() const; - - /** - * @copydoc UnboundedRegExpElement::isEmpty() const - */ - virtual bool isEmpty() const; - friend class RegExpOptimize; }; diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp index cb8ea6f2f19a61c420d21408b6c512c4808443c5..9cfafbf4f18b5b1ecc8cb62a77f58bd18cf381d8 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.cpp @@ -102,14 +102,6 @@ void UnboundedRegExpSymbol::operator>>(std::ostream& out) const { out << "(UnboundedRegExpSymbol " << symbol << ")"; } -bool UnboundedRegExpSymbol::containsEmptyString() const { - return false; -} - -bool UnboundedRegExpSymbol::isEmpty() const { - return false; -} - bool UnboundedRegExpSymbol::testSymbol( const alphabet::Symbol & symbol ) const { return symbol == this->symbol; } diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h index 1b2bc5eee0ccc2e50427025a3ea3c0b86077beb3..858b8b4f61b2fdaa9fd047ec861994bd02bb8d9f 100644 --- a/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h +++ b/alib2data/src/regexp/unbounded/UnboundedRegExpSymbol.h @@ -78,20 +78,10 @@ public: */ virtual void operator>>(std::ostream& out) const; - /** - * @copydoc UnboundedRegExpElement::containsEmptyString() const - */ - virtual bool containsEmptyString() const; - /** * Returns the string representation of RegExp Symbol. */ const alphabet::Symbol& getSymbol() const; - - /** - * @copydoc UnboundedRegExpElement::isEmpty() const - */ - virtual bool isEmpty() const; }; } /* namespace regexp */