diff --git a/aconversions/makefile b/aconversions/makefile index fe10f923049b7f5191f9a408e8acca9a591d1fa5..3b9634df445502725ceb40256608245f10043ad6 100644 --- a/aconversions/makefile +++ b/aconversions/makefile @@ -1,6 +1,6 @@ CC=g++ EXECUTABLE=aconversion -CCFLAGS= -std=c++11 -O2 -c -Wall -I../alib/src -I/usr/include/libxml2/ -I../libaregexptree/src +CCFLAGS= -std=c++11 -O2 -g -c -Wall -I../alib/src -I/usr/include/libxml2/ -I../libaregexptree/src LDFLAGS= -L../alib/lib -L../libaregexptree/lib -lxml2 -laregexptree -lalib -Wl,-rpath,. SOURCES=$(shell find src/ -name *cpp) diff --git a/aconversions/src/aconversion/aconversion.cpp b/aconversions/src/aconversion/aconversion.cpp index efc38b7991040294c1e0c014c74d9d7608fd2d82..fec6d8d2adc67547958d34320ae9de6a39335bbb 100644 --- a/aconversions/src/aconversion/aconversion.cpp +++ b/aconversions/src/aconversion/aconversion.cpp @@ -128,7 +128,7 @@ int main(int argc, char* argv[]) } catch( AlibException & e ) { - cout << e.what( ) << endl; + cerr << e.what( ) << endl; return 1; } diff --git a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp b/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp index 7512a2c52f677b222784e4a6daeb112c1a827d46..ae572db176d242a77c0ecdbd5a40259213013538 100644 --- a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp +++ b/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp @@ -61,7 +61,7 @@ LeftRegularGrammar FAtoLRGConverter::convert( void ) for( const auto & rule : m_grammar.getRules( ) ) { - const Symbol & leftSide = * rule.getLeftSide( ).begin( ); + const Symbol & leftSide = rule.getLeftSide( ).front( ); if( isInSet( State( leftSide.getSymbol( ) ), m_fsm.getFinalStates( ) ) ) { diff --git a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp b/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp index 30fc37d17d8b577cf803a22a18ef0217146303cf..28b1db614752ab0cba3bb37be58a63d785de688e 100644 --- a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp +++ b/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp @@ -40,7 +40,13 @@ RightRegularGrammar FAtoRRGConverter::convert( void ) list<Symbol> leftSide, rightSide; leftSide.push_back( symbolMap.getNonTerminal( transition.getFrom( ) ) ); rightSide.push_back( transition.getInput( ) ); - m_grammar.addRule( Rule( leftSide, rightSide ) ); + + /* + * Rule might already in - consider case: + * \delta(A,a) = { F, G }, where both F and G are final states + */ + if( ! isInSet( Rule( leftSide, rightSide), m_grammar.getRules( ) ) ) + m_grammar.addRule( Rule( leftSide, rightSide ) ); } } @@ -48,7 +54,7 @@ RightRegularGrammar FAtoRRGConverter::convert( void ) m_grammar.setStartSymbol( symbolMap.getNonTerminal( * m_fsm.getInitialStates( ).begin( ) ) ); // step 4 - if( isInSet( State( m_grammar.getStartSymbol( ).getSymbol( ) ), m_fsm.getFinalStates( ) ) ) + if( isInSet( * m_fsm.getInitialStates( ).begin( ), m_fsm.getFinalStates( ) ) ) { // 4a if( ! m_grammar.isNonTerminalOnRightSideOfAnyRule( m_grammar.getStartSymbol( ) ) ) @@ -63,7 +69,7 @@ RightRegularGrammar FAtoRRGConverter::convert( void ) for( const auto & rule : m_grammar.getRules( ) ) { - if( *( rule.getLeftSide( ).begin( ) ) == m_grammar.getStartSymbol( ) ) + if( rule.getLeftSide( ).front( ) == m_grammar.getStartSymbol( ) ) { list<Symbol> leftSide, rightSide( rule.getRightSide( ) ); leftSide.push_back( newStart ); diff --git a/aconversions/src/re2fa/Brzozowski.cpp b/aconversions/src/re2fa/Brzozowski.cpp index 90f33ce024c039d84cf885b9f8c4363bd7bc41d0..42beed5d6e6743e27b1a36fa46a7cdd1c5dcd7c3 100644 --- a/aconversions/src/re2fa/Brzozowski.cpp +++ b/aconversions/src/re2fa/Brzozowski.cpp @@ -6,6 +6,7 @@ */ #include "Brzozowski.h" +#include <iostream> using namespace alib; using namespace automaton; @@ -69,6 +70,7 @@ FSM Brzozowski::convert( void ) } Q.insert( Qi.at( i ).begin( ), Qi.at( i ).end( ) ); + i += 1; } @@ -125,11 +127,9 @@ Brzozowski::StateBuilder::StateBuilder( const set<RegExp> & Q ) const State & Brzozowski::StateBuilder::getState( const RegExp & re ) const { - // map::find() does not work! see gitlab issue #12 - for( const auto & kv : m_states ) - if( kv.first == re ) - return kv.second; - + auto state = m_states.find( re ); + if( state != m_states.end() ) return state->second; + throw AlibException( "Brzozowski::StateBuilder - Regular expression not found!" ); } diff --git a/aconversions/src/re2rg/re2rrg/BrzozowskiDerivationRRG.cpp b/aconversions/src/re2rg/re2rrg/BrzozowskiDerivationRRG.cpp index 4bb4d63f78847066b3920a51de5e375a72a091a0..afd359c6269f3745c2cdc29573882736ce2692aa 100644 --- a/aconversions/src/re2rg/re2rrg/BrzozowskiDerivationRRG.cpp +++ b/aconversions/src/re2rg/re2rrg/BrzozowskiDerivationRRG.cpp @@ -95,13 +95,31 @@ RightRegularGrammar BrzozowskiDerivationRRG::convert( void ) m_grammar.addRule( r ); } } + + m_grammar.setStartSymbol( builder.getNonTerminal( V ) ); + if( V.containsEmptyString( ) ) { list<Symbol> leftSide = { builder.getNonTerminal( V ) }; - m_grammar.addRule( Rule ( leftSide, list<Symbol>( ) ) ); - } + list<Symbol> rightSide; - m_grammar.setStartSymbol( builder.getNonTerminal( V ) ); + if( m_grammar.isNonTerminalOnRightSideOfAnyRule( m_grammar.getStartSymbol( ) ) ) + { + Symbol newStart = m_grammar.createUniqueNonTerminalSymbol( m_grammar.getStartSymbol( ).getSymbol( ), false ); + + list<Symbol> leftSideNewStart = { newStart }; + for( const auto & rule : m_grammar.getRules( ) ) + if( rule.getLeftSide( ).front( ) == m_grammar.getStartSymbol( ) ) + m_grammar.addRule( Rule( leftSideNewStart, rule.getRightSide( ) ) ); + + m_grammar.setStartSymbol( newStart ); + m_grammar.addRule( Rule( leftSideNewStart, rightSide ) ); + } + else + { + m_grammar.addRule( Rule ( leftSide, rightSide ) ); + } + } return m_grammar; } @@ -141,10 +159,8 @@ BrzozowskiDerivationRRG::NonTerminalBuilder::NonTerminalBuilder( const set<RegEx const Symbol & BrzozowskiDerivationRRG::NonTerminalBuilder::getNonTerminal( const RegExp & re ) const { - // map::find() does not work! see gitlab issue #12 - for( const auto & kv : m_nonTerminals ) - if( kv.first == re ) - return kv.second; + auto state = m_nonTerminals.find( re ); + if( state != m_nonTerminals.end( ) ) return state->second; throw AlibException( "BrzozowskiDerivationRRG::NonTerminalBuilder - Regular expression not found!" ); } diff --git a/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp b/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp index 53d0c68b11dac2e3fc70d8f54623392629bc407d..81650e2418fe4e4ee92e4f14bd3aed947173fa17 100644 --- a/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp +++ b/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp @@ -33,20 +33,19 @@ FSM LRGtoFAConverter::convert( void ) if( m_grammar.isEpsilonRule( rule ) ) continue; - State current( rule.getLeftSide( ).begin( )->getSymbol( ) ); + State current( rule.getLeftSide( ).front( ).getSymbol( ) ); // if B->a => \delta(StartState,a)=B if( rule.getRightSide( ).size( ) == 1 ) { - const Symbol & input( rule.getRightSide( ).begin( )->getSymbol( ) ); + const Symbol & input( rule.getRightSide( ).front( ).getSymbol( ) ); m_automaton.addTransition( startState, input, current ); } // if B->Ca => \delta(C,a)=B else if( rule.getRightSide( ).size( ) == 2 ) { - auto rightSideIter = rule.getRightSide( ).begin( ); - State next( rightSideIter ++ ->getSymbol( ) ); - const Symbol & input = * rightSideIter; + State next( rule.getRightSide( ).front( ).getSymbol( ) ); + const Symbol & input = rule.getRightSide( ).back( ); m_automaton.addTransition( next, input, current ); } diff --git a/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp b/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp index 9788b5f3e7fc47189c31e6f84dcd60319113c9e7..30e6ee74edb6bb9d595840d145f85646754a1806 100644 --- a/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp +++ b/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp @@ -33,18 +33,17 @@ FSM RRGtoFAConverter::convert( void ) if( m_grammar.isEpsilonRule( rule ) ) continue; - State current( rule.getLeftSide( ).begin( )->getSymbol( ) ); + State current( rule.getLeftSide( ).front( ).getSymbol( ) ); if( rule.getRightSide( ).size( ) == 1 ) // if B->a => \delta(B,a)=AState { - const Symbol & input( rule.getRightSide( ).begin( )->getSymbol( ) ); + const Symbol & input( rule.getRightSide( ).front( ).getSymbol( ) ); m_automaton.addTransition( current, input, AState ); } else if( rule.getRightSide( ).size( ) == 2 ) // if B->aC => \delta(B,a)=C { - auto rightSideIter = rule.getRightSide( ).begin( ); - const Symbol & input = * rightSideIter ++; - State next( rightSideIter->getSymbol( ) ); + const Symbol & input = rule.getRightSide( ).front( ); + State next( rule.getRightSide( ).back( ).getSymbol( ) ); m_automaton.addTransition( current, input, next ); } diff --git a/aconversions/src/rg2re/lrg2re/LRGAlgebraic.cpp b/aconversions/src/rg2re/lrg2re/LRGAlgebraic.cpp index deb33731f0cf1fcdc59ab89e85bba7951562c887..d7036f06c30423de8de25085f6ebd533dda45d1b 100644 --- a/aconversions/src/rg2re/lrg2re/LRGAlgebraic.cpp +++ b/aconversions/src/rg2re/lrg2re/LRGAlgebraic.cpp @@ -31,20 +31,20 @@ RegExp LRGAlgebraic::convert( void ) for( const auto & rule : m_grammar.getRules( ) ) { - const Symbol & leftSide = * rule.getLeftSide( ).begin( ); + const Symbol & leftSide = rule.getLeftSide( ).front( ); if( rule.getRightSide( ).size( ) == 0 ) { m_solver.addEquation( leftSide, new RegExpEpsilon( ) ); } else if( rule.getRightSide( ).size( ) == 1 ) { - const Symbol & input = * rule.getRightSide( ).begin( ); + const Symbol & input = rule.getRightSide( ).front( ); m_solver.addEquation( leftSide, new RegExpSymbol( input.getSymbol( ) ) ); } else { - const Symbol nt = * rule.getRightSide( ).begin( ); - const Symbol input = * ( std::next( rule.getRightSide( ).begin( ) ) ); + const Symbol nt = rule.getRightSide( ).front( ); + const Symbol input = rule.getRightSide( ).back( ); m_solver.addEquation( leftSide, nt, new RegExpSymbol( input.getSymbol( ) ) ); } } diff --git a/aconversions/src/rg2re/rrg2re/RRGAlgebraic.cpp b/aconversions/src/rg2re/rrg2re/RRGAlgebraic.cpp index 87a2b7a2d543853b9b4b37353ddba0e208abf7cf..71c92816fea4335e0ac2e13bc94f9e3142cc396e 100644 --- a/aconversions/src/rg2re/rrg2re/RRGAlgebraic.cpp +++ b/aconversions/src/rg2re/rrg2re/RRGAlgebraic.cpp @@ -31,20 +31,20 @@ RegExp RRGAlgebraic::convert( void ) for( const auto & rule : m_grammar.getRules( ) ) { - const Symbol & leftSide = * rule.getLeftSide( ).begin( ); + const Symbol & leftSide = rule.getLeftSide( ).front( ); if( rule.getRightSide( ).size( ) == 0 ) { m_solver.addEquation( leftSide, new RegExpEpsilon( ) ); } else if( rule.getRightSide( ).size( ) == 1 ) { - const Symbol & input = * rule.getRightSide( ).begin( ); + const Symbol & input = rule.getRightSide( ).front( ); m_solver.addEquation( leftSide, new RegExpSymbol( input.getSymbol( ) ) ); } else { - const Symbol input = * rule.getRightSide( ).begin( ); - const Symbol nt = * ( std::next( rule.getRightSide( ).begin( ) ) ); + const Symbol input = rule.getRightSide( ).front( ); + const Symbol nt = rule.getRightSide( ).back( ); m_solver.addEquation( leftSide, nt, new RegExpSymbol( input.getSymbol( ) ) ); } } diff --git a/aconversions/src/rg2rg/lrg2rrg/LeftToRightRegularGrammar.cpp b/aconversions/src/rg2rg/lrg2rrg/LeftToRightRegularGrammar.cpp index cb576b7d89915ab004b88067310afed264375f94..80d5559eb2ca331b1feeb5e30b1b955957d1ab61 100644 --- a/aconversions/src/rg2rg/lrg2rrg/LeftToRightRegularGrammar.cpp +++ b/aconversions/src/rg2rg/lrg2rrg/LeftToRightRegularGrammar.cpp @@ -41,27 +41,27 @@ RightRegularGrammar LeftToRightRegularGrammar::convert( void ) { if( rule.getRightSide( ).size( ) == 2 ) { - list<Symbol> leftSide = { * rule.getRightSide( ).begin( ) }; - list<Symbol> rightSide = { * std::next( rule.getRightSide( ).begin( ) ), * rule.getLeftSide( ).begin( ) }; + list<Symbol> leftSide = { rule.getRightSide( ).front( ) }; + list<Symbol> rightSide = { rule.getRightSide( ).back( ), rule.getLeftSide( ).front( ) }; m_rrg.addRule( Rule( leftSide, rightSide ) ); - if( * rule.getLeftSide( ).begin( ) == m_lrg.getStartSymbol( ) ) + if( rule.getLeftSide( ).front( ) == m_lrg.getStartSymbol( ) ) { - list<Symbol> leftSide = { * rule.getRightSide( ).begin( ) }; - list<Symbol> rightSide = { * std::next( rule.getRightSide( ).begin( ) ) }; + list<Symbol> leftSide = { rule.getRightSide( ).front( ) }; + list<Symbol> rightSide = { rule.getRightSide( ).back( ) }; m_rrg.addRule( Rule( leftSide, rightSide ) ); } } else if( rule.getRightSide( ).size( ) == 1 ) { list<Symbol> leftSide = { m_rrg.getStartSymbol( ) }; - list<Symbol> rightSide = { * rule.getRightSide( ).begin( ), *rule.getLeftSide( ).begin( ) }; + list<Symbol> rightSide = { rule.getRightSide( ).front( ), rule.getLeftSide( ).front( ) }; m_rrg.addRule( Rule( leftSide, rightSide ) ); - if( * rule.getLeftSide( ).begin( ) == m_lrg.getStartSymbol( ) ) + if( rule.getLeftSide( ).front( ) == m_lrg.getStartSymbol( ) ) { list<Symbol> leftSide = { m_rrg.getStartSymbol( ) }; - list<Symbol> rightSide = { * rule.getRightSide( ).begin( ) }; + list<Symbol> rightSide = { rule.getRightSide( ).front( ) }; m_rrg.addRule( Rule( leftSide, rightSide ) ); } } diff --git a/aconversions/src/rg2rg/rrg2lrg/RightToLeftRegularGrammar.cpp b/aconversions/src/rg2rg/rrg2lrg/RightToLeftRegularGrammar.cpp index 75a62e6708a56cdfaee457d43d28b2fc80b82fad..35490051646cb43bad0ee5c55e624c7586cf1680 100644 --- a/aconversions/src/rg2rg/rrg2lrg/RightToLeftRegularGrammar.cpp +++ b/aconversions/src/rg2rg/rrg2lrg/RightToLeftRegularGrammar.cpp @@ -41,27 +41,27 @@ LeftRegularGrammar RightToLeftRegularGrammar::convert( void ) { if( rule.getRightSide( ).size( ) == 2 ) { - list<Symbol> leftSide = { * std::next( rule.getRightSide( ).begin( ) ) }; - list<Symbol> rightSide = { * rule.getLeftSide( ).begin( ), * rule.getRightSide( ).begin( ) }; + list<Symbol> leftSide = { rule.getRightSide( ).back( ) }; + list<Symbol> rightSide = { rule.getLeftSide( ).front( ), rule.getRightSide( ).front( ) }; m_lrg.addRule( Rule( leftSide, rightSide ) ); - if( * rule.getLeftSide( ).begin( ) == m_rrg.getStartSymbol( ) ) + if( rule.getLeftSide( ).front( ) == m_rrg.getStartSymbol( ) ) { - list<Symbol> leftSide = { * std::next( rule.getRightSide( ).begin( ) ) }; - list<Symbol> rightSide = { * rule.getRightSide( ).begin( ) }; + list<Symbol> leftSide = { rule.getRightSide( ).back( ) }; + list<Symbol> rightSide = { rule.getRightSide( ).front( ) }; m_lrg.addRule( Rule( leftSide, rightSide ) ); } } else if( rule.getRightSide( ).size( ) == 1 ) { list<Symbol> leftSide = { m_lrg.getStartSymbol( ) }; - list<Symbol> rightSide = { * rule.getLeftSide( ).begin( ), *rule.getRightSide( ).begin( ) }; + list<Symbol> rightSide = { rule.getLeftSide( ).front( ), rule.getRightSide( ).front( ) }; m_lrg.addRule( Rule( leftSide, rightSide ) ); - if( * rule.getLeftSide( ).begin( ) == m_rrg.getStartSymbol( ) ) + if( rule.getLeftSide( ).front( ) == m_rrg.getStartSymbol( ) ) { list<Symbol> leftSide = { m_lrg.getStartSymbol( ) }; - list<Symbol> rightSide = { * rule.getRightSide( ).begin( ) }; + list<Symbol> rightSide = { rule.getRightSide( ).front( ) }; m_lrg.addRule( Rule( leftSide, rightSide ) ); } } diff --git a/alib/makefile b/alib/makefile index 67ac588fe3d9f118a8b7c951627e6e7c46fdaa32..588666118e0af0cb1b4ed5e090314199f99bb4d8 100644 --- a/alib/makefile +++ b/alib/makefile @@ -1,6 +1,6 @@ CC=g++ LIBRARY=libalib.so -CCFLAGS= -std=c++11 -O2 -c -Wall -fPIC -I/usr/include/libxml2/ +CCFLAGS= -std=c++11 -O2 -g -c -Wall -fPIC -I/usr/include/libxml2/ LDFLAGS= -shared -lxml2 SOURCES=$(shell find src/ -name *cpp) diff --git a/alib/src/regexp/Alternation.cpp b/alib/src/regexp/Alternation.cpp index 81ff4f56fafce9c54c6968c92b424c3abceb9b58..aac9219f55ed47a13bc213dfcab3fb030db76925 100644 --- a/alib/src/regexp/Alternation.cpp +++ b/alib/src/regexp/Alternation.cpp @@ -80,10 +80,11 @@ bool Alternation::operator<(const Alternation& other) const { auto thisIter = this->elements.begin(); auto otherIter = other.elements.begin(); for(; thisIter != this->elements.end(); thisIter++, otherIter++) { - if(**thisIter < **otherIter) return true; + if(**thisIter != **otherIter) break; } + if(thisIter == this->elements.end()) return false; - return false; + return **thisIter < **otherIter; } bool Alternation::operator==(const Alternation& other) const { @@ -103,15 +104,15 @@ bool Alternation::containsEmptyString() const { if(e->containsEmptyString()) return true; - return false; + return false; // alternation of zero regexps is empty } bool Alternation::isEmpty() const { for(const auto& e : getElements()) if(!e->isEmpty()) - return true; + return false; - return false; + return true; // alternation of zero regexps is empty } } /* namespace regexp */ diff --git a/alib/src/regexp/Concatenation.cpp b/alib/src/regexp/Concatenation.cpp index 602ebde3c8a4d2386d1e0151a8e82ce3d02a2807..087f14074e913757b1e5df8eb53da2c03c3532b8 100644 --- a/alib/src/regexp/Concatenation.cpp +++ b/alib/src/regexp/Concatenation.cpp @@ -76,10 +76,11 @@ bool Concatenation::operator<(const Concatenation& other) const { auto thisIter = this->elements.begin(); auto otherIter = other.elements.begin(); for(; thisIter != this->elements.end(); thisIter++, otherIter++) { - if(**thisIter < **otherIter) return true; + if(**thisIter != **otherIter) break; } + if(thisIter == this->elements.end()) return false; - return false; + return **thisIter < **otherIter; } bool Concatenation::operator==(const Concatenation& other) const { @@ -99,15 +100,15 @@ bool Concatenation::containsEmptyString() const { if( ! e->containsEmptyString()) return false; - return true; + return true; // concatenation of zero regexps is epsilon } bool Concatenation::isEmpty() const { for(const auto& e : getElements()) - if(!e->isEmpty()) - return false; + if(e->isEmpty()) + return true; - return true; + return false; // concatenation of zero regexps is epsilon } } /* namespace regexp */ diff --git a/alib/src/std/variant.hpp b/alib/src/std/variant.hpp index fa8a96c626e6fad1f1862f232fb07da0949b5341..3771d4c477ba9c520d15381f71e35b0c460812c6 100644 --- a/alib/src/std/variant.hpp +++ b/alib/src/std/variant.hpp @@ -57,7 +57,7 @@ struct variant_helper<F, Ts...> { if (old_t == typeid(F).hash_code()) new (new_v) F(*reinterpret_cast<const F*>(old_v)); else - variant_helper<Ts...>::copy(old_t, old_v, new_v); + return variant_helper<Ts...>::copy(old_t, old_v, new_v); } inline static bool compareEq(size_t this_t, const void * this_v, size_t other_t, const void * other_v) @@ -65,7 +65,7 @@ struct variant_helper<F, Ts...> { if (this_t == typeid(F).hash_code()) return this_t == other_t && *(reinterpret_cast<const F*>(this_v)) == *(reinterpret_cast<const F*>(other_v)); else - variant_helper<Ts...>::compareEq(this_t, this_v, other_t, other_v); + return variant_helper<Ts...>::compareEq(this_t, this_v, other_t, other_v); } inline static bool compareLess(size_t this_t, const void * this_v, size_t other_t, const void * other_v) @@ -76,7 +76,7 @@ struct variant_helper<F, Ts...> { if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code()) return *(reinterpret_cast<const F*>(this_v)) < *(reinterpret_cast<const F*>(other_v)); else - variant_helper<Ts...>::compareLess(this_t, this_v, other_t, other_v); + return variant_helper<Ts...>::compareLess(this_t, this_v, other_t, other_v); } }; diff --git a/alib/src/string/String.cpp b/alib/src/string/String.cpp index 7f746927d4ed6e420a2450077297a7e069625494..db3a74b2f45acba3d5b88a6082d6e7a8ade938d8 100644 --- a/alib/src/string/String.cpp +++ b/alib/src/string/String.cpp @@ -5,6 +5,8 @@ * Author: Jan Travnicek */ +#include <algorithm> + #include "String.h" #include "StringPrinter.h" #include "../AlibException.h" @@ -19,16 +21,21 @@ String::String() { void String::addAlphabetSymbol(const alphabet::Symbol& symbol) { std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = this->alphabet.insert(symbol); if (!ret.second) - throw alib::AlibException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); + throw alib::AlibException("Alphabet symbol \"" + symbol.getSymbol() + "\" already exists."); } void String::removeAlphabetSymbol(const alphabet::Symbol& symbol) { - auto it = this->alphabet.find (symbol); - if(it != this->alphabet.end()) - throw alib::AlibException("Input symbol \"" + symbol.getSymbol() + "\" used in string."); + auto it = this->alphabet.find( symbol ); + if( it == this->alphabet.end()) + throw alib::AlibException("Symbol \"" + symbol.getSymbol() + "\" is not in alphabet."); + + auto it2 = std::find( this->symbols.begin( ), this->symbols.end( ), symbol ); + if(it2 != this->symbols.end()) + throw alib::AlibException("Symbol \"" + symbol.getSymbol() + "\" is used in string."); + this->alphabet.erase(symbol); } - + const std::set<alphabet::Symbol>& String::getAlphabet() const { return this->alphabet; } @@ -45,11 +52,11 @@ bool String::isEmpty() const { return this->symbols.size() == 0; } -void String::toXML(std::ostream& out) { +void String::toXML(std::ostream& out) const { StringPrinter::toXML(*this, out); } -std::ostream& operator <<(std::ostream& out, String& string) { +std::ostream& operator <<(std::ostream& out, const String& string) { string.toXML(out); return out; } diff --git a/alib/src/string/String.h b/alib/src/string/String.h index 12277cece68d4c05cbde6632cc8ea1acc77d0578..dc4f603fa024fa85b25b8f0b6df29f50e3980a22 100644 --- a/alib/src/string/String.h +++ b/alib/src/string/String.h @@ -28,39 +28,39 @@ private: public: String(); - + /** * Adds input symbol to the alphabet. * @param symbol Symbol to add - * @throws AutomatonException when symbol already exists + * @throws AlibException if symbol already exists */ void addAlphabetSymbol(const alphabet::Symbol& symbol); /** * Removes input symbol from the the alphabet. * @param symbol Symbol to remove - * @throws AutomatonException when symbol is not present in input alphabet - * or when symbol is part of the transition + * @throws AlibException if symbol is not present in input alphabet + * or when symbol is present in content of the string. */ void removeAlphabetSymbol(const alphabet::Symbol& symbol); - + /** * @return the input alphabet */ const std::set<alphabet::Symbol>& getAlphabet() const; /** - * @return Root node of the regular expression tree + * @return List of symbols forming string. */ std::list<alphabet::Symbol>& getContent(); /** - * @return Root node of the regular expression tree + * @return List of symbols forming string (const version). */ const std::list<alphabet::Symbol>& getContent() const; /** - * @return true if regexp represents empty language + * @return true if string is an empty word (its length is 0) */ bool isEmpty() const; @@ -68,14 +68,14 @@ public: * Prints XML representation of the String to the output stream. * @param out output stream to which print the String */ - void toXML(std::ostream& out); + void toXML(std::ostream& out) const; /** * Prints XML representation of the String to the output stream. * @param out output stream to which print the String - * @param regexp String to print + * @param string String to print */ - friend std::ostream& operator<<(std::ostream& out, String& regexp); + friend std::ostream& operator<<(std::ostream& out, const String& string); }; diff --git a/alib/src/string/StringPrinter.cpp b/alib/src/string/StringPrinter.cpp index f0970f4873b28145ffced5d1d2e84765d8508c7f..3746e5f6a438ad379107c7f9cfa6a3e2ef9ce2f0 100644 --- a/alib/src/string/StringPrinter.cpp +++ b/alib/src/string/StringPrinter.cpp @@ -12,14 +12,14 @@ namespace string { const std::string StringPrinter::INDENTATION = "\t"; -void StringPrinter::toXML(String& string, std::ostream& out) { +void StringPrinter::toXML(const String& string, std::ostream& out) { out << "<string>\n"; printAlphabet(string, out, INDENTATION); printContent(string, out, INDENTATION); out << "</string>\n"; } -void StringPrinter::printAlphabet(String& string, std::ostream& out, std::string prefix) { +void StringPrinter::printAlphabet(const String& string, std::ostream& out, const std::string & prefix) { out << prefix << "<alphabet>\n"; for (auto element : string.getAlphabet()) { printSymbol(element, out, prefix + INDENTATION); @@ -27,7 +27,7 @@ void StringPrinter::printAlphabet(String& string, std::ostream& out, std::string out << prefix << "</alphabet>\n"; } -void StringPrinter::printContent(String& string, std::ostream& out, std::string prefix) { +void StringPrinter::printContent(const String& string, std::ostream& out, const std::string & prefix) { out << prefix << "<content>\n"; for (auto element : string.getContent()) { printSymbol(element, out, prefix + INDENTATION); @@ -35,10 +35,8 @@ void StringPrinter::printContent(String& string, std::ostream& out, std::string out << prefix << "</content>\n"; } -void StringPrinter::printSymbol(alphabet::Symbol& element, std::ostream& out, std::string prefix) { - out << prefix << "<symbol>\n"; - out << prefix << element.getSymbol(); - out << prefix << "</symbol>\n"; +void StringPrinter::printSymbol(const alphabet::Symbol& element, std::ostream& out, const std::string & prefix) { + out << prefix << "<symbol>" << element.getSymbol() << "</symbol>\n"; } } /* namespace string */ diff --git a/alib/src/string/StringPrinter.h b/alib/src/string/StringPrinter.h index e5f178c53cbbe9c14ce0955cc476f1cb2f0be257..192fa9fa1988f1eeb45859260ede00b345196400 100644 --- a/alib/src/string/StringPrinter.h +++ b/alib/src/string/StringPrinter.h @@ -15,21 +15,22 @@ namespace notions { namespace string { /** - * This class contains methods to print XML representation of regular expression to the output stream. + * This class contains methods to print XML representation of string to the output stream. */ class StringPrinter { protected: static const std::string INDENTATION; - static void printContent(String& element, std::ostream& out, std::string prefix); - static void printAlphabet(String& content, std::ostream& out, std::string prefix); - static void printSymbol(alphabet::Symbol& symbol, std::ostream& out, std::string prefix); + + static void printContent(const String& element, std::ostream& out, const std::string & prefix); + static void printAlphabet(const String& content, std::ostream& out, const std::string & prefix); + static void printSymbol(const alphabet::Symbol& symbol, std::ostream& out, const std::string & prefix); public: /** - * Prints XML representation of RegExp to the output stream. - * @param regexp RegExp to print - * @param out output stream to which print the RegExp + * Prints XML representation of String to the output stream. + * @param string String to print + * @param out output stream to which print the String */ - static void toXML(notions::string::String& regexp, std::ostream& out); + static void toXML(const notions::string::String& regexp, std::ostream& out); }; } /* namespace string */ diff --git a/examples/DFSM1IS.xml b/examples/automaton/DFSM1IS.xml similarity index 100% rename from examples/DFSM1IS.xml rename to examples/automaton/DFSM1IS.xml diff --git a/examples/FSM.xml b/examples/automaton/FSM.xml similarity index 100% rename from examples/FSM.xml rename to examples/automaton/FSM.xml diff --git a/examples/FSM2.xml b/examples/automaton/FSM2.xml similarity index 100% rename from examples/FSM2.xml rename to examples/automaton/FSM2.xml diff --git a/examples/NFSM1.DET.xml b/examples/automaton/NFSM1.DET.xml similarity index 100% rename from examples/NFSM1.DET.xml rename to examples/automaton/NFSM1.DET.xml diff --git a/examples/NFSM1.xml b/examples/automaton/NFSM1.xml similarity index 100% rename from examples/NFSM1.xml rename to examples/automaton/NFSM1.xml diff --git a/examples/NFSM2.xml b/examples/automaton/NFSM2.xml similarity index 100% rename from examples/NFSM2.xml rename to examples/automaton/NFSM2.xml diff --git a/examples/NFSM3.xml b/examples/automaton/NFSM3.xml similarity index 100% rename from examples/NFSM3.xml rename to examples/automaton/NFSM3.xml diff --git a/examples/NFSM4.xml b/examples/automaton/NFSM4.xml similarity index 100% rename from examples/NFSM4.xml rename to examples/automaton/NFSM4.xml diff --git a/examples/automaton/NFSM5.DET.MIN.xml b/examples/automaton/NFSM5.DET.MIN.xml new file mode 100644 index 0000000000000000000000000000000000000000..906bc8b8728944050d3ca7a0aad97cbfb84b3027 --- /dev/null +++ b/examples/automaton/NFSM5.DET.MIN.xml @@ -0,0 +1,107 @@ +<automaton> + <states> + <state>0</state> + <state>1</state> + <state>2</state> + <state>3</state> + <state>4</state> + <state>5</state> + <state>6</state> + <state>7</state> + <state>8</state> + <state>9</state> + </states> + <inputAlphabet> + <symbol>f</symbol> + <symbol>i</symbol> + <symbol>l</symbol> + <symbol>z</symbol> + </inputAlphabet> + <transitions> + <transition> + <from>0</from> + <input>l</input> + <to>1</to> + </transition> + <transition> + <from>1</from> + <input>i</input> + <to>2</to> + </transition> + <transition> + <from>1</from> + <input>l</input> + <to>3</to> + </transition> + <transition> + <from>1</from> + <input>z</input> + <to>4</to> + </transition> + <transition> + <from>3</from> + <input>l</input> + <to>4</to> + </transition> + <transition> + <from>3</from> + <input>z</input> + <to>5</to> + </transition> + <transition> + <from>4</from> + <input>f</input> + <to>6</to> + </transition> + <transition> + <from>4</from> + <input>l</input> + <to>7</to> + </transition> + <transition> + <from>5</from> + <input>l</input> + <to>6</to> + </transition> + <transition> + <from>6</from> + <input>f</input> + <to>8</to> + </transition> + <transition> + <from>7</from> + <input>f</input> + <to>2</to> + </transition> + <transition> + <from>7</from> + <input>i</input> + <to>9</to> + </transition> + <transition> + <from>7</from> + <input>l</input> + <to>6</to> + </transition> + <transition> + <from>8</from> + <input>z</input> + <to>8</to> + </transition> + <transition> + <from>9</from> + <input>l</input> + <to>0</to> + </transition> + </transitions> + <initialStates> + <state>0</state> + </initialStates> + <finalStates> + <state>2</state> + <state>5</state> + <state>7</state> + <state>8</state> + <state>9</state> + </finalStates> +</automaton> diff --git a/examples/automaton/NFSM5.xml b/examples/automaton/NFSM5.xml new file mode 100644 index 0000000000000000000000000000000000000000..31d4fe17e35719980044098da5c01270ca1b2aef --- /dev/null +++ b/examples/automaton/NFSM5.xml @@ -0,0 +1,108 @@ +<automaton> + <states> + <state>0</state> + <state>1</state> + <state>10</state> + <state>2</state> + <state>3</state> + <state>4</state> + <state>5</state> + <state>6</state> + <state>7</state> + <state>8</state> + <state>9</state> + </states> + <inputAlphabet> + <symbol>f</symbol> + <symbol>i</symbol> + <symbol>l</symbol> + <symbol>z</symbol> + </inputAlphabet> + <transitions> + <transition> + <from>0</from> + <input>l</input> + <to>5</to> + </transition> + <transition> + <from>1</from> + <input>l</input> + <to>3</to> + </transition> + <transition> + <from>10</from> + <input>z</input> + <to>10</to> + </transition> + <transition> + <from>2</from> + <input>f</input> + <to>3</to> + </transition> + <transition> + <from>2</from> + <input>l</input> + <to>1</to> + </transition> + <transition> + <from>2</from> + <input>l</input> + <to>7</to> + </transition> + <transition> + <from>3</from> + <input>f</input> + <to>10</to> + </transition> + <transition> + <from>4</from> + <input>l</input> + <to>2</to> + </transition> + <transition> + <from>4</from> + <input>z</input> + <to>1</to> + </transition> + <transition> + <from>5</from> + <input>i</input> + <to>6</to> + </transition> + <transition> + <from>5</from> + <input>l</input> + <to>4</to> + </transition> + <transition> + <from>5</from> + <input>z</input> + <to>2</to> + </transition> + <transition> + <from>7</from> + <input>f</input> + <to>9</to> + </transition> + <transition> + <from>7</from> + <input>i</input> + <to>8</to> + </transition> + <transition> + <from>8</from> + <input>l</input> + <to>0</to> + </transition> + </transitions> + <initialStates> + <state>0</state> + </initialStates> + <finalStates> + <state>1</state> + <state>10</state> + <state>6</state> + <state>8</state> + <state>9</state> + </finalStates> +</automaton> diff --git a/examples/NIDPDA1.xml b/examples/automaton/NIDPDA1.xml similarity index 100% rename from examples/NIDPDA1.xml rename to examples/automaton/NIDPDA1.xml diff --git a/examples/NIDPDA2.xml b/examples/automaton/NIDPDA2.xml similarity index 100% rename from examples/NIDPDA2.xml rename to examples/automaton/NIDPDA2.xml diff --git a/examples/NIDPDA3.xml b/examples/automaton/NIDPDA3.xml similarity index 100% rename from examples/NIDPDA3.xml rename to examples/automaton/NIDPDA3.xml diff --git a/examples/NIDPDA4.xml b/examples/automaton/NIDPDA4.xml similarity index 100% rename from examples/NIDPDA4.xml rename to examples/automaton/NIDPDA4.xml diff --git a/examples/PDA.xml b/examples/automaton/PDA.xml similarity index 100% rename from examples/PDA.xml rename to examples/automaton/PDA.xml diff --git a/examples/RHDPDA2.xml b/examples/automaton/RHDPDA2.xml similarity index 100% rename from examples/RHDPDA2.xml rename to examples/automaton/RHDPDA2.xml diff --git a/examples/RHDPDA3.xml b/examples/automaton/RHDPDA3.xml similarity index 100% rename from examples/RHDPDA3.xml rename to examples/automaton/RHDPDA3.xml diff --git a/examples/RHDPDA4.xml b/examples/automaton/RHDPDA4.xml similarity index 100% rename from examples/RHDPDA4.xml rename to examples/automaton/RHDPDA4.xml diff --git a/examples/RHDPDA5.xml b/examples/automaton/RHDPDA5.xml similarity index 100% rename from examples/RHDPDA5.xml rename to examples/automaton/RHDPDA5.xml diff --git a/examples/TM.xml b/examples/automaton/TM.xml similarity index 100% rename from examples/TM.xml rename to examples/automaton/TM.xml diff --git a/examples/TM2.xml b/examples/automaton/TM2.xml similarity index 100% rename from examples/TM2.xml rename to examples/automaton/TM2.xml diff --git a/examples/TM3.xml b/examples/automaton/TM3.xml similarity index 100% rename from examples/TM3.xml rename to examples/automaton/TM3.xml diff --git a/examples/VPA1.xml b/examples/automaton/VPA1.xml similarity index 100% rename from examples/VPA1.xml rename to examples/automaton/VPA1.xml diff --git a/examples/VPA2.xml b/examples/automaton/VPA2.xml similarity index 100% rename from examples/VPA2.xml rename to examples/automaton/VPA2.xml diff --git a/examples/string/empty.xml b/examples/string/empty.xml new file mode 100644 index 0000000000000000000000000000000000000000..de8c746eb7c0be98bdae0e9f420a0650675722f7 --- /dev/null +++ b/examples/string/empty.xml @@ -0,0 +1,10 @@ +<string> + <alphabet> + <symbol>a</symbol> + <symbol>c</symbol> + <symbol>t</symbol> + <symbol>g</symbol> + </alphabet> + <content> + </content> +</string> diff --git a/examples/string/word.xml b/examples/string/word.xml new file mode 100644 index 0000000000000000000000000000000000000000..fc94c10ad13ed69d8ec96dcbe37281d0075bc9e9 --- /dev/null +++ b/examples/string/word.xml @@ -0,0 +1,21 @@ +<string> + <alphabet> + <symbol>a</symbol> + <symbol>c</symbol> + <symbol>t</symbol> + <symbol>g</symbol> + </alphabet> + <content> + <symbol>a</symbol> + <symbol>t</symbol> + <symbol>t</symbol> + <symbol>c</symbol> + <symbol>g</symbol> + <symbol>c</symbol> + <symbol>c</symbol> + <symbol>g</symbol> + <symbol>t</symbol> + <symbol>t</symbol> + <symbol>a</symbol> + </content> +</string> diff --git a/tests.aconversion.sh b/tests.aconversion.sh new file mode 100755 index 0000000000000000000000000000000000000000..bb4d4735e06d1ab31a8f44c0ca9891f74f3b815f --- /dev/null +++ b/tests.aconversion.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash + +TESTCASE_ITERATIONS=150 +TESTCASE_TIMEOUT=7 +LOGFILE="log_tests.txt" + +EXECUTABLES="arand aepsilon atrim adeterminize aminimize anormalize adiff.automaton aconversion" + +# ---------------------------- + +for FILE in $EXECUTABLES; do + if [ ! -f bin/$FILE ]; then + echo "Executable" $FILE "is required for testing. Make sure it is in bin folder." + exit 1 + fi +done + +cd bin/ +rm -f $LOGFILE + +# ---------------------------- + +function mDFA { + echo "$1" | ./aepsilon | ./atrim | ./adeterminize -t FSM | ./aminimize | ./anormalize +} + +function compare { + echo "$1" > tmp1.xml + echo "$2" > tmp2.xml + + # relies on ret code by adiff.automaton + ./adiff.automaton tmp1.xml tmp2.xml + RET=$? + rm tmp1.xml tmp2.xml + + return $RET +} + +# generates random NFA with $1 density, $2 states and $3 elements of alphabet +function generate { + # ./arand -d $1 -n $2 -a $3 + ./arand -d $1 -n $(( $RANDOM % $2 + 1 )) -a $(( $RANDOM % $3 + 1 )) +} + +# $1 = command for conversion. Output of such command must be (eps-)NFA !! +function runTest2 { + TMPNFA="nfa.xml" + echo "$(generate 3 15 3)" > $TMPNFA + + TMP=$(timeout $TESTCASE_TIMEOUT bash -c "cat $TMPNFA | $1") + RETTMP=$? + if [ $RETTMP -ge 123 ]; then + return 2 + fi + + mDFA1=$(mDFA "$(cat $TMPNFA)") + mDFA2=$(mDFA "$TMP") + + CMP=$(compare "$mDFA1" "$mDFA2") + if [ $? == 0 ]; then + rm nfa.xml + return 0 + else + echo "-----------------------------------------" >> $LOGFILE + echo "$1" >> $LOGFILE + echo "$CMP" >> $LOGFILE + echo $(cat nfa.xml) >> $LOGFILE + rm nfa.xml + return 1 + fi +} + +function runTest { + ITERS=$TESTCASE_ITERATIONS + RES_GOOD=0 + RES_BAD=0 + RES_TIMEOUT=0 + + if [ $# == 0 ] || [ $# -gt 2 ]; then + echo "Invalid runTest call." + exit + elif [ $# == 2 ]; then + ITERS=$2 + fi + + + echo $1 + echo -ne "\t" + for i in $(seq 1 $ITERS ); + do + + runTest2 "$1" + RETTEST=$? + + if [ $RETTEST == 0 ]; then + echo -n "." + RES_GOOD=$((RES_GOOD + 1)) + elif [ $RETTEST == 1 ]; then + echo -n "x" + RES_BAD=$((RES_BAD + 1)) + elif [ $RETTEST == 2 ]; then + echo -n "T" + RES_TIMEOUT=$((RES_TIMEOUT + 1)) + elif [ $RETTEST == 3 ]; then + echo -n "F" + RES_BAD=$((RES_BAD + 1)) + else + echo -n "?" + fi + done + + echo -ne "\n\t" + echo "RES: GOOD:" $RES_GOOD ", BAD:" $RES_BAD ", TIMEOUT:" $RES_TIMEOUT + echo "" +} + +# FA -> RG -> FA +# covers: FA -> LRG, FA -> RRG, RRG <-> LRG, RRG -> FA, LRG -> FA +runTest "./aconversion -t RRG | ./aconversion -t LRG | ./aconversion -t FA" +runTest "./aconversion -t LRG | ./aconversion -t RRG | ./aconversion -t FA" + +# FA -> RE -> FA +# covers: FA -> RE (Brzozowski algebraic, elimination), RE -> FA (Brzozowski derivation, Thompson, Glushkov) +runTest "./aconversion -t RE -a algebraic | ./aconversion -t FA -a brzozowski" +runTest "./aconversion -t RE -a algebraic | ./aconversion -t FA -a thompson" +runTest "./aconversion -t RE -a algebraic | ./aconversion -t FA -a glushkov " +runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a brzozowski" +runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a thompson" +runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a glushkov" + +# FA -> RE -> RRG -> LRG -> FA +# covers: FA -> RE (Brz. algebraic, elimination), RE -> RRG ( Brz. derivation, Glushkov), RRG -> LRG, LRG -> FA +runTest "./aconversion -t RE -a algebraic | ./aconversion -t RRG -a brzozowski | ./aconversion -t LRG | ./aconversion -t FA" +runTest "./aconversion -t RE -a algebraic | ./aconversion -t RRG -a glushkov | ./aconversion -t LRG | ./aconversion -t FA" +runTest "./aconversion -t RE -a elimination | ./aconversion -t RRG -a brzozowski | ./aconversion -t LRG | ./aconversion -t FA" +runTest "./aconversion -t RE -a elimination | ./aconversion -t RRG -a glushkov | ./aconversion -t LRG | ./aconversion -t FA" + +# FA -> RRG -> RE -> FA +# covers: FA -> RRG, FA -> LRG, RRG -> RE, LRG -> RE, RE -> FA (Brz. derivation, Thompson, Glushkov) +runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA brzozowski" +runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA brzozowski" +runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA thompson" +runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA thompson" +runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA glushkov" +runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA glushkov"