From 7c3655d11dab15e9bfcfd637fd2d26fba24d0c54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <peckato1@fit.cvut.cz>
Date: Thu, 13 Mar 2014 15:06:01 +0100
Subject: [PATCH] RE -> RRG Glushkov v1

---
 .../src/aconversion/ConversionHandler.cpp     |  13 +-
 .../src/aconversion/ConversionHandler.h       |   2 +
 aconversions/src/include/macros.h             |   2 +-
 .../re2rg/re2rrg/AbstractREtoRRGConverter.h   |   1 +
 aconversions/src/re2rg/re2rrg/GlushkovRRG.cpp | 148 +++++++++
 aconversions/src/re2rg/re2rrg/GlushkovRRG.h   |  55 ++++
 aconversions/src/shared/GlushkovTraversal.cpp | 296 ++++++++++++++++++
 aconversions/src/shared/GlushkovTraversal.h   |  70 +++++
 8 files changed, 584 insertions(+), 3 deletions(-)
 create mode 100644 aconversions/src/re2rg/re2rrg/GlushkovRRG.cpp
 create mode 100644 aconversions/src/re2rg/re2rrg/GlushkovRRG.h
 create mode 100644 aconversions/src/shared/GlushkovTraversal.cpp
 create mode 100644 aconversions/src/shared/GlushkovTraversal.h

diff --git a/aconversions/src/aconversion/ConversionHandler.cpp b/aconversions/src/aconversion/ConversionHandler.cpp
index b986415b81..b18f150a4a 100644
--- a/aconversions/src/aconversion/ConversionHandler.cpp
+++ b/aconversions/src/aconversion/ConversionHandler.cpp
@@ -171,6 +171,14 @@ void ConversionHandler::convertRegExp( ostream & out )
             conv->convert( ).toXML( out );
             delete conv;
         }
+        else if ( m_algorithm == GLUSHKOV_RRG )
+        {
+            AbstractREtoRRGConverter* conv;
+
+            conv = new GlushkovRRG( regexp );
+            conv->convert( ).toXML( out );
+            delete conv;
+        }
     }
 }
 
@@ -247,6 +255,7 @@ ConversionHandler::TAlgorithm ConversionHandler::parseAlgorithmFromString( const
 
     /* RE to RG */
     if( algorithm == "brzozowskirrg") return BRZOZOWSKI_RRG;
+    if( algorithm == "glushkovrrg") return GLUSHKOV_RRG;
 
     /* RG to FA */
     if( algorithm == "rg" ) return RG_FA;
@@ -262,7 +271,7 @@ ConversionHandler::TAlgorithm ConversionHandler::getDefaultAlgorithm( void ) con
     if( m_source == FINITE_AUTOMATA && m_target == REGULAR_EXPRESSION ) return STATE_ELIMINATION;
     if( m_source == FINITE_AUTOMATA && m_target == REGULAR_GRAMMAR )    return FA_RRG;
     if( m_source == REGULAR_EXPRESSION && m_target == FINITE_AUTOMATA ) return GLUSHKOV;
-    if( m_source == REGULAR_EXPRESSION && m_target == REGULAR_GRAMMAR ) return BRZOZOWSKI_RRG;
+    if( m_source == REGULAR_EXPRESSION && m_target == REGULAR_GRAMMAR ) return GLUSHKOV_RRG;
     if( m_source == REGULAR_GRAMMAR && m_target == FINITE_AUTOMATA )    return RG_FA;
     if( m_source == REGULAR_GRAMMAR && m_target == REGULAR_EXPRESSION ) return BRZOZOWSKI_ALGEBRAIC;
     if( m_source == REGULAR_GRAMMAR && m_target == REGULAR_GRAMMAR )    return LRG_RRG;
@@ -288,7 +297,7 @@ bool ConversionHandler::checkAlgorithm( void ) const
         return ( m_target == FINITE_AUTOMATA &&
                     ( m_algorithm == BRZOZOWSKI_DERIVATION || m_algorithm == GLUSHKOV || m_algorithm == THOMPSON ) ) ||
                ( m_target == REGULAR_GRAMMAR &&
-                    ( m_algorithm == BRZOZOWSKI_RRG) );
+                    ( m_algorithm == BRZOZOWSKI_RRG || m_algorithm == GLUSHKOV_RRG ) );
 
     /* RG to FA */
     /* RG to RE */
diff --git a/aconversions/src/aconversion/ConversionHandler.h b/aconversions/src/aconversion/ConversionHandler.h
index a5e27368a7..28f911930a 100644
--- a/aconversions/src/aconversion/ConversionHandler.h
+++ b/aconversions/src/aconversion/ConversionHandler.h
@@ -31,6 +31,7 @@
 #include "../re2rg/re2rrg/BrzozowskiDerivationRRG.h"
 #include "../lrg2rrg/LeftToRightRegularGrammar.h"
 #include "../rrg2lrg/RightToLeftRegularGrammar.h"
+#include "../re2rg/re2rrg/GlushkovRRG.h"
 
 namespace conversions
 {
@@ -57,6 +58,7 @@ public:
 
         /* RE to RG */
         BRZOZOWSKI_RRG,
+        GLUSHKOV_RRG,
 
         /* RG to FA */
         RG_FA,
diff --git a/aconversions/src/include/macros.h b/aconversions/src/include/macros.h
index 6af4fc212f..735e229948 100644
--- a/aconversions/src/include/macros.h
+++ b/aconversions/src/include/macros.h
@@ -9,7 +9,7 @@ namespace conversions
 {
 
 #define isInSet(x,set) ( (set).find((x)) != (set).end() )
-#define isInList(x,list) ( find((list).begin(), (list).end(), (x)) )
+#define isInList(x,list) ( find((list).begin(), (list).end(), (x)) != (list).end() )
 #define isKeyInMap(key,map) ( (map).find((key)) != (map).end() )
 
 } /* namespace conversions */
diff --git a/aconversions/src/re2rg/re2rrg/AbstractREtoRRGConverter.h b/aconversions/src/re2rg/re2rrg/AbstractREtoRRGConverter.h
index d31f20ace0..7e313f5135 100644
--- a/aconversions/src/re2rg/re2rrg/AbstractREtoRRGConverter.h
+++ b/aconversions/src/re2rg/re2rrg/AbstractREtoRRGConverter.h
@@ -11,6 +11,7 @@
 #include <regexp/RegExp.h>
 #include <grammar/Regular/RightRegularGrammar.h>
 
+#include "../../include/macros.h"
 #include "../AbstractREtoRGConverter.h"
 
 namespace conversions
diff --git a/aconversions/src/re2rg/re2rrg/GlushkovRRG.cpp b/aconversions/src/re2rg/re2rrg/GlushkovRRG.cpp
new file mode 100644
index 0000000000..0fb53d9938
--- /dev/null
+++ b/aconversions/src/re2rg/re2rrg/GlushkovRRG.cpp
@@ -0,0 +1,148 @@
+/*
+ * GlushkovRRG.cpp
+ *
+ *  Created on: 11. 1. 2014
+ *      Author: tomas
+ */
+
+#include "GlushkovRRG.h"
+
+using namespace alib;
+using namespace alphabet;
+using namespace grammar;
+using namespace regexp;
+using namespace std;
+
+namespace conversions
+{
+
+GlushkovRRG::GlushkovRRG( const RegExp & re ) : AbstractREtoRRGConverter( re )
+{
+
+}
+
+GlushkovRRG::~GlushkovRRG( void )
+{
+
+}
+
+RightRegularGrammar GlushkovRRG::convert( void )
+{
+    // step 1
+    initNumberSymbols( );
+
+    for( const auto & symbol : RegExpAlphabet::getSymbols( m_re ) )
+        m_grammar.addTerminalSymbol( symbol.getSymbol( ) );
+
+    // steps 2, 3, 4
+    constructBeginSymbolSet( );
+    constructEndSymbolSet( );
+    constructNeighbourSymbolSet( );
+        // \e in q0 check is in step 7
+
+    // step 5
+    Symbol S = m_grammar.createUniqueNonTerminalSymbol( "S" );
+    m_grammar.setStartSymbol( S );
+
+    //for( const auto & kv : m_numberedSymbols )
+        //m_grammar.createUniqueNonTerminalSymbol( kv.second.m_nonTerminal );
+
+    // step 6
+    for( const auto & ns : m_beginSymbolSet )
+    {
+        list<Symbol> leftSide = { S };
+        list<Symbol> rightSide = { ns.m_alphabetSymbol, ns.m_nonTerminal };
+        m_grammar.addRule( Rule( leftSide, rightSide ) );
+    }
+
+    for( const auto & ns : m_neighbourSymbolSet )
+    {
+        const NumberedSymbol & first  = m_numberedSymbols.find( ns.m_first )->second;
+        const NumberedSymbol & second = m_numberedSymbols.find( ns.m_second )->second;
+
+        list<Symbol> leftSide = { first.m_nonTerminal };
+        list<Symbol> rightSide = { second.m_alphabetSymbol, second.m_nonTerminal };
+
+        m_grammar.addRule( Rule( leftSide, rightSide ) );
+    }
+
+    // step 7
+    for( const auto & ns : m_endSymbolSet )
+    {
+        /*
+         * for all rules where ns.m_nonTerminal is on rightSide:
+         *  add Rule: leftSide -> ns.m_alphabetSymbol
+         *  unless it already exists
+         */
+
+        for( const auto & rule : m_grammar.getRules( ) )
+        {
+            if( isInList( ns.m_nonTerminal, rule.getRightSide( ) ) )
+            {
+                list<Symbol> leftSide = rule.getLeftSide( );
+                list<Symbol> rightSide = { ns.m_alphabetSymbol };
+                Rule r( leftSide, rightSide );
+                if( ! isInSet( r, m_grammar.getRules( ) ) )
+                    m_grammar.addRule( r );
+            }
+        }
+    }
+
+    if( m_re.containsEmptyString( ) )
+    {
+        list<Symbol> leftSide = { S };
+        list<Symbol> rightSide = { };
+        m_grammar.addRule( Rule( leftSide, rightSide ) );
+    }
+
+    return m_grammar;
+}
+
+void GlushkovRRG::initNumberSymbols( void )
+{
+    int id = 1;
+
+    for( const auto & symb : RegExpAlphabet::getSymbolsListInOrder( m_re ) )
+        m_numberedSymbols.insert( pair<const RegExpSymbol*, NumberedSymbol>( symb, NumberedSymbol( symb, m_grammar, id ++ ) ) );
+}
+
+// ----------------------------------------------------------------------------
+
+void GlushkovRRG::constructBeginSymbolSet( void )
+{
+    for( const auto & s : GlushkovTraversal::getLeftmostSymbolsInTree( m_re ) )
+        m_beginSymbolSet.insert( m_numberedSymbols.find( s )->second );
+}
+
+void GlushkovRRG::constructEndSymbolSet( void )
+{
+    for( const auto & s : GlushkovTraversal::getRightmostSymbolsInTree( m_re ) )
+        m_endSymbolSet.insert( m_numberedSymbols.find( s )->second );
+}
+
+void GlushkovRRG::constructNeighbourSymbolSet( void )
+{
+    for( const auto & n : GlushkovTraversal::getNeighbours( m_re ) )
+        m_neighbourSymbolSet.insert( n );
+}
+
+// ----------------------------------------------------------------------------
+
+bool GlushkovRRG::NumberedSymbol::operator<( const NumberedSymbol & x ) const
+{
+    return m_i < x.m_i;
+}
+
+GlushkovRRG::NumberedSymbol::NumberedSymbol( const RegExpSymbol * symbol, grammar::RightRegularGrammar & g, int i ) :
+        m_i( i ),
+        m_alphabetSymbol( symbol->getSymbol( ) ),
+        m_nonTerminal( g.createUniqueNonTerminalSymbol( "["     + m_alphabetSymbol.getSymbol( ) + "], id " + to_string( m_i ), false ) )
+{
+
+}
+
+// ----------------------------------------------------------------------------
+
+
+
+} /* namespace conversions */
diff --git a/aconversions/src/re2rg/re2rrg/GlushkovRRG.h b/aconversions/src/re2rg/re2rrg/GlushkovRRG.h
new file mode 100644
index 0000000000..82c4ba6ed1
--- /dev/null
+++ b/aconversions/src/re2rg/re2rrg/GlushkovRRG.h
@@ -0,0 +1,55 @@
+/*
+ * GlushkovRRG.h
+ *
+ *  Created on: 11. 1. 2014
+ *      Author: tomas
+ */
+
+#ifndef GLUSHKOVRRG_H_
+#define GLUSHKOVRRG_H_
+
+#include <map>
+
+#include <grammar/Regular/RightRegularGrammar.h>
+#include <regexp/RegExp.h>
+
+#include "../../shared/GlushkovTraversal.h"
+#include "AbstractREtoRRGConverter.h"
+
+#include "RegExpAlphabet.h"
+
+namespace conversions
+{
+
+class GlushkovRRG : public AbstractREtoRRGConverter
+{
+public:
+    GlushkovRRG( const regexp::RegExp & re );
+    ~GlushkovRRG( void );
+    grammar::RightRegularGrammar convert( void );
+
+private:
+    struct NumberedSymbol
+    {
+        const int m_i;
+        const alphabet::Symbol m_alphabetSymbol;
+        const alphabet::Symbol m_nonTerminal;
+
+        NumberedSymbol( const regexp::RegExpSymbol * symb, grammar::RightRegularGrammar & rrg, int i );
+        bool operator<( const NumberedSymbol & x ) const;
+    };
+
+    void initNumberSymbols( void );
+    void constructBeginSymbolSet( void );
+    void constructEndSymbolSet( void );
+    void constructNeighbourSymbolSet( void );
+
+    std::map<const regexp::RegExpElement*, NumberedSymbol> m_numberedSymbols;
+    std::set<NumberedSymbol> m_beginSymbolSet, m_endSymbolSet;
+    std::set<GlushkovTraversal::Neighbours> m_neighbourSymbolSet;
+
+};
+
+} /* namespace conversions */
+
+#endif /* GLUSHKOVRRG_H_ */
diff --git a/aconversions/src/shared/GlushkovTraversal.cpp b/aconversions/src/shared/GlushkovTraversal.cpp
new file mode 100644
index 0000000000..d9971752ca
--- /dev/null
+++ b/aconversions/src/shared/GlushkovTraversal.cpp
@@ -0,0 +1,296 @@
+/*
+ * GlushkovTraversal.cpp
+ *
+ *  Created on: 13. 3. 2014
+ *      Author: tomas
+ */
+
+#include "GlushkovTraversal.h"
+
+using namespace alib;
+using namespace regexp;
+using namespace std;
+
+namespace conversions
+{
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const RegExp & re )
+{
+    return getLeftmostSymbolsInTree( re.getRegExp( ) );
+
+}
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const RegExp & re )
+{
+    return getRightmostSymbolsInTree( re.getRegExp( ) );
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const RegExp & re )
+{
+    return getNeighbours( re.getRegExp( ) );
+}
+
+// -----------------------------------------------------------------------------
+
+GlushkovTraversal::Neighbours::Neighbours( const RegExpSymbol * first, const RegExpSymbol * second ) :
+        m_first( first ),
+        m_second( second )
+{
+
+}
+
+bool GlushkovTraversal::Neighbours::operator<( const Neighbours & x ) const
+{
+    if( m_first != x.m_first )
+        return m_first < x.m_first;
+    else
+        return m_second < x.m_second;
+}
+
+// -----------------------------------------------------------------------------
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const RegExpElement * node )
+{
+    const Alternation* alternation = dynamic_cast<const Alternation*>( node );
+    const Concatenation* concatenation = dynamic_cast<const Concatenation*>( node );
+    const Iteration* iteration = dynamic_cast<const Iteration*>( node );
+    const RegExpSymbol* symbol = dynamic_cast<const RegExpSymbol*>( node );
+    const RegExpEmpty* empty = dynamic_cast<const RegExpEmpty*>( node );
+    const RegExpEpsilon* eps = dynamic_cast<const RegExpEpsilon*>( node );
+
+    if( symbol )
+        return getLeftmostSymbolsInTree( symbol );
+    else if( alternation )
+        return getLeftmostSymbolsInTree( alternation );
+    else if( concatenation )
+        return getLeftmostSymbolsInTree( concatenation );
+    else if( iteration )
+        return getLeftmostSymbolsInTree( iteration );
+    else if( eps )
+        return getLeftmostSymbolsInTree( eps );
+    else if( empty )
+        return getLeftmostSymbolsInTree( empty );
+
+     throw AlibException( "GlushkovTraversal::getLeftmostSymbolsInTree - invalid RegExpElement node" );
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const Alternation * node )
+{
+    set<const RegExpSymbol*> ret;
+
+    for( const auto & e : node->getElements( ) )
+    {
+        const set<const RegExpSymbol*> tmp = getLeftmostSymbolsInTree( e );
+        ret.insert( tmp.begin( ), tmp.end( ) );
+    }
+
+    return ret;
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const Concatenation * node )
+{
+    set<const RegExpSymbol*> ret;
+
+    for( const auto & e : node->getElements( ) )
+    {
+        set<const RegExpSymbol*> tmp = getLeftmostSymbolsInTree( e );
+        ret.insert( tmp.begin( ), tmp.end( ) );
+
+        if( ! e->containsEmptyString( ) ) // If this subtree can be epsilon, then we need to add next subtree also
+            break;
+    }
+
+    return ret;
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const Iteration * node )
+{
+    return getLeftmostSymbolsInTree( node->getElement( ) );
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const RegExpSymbol * node )
+{
+    return set<const RegExpSymbol*> { node };
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const RegExpEpsilon * node )
+{
+    return set<const RegExpSymbol*>( );
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getLeftmostSymbolsInTree( const RegExpEmpty * node )
+{
+    return set<const RegExpSymbol*>( );
+}
+// ----------------------------------------------------------------------------
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const RegExpElement * node )
+{
+    const Alternation* alternation = dynamic_cast<const Alternation*>( node );
+    const Concatenation* concatenation = dynamic_cast<const Concatenation*>( node );
+    const Iteration* iteration = dynamic_cast<const Iteration*>( node );
+    const RegExpSymbol* symbol = dynamic_cast<const RegExpSymbol*>( node );
+    const RegExpEmpty* empty = dynamic_cast<const RegExpEmpty*>( node );
+    const RegExpEpsilon* eps = dynamic_cast<const RegExpEpsilon*>( node );
+
+    if( symbol )
+        return getRightmostSymbolsInTree( symbol );
+    else if( alternation )
+        return getRightmostSymbolsInTree( alternation );
+    else if( concatenation )
+        return getRightmostSymbolsInTree( concatenation );
+    else if( iteration )
+        return getRightmostSymbolsInTree( iteration );
+    else if( eps )
+        return getRightmostSymbolsInTree( eps );
+    else if( empty )
+        return getRightmostSymbolsInTree( empty );
+
+     throw AlibException( "GlushkovTraversal::getRightmostSymbolsInTree - invalid RegExpElement node" );
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const Alternation * node )
+{
+    set<const RegExpSymbol*> ret;
+
+    for( const auto & e : node->getElements( ) )
+    {
+        set<const RegExpSymbol*> tmp = getRightmostSymbolsInTree( e );
+        ret.insert( tmp.begin( ), tmp.end( ) );
+    }
+
+    return ret;
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const Concatenation * node )
+{
+    set<const RegExpSymbol*> ret;
+
+    for( auto it = node->getElements( ).rbegin( ); it != node->getElements( ).rend( ) ; it ++ )
+    {
+        set<const RegExpSymbol*> tmp = getRightmostSymbolsInTree( *it );
+        ret.insert( tmp.begin( ), tmp.end( ) );
+
+        if( ! ( * it )->containsEmptyString( ) )
+            break;
+    }
+
+    return ret;
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const Iteration * node )
+{
+    return getRightmostSymbolsInTree( node->getElement( ) );
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const RegExpSymbol * node )
+{
+    return set<const RegExpSymbol*> { node };
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const RegExpEpsilon * node )
+{
+    return set<const RegExpSymbol*>( );
+}
+
+set<const RegExpSymbol*> GlushkovTraversal::getRightmostSymbolsInTree( const RegExpEmpty * node )
+{
+    return set<const RegExpSymbol*>( );
+}
+
+// ----------------------------------------------------------------------------
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const RegExpElement * node )
+{
+    const Alternation* alternation = dynamic_cast<const Alternation*>( node );
+    const Concatenation* concatenation = dynamic_cast<const Concatenation*>( node );
+    const Iteration* iteration = dynamic_cast<const Iteration*>( node );
+    const RegExpSymbol* symbol = dynamic_cast<const RegExpSymbol*>( node );
+    const RegExpEmpty* empty = dynamic_cast<const RegExpEmpty*>( node );
+    const RegExpEpsilon* eps = dynamic_cast<const RegExpEpsilon*>( node );
+
+    if( symbol )
+        return getNeighbours( symbol );
+    else if( alternation )
+        return getNeighbours( alternation );
+    else if( concatenation )
+        return getNeighbours( concatenation );
+    else if( iteration )
+        return getNeighbours( iteration );
+    else if( eps )
+        return getNeighbours( eps );
+    else if( empty )
+        return getNeighbours( empty );
+
+     throw AlibException( "GlushkovTraversal::getNeighbours - unknown RegExpElement* " );
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const Alternation * node )
+{
+    set<Neighbours> n;
+    for( const auto & e : node->getElements( ) )
+    {
+        set<Neighbours> tmp = getNeighbours( e );
+        n.insert( tmp.begin( ), tmp.end( ) );
+    }
+
+    return n;
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const Concatenation * node )
+{
+    set<Neighbours> n;
+    for( const auto & e : node->getElements( ) )
+    {
+        set<Neighbours> tmp = getNeighbours( e );
+        n.insert( tmp.begin( ), tmp.end( ) );
+    }
+
+    for( auto e = node->getElements( ).begin( ); e != node->getElements( ).end( ); e ++ )
+    {
+        auto f = e;
+        if( f == node->getElements( ).end( ) )
+            continue;
+
+        for( f++ ; f != node->getElements( ).end( ); f ++ )
+        {
+            for( const auto & x : getRightmostSymbolsInTree( * e ) )
+                for( const auto & y : getLeftmostSymbolsInTree( * f ) )
+                    n.insert( Neighbours( x, y ) );
+
+            if( ! ( * f )->containsEmptyString( ) )
+                break;
+        }
+    }
+
+    return n;
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const Iteration * node )
+{
+    set<Neighbours> n;
+    set<Neighbours> tmp = getNeighbours( node->getElement( ) );
+    n.insert( tmp.begin( ), tmp.end( ) );
+
+    for( const auto & x : getRightmostSymbolsInTree( node->getElement( ) ) )
+        for( const auto & y : getLeftmostSymbolsInTree( node->getElement( ) ) )
+            n.insert( Neighbours( x, y ) );
+
+    return n;
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const RegExpSymbol * node )
+{
+    return set<Neighbours>( );
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const RegExpEpsilon * node )
+{
+    return set<Neighbours>( );
+}
+
+set<GlushkovTraversal::Neighbours> GlushkovTraversal::getNeighbours( const RegExpEmpty * node )
+{
+    return set<Neighbours>( );
+}
+
+} /* namespace conversions */
diff --git a/aconversions/src/shared/GlushkovTraversal.h b/aconversions/src/shared/GlushkovTraversal.h
new file mode 100644
index 0000000000..cf2ff3d4a1
--- /dev/null
+++ b/aconversions/src/shared/GlushkovTraversal.h
@@ -0,0 +1,70 @@
+/*
+ * GlushkovTraversal.h
+ *
+ *  Created on: 13. 3. 2014
+ *      Author: tomas
+ */
+
+#ifndef GLUSHKOVTRAVERSAL_H_
+#define GLUSHKOVTRAVERSAL_H_
+
+#include <set>
+
+#include <regexp/RegExp.h>
+#include <regexp/RegExpElement.h>
+#include <regexp/Alternation.h>
+#include <regexp/Concatenation.h>
+#include <regexp/Iteration.h>
+#include <regexp/RegExpSymbol.h>
+#include <regexp/RegExpEmpty.h>
+#include <regexp/RegExpEpsilon.h>
+
+#include <AlibException.h>
+
+namespace conversions
+{
+
+class GlushkovTraversal
+{
+public:
+    struct Neighbours
+    {
+        const regexp::RegExpSymbol * m_first, * m_second;
+
+        Neighbours( const regexp::RegExpSymbol * first, const regexp::RegExpSymbol * second );
+        bool operator<( const Neighbours & x ) const;
+    };
+
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::RegExp & re );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::RegExp & re );
+    static std::set<Neighbours> getNeighbours( const regexp::RegExp & re );
+
+private:
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::RegExpElement * node );
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::Alternation * node );
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::Concatenation * node );
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::Iteration * node );
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::RegExpSymbol * node );
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::RegExpEmpty * node );
+    static std::set<const regexp::RegExpSymbol*> getLeftmostSymbolsInTree( const regexp::RegExpEpsilon * node );
+
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::RegExpElement * node );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::Alternation * node );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::Concatenation * node );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::Iteration * node );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::RegExpSymbol * node );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::RegExpEmpty * node );
+    static std::set<const regexp::RegExpSymbol*> getRightmostSymbolsInTree( const regexp::RegExpEpsilon * node );
+
+    static std::set<Neighbours> getNeighbours( const regexp::RegExpElement * node );
+    static std::set<Neighbours> getNeighbours( const regexp::Alternation * node );
+    static std::set<Neighbours> getNeighbours( const regexp::Concatenation * node );
+    static std::set<Neighbours> getNeighbours( const regexp::Iteration * node );
+    static std::set<Neighbours> getNeighbours( const regexp::RegExpSymbol * node );
+    static std::set<Neighbours> getNeighbours( const regexp::RegExpEmpty * node );
+    static std::set<Neighbours> getNeighbours( const regexp::RegExpEpsilon * node );
+};
+
+} /* namespace conversions */
+
+#endif /* GLUSHKOVTRAVERSAL_H_ */
-- 
GitLab