From 472ae8cf376e7b6cf13f92480772cb419e0cdd36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <peckato1@fit.cvut.cz>
Date: Sat, 15 Mar 2014 23:20:12 +0100
Subject: [PATCH] Closes #14: mapping automata state to nonterminal.

---
 .../src/fa2rg/AbstractFAtoRGConverter.cpp     |  9 +--
 .../src/fa2rg/AbstractFAtoRGConverter.h       |  5 +-
 .../src/fa2rg/StateNonterminalMap.cpp         | 56 +++++++++++++++++++
 aconversions/src/fa2rg/StateNonterminalMap.h  | 43 ++++++++++++++
 .../src/fa2rg/fa2lrg/FAtoLRGConverter.cpp     | 16 +++---
 .../src/fa2rg/fa2rrg/FAtoRRGConverter.cpp     | 18 +++---
 6 files changed, 121 insertions(+), 26 deletions(-)
 create mode 100644 aconversions/src/fa2rg/StateNonterminalMap.cpp
 create mode 100644 aconversions/src/fa2rg/StateNonterminalMap.h

diff --git a/aconversions/src/fa2rg/AbstractFAtoRGConverter.cpp b/aconversions/src/fa2rg/AbstractFAtoRGConverter.cpp
index 0f457e2fb8..dedff158fe 100644
--- a/aconversions/src/fa2rg/AbstractFAtoRGConverter.cpp
+++ b/aconversions/src/fa2rg/AbstractFAtoRGConverter.cpp
@@ -20,16 +20,9 @@ AbstractFAtoRGConverter::AbstractFAtoRGConverter( const FSM & fsm ) : m_fsm( fsm
         throw AlibException( "FSM has epsilon transitions" );
 }
 
-void AbstractFAtoRGConverter::createNonTerminalSymbols( RegularGrammar & rg ) const
+AbstractFAtoRGConverter::~AbstractFAtoRGConverter( void )
 {
-    for( const auto & state : m_fsm.getStates( ) )
-        rg.addNonTerminalSymbol( Symbol( state.getName( ) ) );
-}
 
-void AbstractFAtoRGConverter::createTerminalSymbols( RegularGrammar & rg ) const
-{
-    for( const auto & symbol : m_fsm.getInputAlphabet( ) )
-        rg.addTerminalSymbol( symbol );
 }
 
 } /* namespace conversions */
diff --git a/aconversions/src/fa2rg/AbstractFAtoRGConverter.h b/aconversions/src/fa2rg/AbstractFAtoRGConverter.h
index 495c1b5081..796e1fa84c 100644
--- a/aconversions/src/fa2rg/AbstractFAtoRGConverter.h
+++ b/aconversions/src/fa2rg/AbstractFAtoRGConverter.h
@@ -13,6 +13,7 @@
 #include <AlibException.h>
 
 #include "../abstract/Conversion.h"
+#include "StateNonterminalMap.h"
 
 namespace conversions
 {
@@ -21,12 +22,10 @@ class AbstractFAtoRGConverter : public Conversion
 {
 public:
     AbstractFAtoRGConverter( const automaton::FSM & fsm );
+    ~AbstractFAtoRGConverter( void );
 
 protected:
     const automaton::FSM & m_fsm;
-
-    void createNonTerminalSymbols( grammar::RegularGrammar & grammar ) const;
-    void createTerminalSymbols( grammar::RegularGrammar & grammar ) const;
 };
 
 } /* namespace conversions */
diff --git a/aconversions/src/fa2rg/StateNonterminalMap.cpp b/aconversions/src/fa2rg/StateNonterminalMap.cpp
new file mode 100644
index 0000000000..0926708092
--- /dev/null
+++ b/aconversions/src/fa2rg/StateNonterminalMap.cpp
@@ -0,0 +1,56 @@
+/*
+ * StateNonterminalMap.cpp
+ *
+ *  Created on: 15. 3. 2014
+ *      Author: tomas
+ */
+
+#include "StateNonterminalMap.h"
+
+using namespace alib;
+using namespace alphabet;
+using namespace automaton;
+using namespace grammar;
+
+namespace conversions
+{
+
+StateNonterminalMap::StateNonterminalMap( const FSM & fsm, RegularGrammar & grammar ) :
+        m_fsm( fsm ),
+        m_grammar( grammar )
+{
+    initMap( );
+}
+
+const Symbol & StateNonterminalMap::getNonTerminal( const State & state )
+{
+    auto it = m_map.find( state );
+
+    // probably harmless to return reference to object stored in map
+    if( it != m_map.end( ) )
+        return it->second;
+
+
+    // oops automata might have changed
+    // who the hell edits automata in process of converting to grammar?
+    if( isInSet( state, m_fsm.getStates( ) ) )
+    {
+        Symbol nonTerminal = m_grammar.createUniqueNonTerminalSymbol( state.getName( ), false );
+        m_map.insert( make_pair( state, nonTerminal ) );
+        return m_map.find( state )->second;
+    }
+
+
+    throw AlibException( "No nonterminal for this state! Should not happen unless you manipulated with automata after initialize mapper initialize." );
+}
+
+void StateNonterminalMap::initMap( void )
+{
+    for( const auto & state : m_fsm.getStates( ) )
+    {
+        Symbol nonTerminal = m_grammar.createUniqueNonTerminalSymbol( state.getName( ), false );
+        m_map.insert( make_pair( state, nonTerminal ) );
+    }
+}
+
+} /* namespace conversions */
diff --git a/aconversions/src/fa2rg/StateNonterminalMap.h b/aconversions/src/fa2rg/StateNonterminalMap.h
new file mode 100644
index 0000000000..799491e757
--- /dev/null
+++ b/aconversions/src/fa2rg/StateNonterminalMap.h
@@ -0,0 +1,43 @@
+/*
+ * StateNonterminalMap.h
+ *
+ *  Created on: 15. 3. 2014
+ *      Author: tomas
+ */
+
+#ifndef STATENONTERMINALMAP_H_
+#define STATENONTERMINALMAP_H_
+
+#include <map>
+
+#include <automaton/FSM/FSM.h>
+#include <grammar/Regular/RegularGrammar.h>
+#include <AlibException.h>
+
+#include "../include/macros.h"
+
+namespace conversions
+{
+
+class StateNonterminalMap
+{
+public:
+    StateNonterminalMap( const automaton::FSM & fsm, grammar::RegularGrammar & grammar );
+    const alphabet::Symbol & getNonTerminal( const automaton::State & state );
+
+private:
+    void initMap( void );
+
+    /**
+     * Maps automaton's state to grammar's Symbol
+     */
+    std::map<const automaton::State, const alphabet::Symbol> m_map;
+
+    const automaton::FSM & m_fsm;
+    grammar::RegularGrammar & m_grammar;
+
+};
+
+} /* namespace conversions */
+
+#endif /* STATENONTERMINALMAP_H_ */
diff --git a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp b/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp
index b99349a96f..7512a2c52f 100644
--- a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp
+++ b/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp
@@ -19,25 +19,27 @@ FAtoLRGConverter::~FAtoLRGConverter( void )
 
 LeftRegularGrammar FAtoLRGConverter::convert( void )
 {
-    createTerminalSymbols( m_grammar );
-    createNonTerminalSymbols( m_grammar );
+    for( const auto & symbol : m_fsm.getInputAlphabet( ) )
+        m_grammar.addTerminalSymbol( symbol );
+
+    StateNonterminalMap symbolMap( m_fsm, m_grammar );
 
     // step 2 - create set of P in G
     for( const auto & transition : m_fsm.getTransitions( ) )
     {
         // 2a
         list<Symbol> leftSide, rightSide;
-        leftSide.push_back( Symbol( transition.getTo( ).getName( ) ) );
-        rightSide.push_back( Symbol( transition.getFrom( ).getName( ) ) );
-        rightSide.push_back( Symbol( transition.getInput( ).getSymbol( ) ) );
+        leftSide.push_back( symbolMap.getNonTerminal( transition.getTo( ) ) );
+        rightSide.push_back( symbolMap.getNonTerminal( transition.getFrom( ) ) );
+        rightSide.push_back( transition.getInput( ) );
         m_grammar.addRule( Rule( leftSide, rightSide ) );
 
         // 2b
         if( isInSet( transition.getFrom( ), m_fsm.getInitialStates( ) ) )
         {
             list<Symbol> leftSide, rightSide;
-            leftSide.push_back( Symbol( transition.getTo( ).getName( ) ) );
-            rightSide.push_back( Symbol( transition.getInput( ).getSymbol( ) ) );
+            leftSide.push_back( symbolMap.getNonTerminal( transition.getTo( ) ) );
+            rightSide.push_back( transition.getInput( ) );
             m_grammar.addRule( Rule( leftSide, rightSide ) );
         }
     }
diff --git a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp b/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp
index 59ecc0d1d6..30fc37d17d 100644
--- a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp
+++ b/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp
@@ -19,31 +19,33 @@ FAtoRRGConverter::~FAtoRRGConverter( void )
 
 RightRegularGrammar FAtoRRGConverter::convert( void )
 {
-    createTerminalSymbols( m_grammar );
-    createNonTerminalSymbols( m_grammar );
+    for( const auto & symbol : m_fsm.getInputAlphabet( ) )
+        m_grammar.addTerminalSymbol( symbol );
+
+    StateNonterminalMap symbolMap( m_fsm, m_grammar );
 
     // step 2 - create set of P in G
     for( const auto & transition : m_fsm.getTransitions( ) )
     {
         // 2a
         list<Symbol> leftSide, rightSide;
-        leftSide.push_back( Symbol( transition.getFrom( ).getName( ) ) );
-        rightSide.push_back( Symbol( transition.getInput( ).getSymbol( ) ) );
-        rightSide.push_back( Symbol( transition.getTo( ).getName( ) ) );
+        leftSide.push_back( symbolMap.getNonTerminal( transition.getFrom( ) ) );
+        rightSide.push_back( transition.getInput( ) );
+        rightSide.push_back( symbolMap.getNonTerminal( transition.getTo( ) ) );
         m_grammar.addRule( Rule( leftSide, rightSide ) );
 
         // 2b
         if( isInSet( transition.getTo( ), m_fsm.getFinalStates( ) ) )
         {
             list<Symbol> leftSide, rightSide;
-            leftSide.push_back( Symbol( transition.getFrom( ).getName( ) ) );
-            rightSide.push_back( Symbol( transition.getInput( ).getSymbol( ) ) );
+            leftSide.push_back( symbolMap.getNonTerminal( transition.getFrom( ) ) );
+            rightSide.push_back( transition.getInput( ) );
             m_grammar.addRule( Rule( leftSide, rightSide ) );
         }
     }
 
     // step 3 - set start symbol of G
-    m_grammar.setStartSymbol( Symbol( m_fsm.getInitialStates( ).begin( )->getName( ) ) );
+    m_grammar.setStartSymbol( symbolMap.getNonTerminal( * m_fsm.getInitialStates( ).begin( ) ) );
 
     // step 4
     if( isInSet( State( m_grammar.getStartSymbol( ).getSymbol( ) ), m_fsm.getFinalStates( ) ) )
-- 
GitLab